summaryrefslogtreecommitdiff
path: root/source3/smbd/dnsregister.c
diff options
context:
space:
mode:
authorRishi Srivatsavai <rishisv@gmail.com>2007-12-13 20:56:29 -0800
committerJames Peach <jpeach@samba.org>2007-12-13 20:56:29 -0800
commit12ac4c3119b3b7712e670d95d61413d97ecafaef (patch)
tree67a8dad20a20d9bbbfb54b325b46f671fd61f824 /source3/smbd/dnsregister.c
parent819a74ed8f1d2b312a22cc803235aaece0e24697 (diff)
downloadsamba-12ac4c3119b3b7712e670d95d61413d97ecafaef.tar.gz
samba-12ac4c3119b3b7712e670d95d61413d97ecafaef.tar.bz2
samba-12ac4c3119b3b7712e670d95d61413d97ecafaef.zip
Register the smb service with mDNS if mSDN is supported.
If mDNS is supported, attempt to register the first port we are listening on for the _smb._tcp service. This provides more reliable service discovery than NetBIOS browsing. (This used to be commit 1e7241517d1f55d60af22570e0c9feb280e3fdb5)
Diffstat (limited to 'source3/smbd/dnsregister.c')
-rw-r--r--source3/smbd/dnsregister.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c
new file mode 100644
index 0000000000..fcd97b5dab
--- /dev/null
+++ b/source3/smbd/dnsregister.c
@@ -0,0 +1,212 @@
+/*
+ Unix SMB/CIFS implementation.
+ DNS-SD registration
+ Copyright (C) Rishi Srivatsavai 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <includes.h>
+#include <dns_sd.h>
+
+/* Uses DNS service discovery (libdns_sd) to
+ * register the SMB service. SMB service is registered
+ * on ".local" domain via Multicast DNS & any
+ * other unicast DNS domains available.
+ *
+ * Users use the smbclient -B (Browse) option to
+ * browse for advertised SMB services.
+ */
+
+#define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */
+
+struct dns_reg_state {
+ DNSServiceRef srv_ref;
+ struct timed_event *retry_handler;
+};
+
+#ifdef WITH_DNSSD_SUPPORT
+
+void dns_register_close(struct dns_reg_state **dns_state_ptr)
+{
+ int mdnsd_conn_fd;
+ struct dns_reg_state *dns_state = *dns_state_ptr;
+
+ if (dns_state == NULL) {
+ return;
+ }
+
+ if (dns_state->srv_ref != NULL) {
+ /* Close connection to the mDNS daemon */
+ DNSServiceRefDeallocate(dns_state->srv_ref);
+ dns_state->srv_ref = NULL;
+ }
+
+ /* Clear event handler */
+ if (dns_state->retry_handler != NULL) {
+ TALLOC_FREE(dns_state->retry_handler);
+ dns_state->retry_handler = NULL;
+ }
+
+ talloc_free(dns_state);
+ *dns_state_ptr = NULL;
+}
+
+static void dns_register_smbd_retry(struct event_context *ctx,
+ struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data;
+
+ /* Clear previous registration state to force new
+ * registration attempt. Clears event handler.
+ */
+ dns_register_close(dns_state);
+}
+
+static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state,
+ struct timeval *timeout)
+{
+ struct timed_event * event;
+
+ dns_state->srv_ref = NULL;
+ event= event_add_timed(smbd_event_context(),
+ NULL,
+ timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0),
+ "DNS registration handler",
+ dns_register_smbd_retry,
+ dns_state);
+
+ dns_state->retry_handler = event;
+ get_timed_events_timeout(smbd_event_context(), timeout);
+}
+
+/* Kick off a mDNS request to register the "_smb._tcp" on the specified port.
+ * We really ought to register on all the ports we are listening on. This will
+ * have to be an exercise for some-one who knows the DNS registration API a bit
+ * better.
+ */
+void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
+ unsigned port,
+ int *maxfd,
+ fd_set *listen_set,
+ struct timeval *timeout)
+{
+ int mdnsd_conn_fd;
+ DNSServiceErrorType err;
+ struct dns_reg_state *dns_state = *dns_state_ptr;
+
+ if (dns_state == NULL) {
+ *dns_state_ptr = dns_state = talloc(NULL, struct dns_reg_state);
+ if (dns_state == NULL) {
+ return;
+ }
+ }
+
+ /* Quit if a re-try attempt has been scheduled. */
+ if (dns_state->retry_handler != NULL) {
+ return;
+ }
+
+ /* If a registration is active add conn
+ * fd to select listen_set and return
+ */
+ if (dns_state->srv_ref != NULL) {
+ mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
+ FD_SET(mdnsd_conn_fd, listen_set);
+ return;
+ }
+
+ DEBUG(6, ("registering _smb._tcp service on port %d\n", port));
+
+ /* Register service with DNS. Connects with the mDNS
+ * daemon running on the local system to perform DNS
+ * service registration.
+ */
+ err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */,
+ kDNSServiceInterfaceIndexAny,
+ NULL /* service name */,
+ "_smb._tcp" /* service type */,
+ NULL /* domain */,
+ "" /* SRV target host name */,
+ htons(port),
+ 0 /* TXT record len */,
+ NULL /* TXT record data */,
+ NULL /* callback func */,
+ NULL /* callback context */);
+
+ if (err != kDNSServiceErr_NoError) {
+ /* Failed to register service. Schedule a re-try attempt.
+ */
+ DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
+ schedule_dns_register_smbd_retry(dns_state, timeout);
+ return;
+ }
+
+ mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
+ FD_SET(mdnsd_conn_fd, listen_set);
+ *maxfd = MAX(*maxfd, mdnsd_conn_fd);
+ *timeout = timeval_zero();
+
+}
+
+/* Processes reply from mDNS daemon. Returns true if a reply was received */
+bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
+ fd_set *lfds, struct timeval *timeout)
+{
+ int mdnsd_conn_fd = -1;
+
+ if (dns_state->srv_ref == NULL) {
+ return false;
+ }
+
+ mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
+
+ /* Process reply from daemon. Handles any errors. */
+ if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) {
+ DNSServiceErrorType err;
+
+ err = DNSServiceProcessResult(dns_state->srv_ref);
+ if (err != kDNSServiceErr_NoError) {
+ DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
+ err));
+ schedule_dns_register_smbd_retry(dns_state, timeout);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+#else /* WITH_DNSSD_SUPPORT */
+
+ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
+ unsigned port,
+ int *maxfd,
+ fd_set *listen_set,
+ struct timeval *timeout)
+{}
+
+ void dns_register_close(struct dns_reg_state ** dns_state_ptr)
+{}
+
+ bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
+ fd_set *lfds, struct timeval *timeout)
+{
+ return false;
+}
+
+#endif /* WITH_DNSSD_SUPPORT */