The Samba-Bugzilla – Attachment 2934 Details for
Bug 4510
DNS service discovery support in samba
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
service discovery support via DNS
smbdiff (text/plain), 16.97 KB, created by
Rishi Srivatsavai
on 2007-09-30 08:53:06 UTC
(
hide
)
Description:
service discovery support via DNS
Filename:
MIME Type:
Creator:
Rishi Srivatsavai
Created:
2007-09-30 08:53:06 UTC
Size:
16.97 KB
patch
obsolete
>Index: source/Makefile.in >=================================================================== >--- source/Makefile.in (revision 25440) >+++ source/Makefile.in (working copy) >@@ -63,6 +63,7 @@ > LDAP_LIBS=@LDAP_LIBS@ > NSCD_LIBS=@NSCD_LIBS@ > UUID_LIBS=@UUID_LIBS@ >+DNSSD_LIBS=@DNSSD_LIBS@ > > INSTALLCMD=@INSTALL@ > INSTALLLIBCMD_SH=@INSTALLLIBCMD_SH@ >@@ -651,7 +652,7 @@ > $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ > $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(LDB_OBJ) > >-CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_pipe.o \ >+CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_pipe.o client/dnsbrowse.o \ > $(RPC_CLIENT_OBJ1) \ > $(RPC_PARSE_OBJ2) > >@@ -1148,7 +1149,8 @@ > @echo Linking $@ > @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \ > $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \ >- $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ @SMBD_LIBS@ >+ $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ \ >+ $(DNSSD_LIBS) @SMBD_LIBS@ > > bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@ > @echo Linking $@ >@@ -1167,7 +1169,7 @@ > > bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ > @echo Linking $@ >- @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) >+ @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) $(DNSSD_LIBS) > > bin/smbctool@EXEEXT@: $(BINARY_PREREQS) $(TOOL_OBJ) @BUILD_POPT@ > @echo Linking $@ >Index: source/smbd/server.c >=================================================================== >--- source/smbd/server.c (revision 25440) >+++ source/smbd/server.c (working copy) >@@ -5,6 +5,7 @@ > Copyright (C) Martin Pool 2002 > Copyright (C) Jelmer Vernooij 2002-2003 > Copyright (C) James Peach 2007 >+ 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 >@@ -315,16 +316,139 @@ > return num_children < max_processes; > } > >+ >+#ifdef HAVE_LIBDNS_SD >+ >+/* 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. >+ */ >+ >+static void dns_register_close(struct dns_reg_state *regstateptr) >+{ >+ int mdnsd_conn_fd; >+ >+ if (regstateptr == NULL) >+ return; >+ >+ if (regstateptr->regsrvref != NULL) { >+ /* Close connection to the mDNS daemon */ >+ DNSServiceRefDeallocate(regstateptr->regsrvref); >+ regstateptr->regsrvref = NULL; >+ } >+ >+ /* Clear event handler */ >+ if (regstateptr->dnsregretryhandler != NULL) { >+ TALLOC_FREE(regstateptr->dnsregretryhandler); >+ regstateptr->dnsregretryhandler = 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 *regstateptr = (struct dns_reg_state *)private_data; >+ /* Clear previous registration state to force new >+ * registration attempt. Clears event handler. */ >+ dns_register_close(regstateptr); >+} >+ >+static void schedule_dns_register_smbd_retry(struct dns_reg_state *regstateptr, >+ struct timeval *timeout) >+{ >+ regstateptr->regsrvref = NULL; >+ regstateptr->dnsregretryhandler = event_add_timed( >+ smbd_event_context(), >+ NULL, timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0), >+ "DNS registration handler", >+ dns_register_smbd_retry, regstateptr); >+ get_timed_events_timeout(smbd_event_context(), timeout); >+} >+ >+ >+ >+static void dns_register_smbd(struct dns_reg_state *regstateptr, int *maxfd, >+ fd_set *listen_set, struct timeval *timeout) >+{ >+ int mdnsd_conn_fd; >+ >+ /* Quit if a re-try attempt has been scheduled. */ >+ if (regstateptr->dnsregretryhandler != NULL) >+ return; >+ >+ /* If a registration is active add conn >+ * fd to select listen_set and return */ >+ if (regstateptr->regsrvref != NULL) { >+ mdnsd_conn_fd = DNSServiceRefSockFD(regstateptr->regsrvref); >+ FD_SET(mdnsd_conn_fd, listen_set); >+ return; >+ } >+ >+ /* Register service with DNS. Connects with the mDNS >+ * daemon running on the local system to perform DNS >+ * service registration. >+ */ >+ if (!DNSServiceRegister(®stateptr->regsrvref, 0, >+ kDNSServiceInterfaceIndexAny, "", "_smb._tcp", "", "", >+ htons(139), 0, NULL, NULL, NULL)) { >+ mdnsd_conn_fd = DNSServiceRefSockFD(regstateptr->regsrvref); >+ FD_SET(mdnsd_conn_fd, listen_set); >+ *maxfd = MAX(*maxfd, mdnsd_conn_fd); >+ *timeout = timeval_zero(); >+ } else { >+ /* Failed to register service. Schedule a re-try attempt. >+ */ >+ DEBUG(3,("dns_sd: could not register with mDNS daemon.\n")); >+ schedule_dns_register_smbd_retry(regstateptr, timeout); >+ } >+} >+ >+/* Processes reply from mDNS daemon. Returns True if a reply was received */ >+static BOOL dns_register_smbd_reply(struct dns_reg_state *regstateptr, >+ fd_set *lfds, struct timeval *timeout) >+{ >+ int mdnsd_conn_fd = -1; >+ >+ if (regstateptr->regsrvref != NULL) { >+ mdnsd_conn_fd = DNSServiceRefSockFD(regstateptr->regsrvref); >+ /* Process reply from daemon. Handles any errors. */ >+ if( (mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd, lfds)) ) { >+ if ( DNSServiceProcessResult(regstateptr->regsrvref) != kDNSServiceErr_NoError) { >+ DEBUG(3,("dns_sd: mdns process result returned error. Keep re-trying.\n")); >+ schedule_dns_register_smbd_retry(regstateptr, timeout); >+ } >+ return True; >+ } >+ } >+ return False; >+} >+ >+#endif /* HAVE_LIBDNS_SD */ >+ >+ > /**************************************************************************** > Are we idle enough that we could safely exit? > ****************************************************************************/ > > static BOOL smbd_is_idle(void) > { >+ if (events_pending(smbd_event_context())) >+ return False; >+ > /* Currently we define "idle" as having no client connections. */ > return count_all_current_connections() == 0; > } > >+ >+ >+ > /**************************************************************************** > Open the socket communication. > ****************************************************************************/ >@@ -339,6 +463,11 @@ > int i; > struct timeval idle_timeout = timeval_zero(); > >+#ifdef HAVE_LIBDNS_SD >+ struct dns_reg_state dnsregptr; >+ (void) memset(&dnsregptr, 0, sizeof(struct dns_reg_state)); >+#endif >+ > if (server_mode == SERVER_MODE_INETD) { > return open_sockets_inetd(); > } >@@ -420,6 +549,10 @@ > FD_ZERO(&w_fds); > GetTimeOfDay(&now); > >+#ifdef HAVE_LIBDNS_SD >+ dns_register_smbd(&dnsregptr, &maxfd, &r_fds, &idle_timeout); >+#endif >+ > event_add_to_select_args(smbd_event_context(), &now, > &r_fds, &w_fds, &idle_timeout, > &maxfd); >@@ -456,6 +589,11 @@ > continue; > } > >+#ifdef HAVE_LIBDNS_SD >+ if (dns_register_smbd_reply(&dnsregptr, &r_fds, &idle_timeout) && ((--num) == 0)) >+ continue; >+#endif >+ > if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) { > continue; > } >@@ -515,6 +653,11 @@ > /* close the listening socket(s) */ > for(i = 0; i < num_sockets; i++) > close(fd_listenset[i]); >+ >+#ifdef HAVE_LIBDNS_SD >+ /* close socket to mDNS daemon */ >+ dns_register_close(&dnsregptr); >+#endif > > /* close our standard file > descriptors */ >Index: source/include/includes.h >=================================================================== >--- source/include/includes.h (revision 25440) >+++ source/include/includes.h (working copy) >@@ -1265,4 +1265,13 @@ > #include "libnscd.h" > #endif > >+#ifdef HAVE_LIBDNS_SD >+#include "dns_sd.h" >+#define DNS_REG_RETRY_INTERVAL 5*60 /* in seconds */ >+struct dns_reg_state { >+ DNSServiceRef regsrvref; >+ struct timed_event *dnsregretryhandler; >+}; >+#endif /* HAVE_LIBDNS_SD */ >+ > #endif /* _INCLUDES_H */ >Index: source/configure.in >=================================================================== >--- source/configure.in (revision 25440) >+++ source/configure.in (working copy) >@@ -316,6 +316,7 @@ > AC_SUBST(IDMAP_LIBS) > AC_SUBST(KRB5_LIBS) > AC_SUBST(UUID_LIBS) >+AC_SUBST(DNSSD_LIBS) > AC_SUBST(LDAP_LIBS) > AC_SUBST(PAM_MODULES) > AC_SUBST(INSTALL_PAM_MODULES) >@@ -6187,9 +6188,65 @@ > AC_SUBST(INIPARSERLIBS) > AC_SUBST(FLAGS1) > >+################################################# >+# Check if user wants DNS service discovery support >+with_dnssd_support=no >+AC_MSG_CHECKING([whether to enable DNS service discovery support]) > >+AC_ARG_WITH(dnssd, >+[ --with-dnssd Enable DNS service discovery support (default no)], >+[ case "$withval" in >+ yes|no) >+ with_dnssd_support=$withval >+ ;; >+ esac ]) > >+AC_MSG_RESULT($with_dnssd_support) >+ >+if test x"$with_dnssd_support" != x"no"; then >+ >+ ################################################################## >+ # then test for dns_sd.h >+ AC_CHECK_HEADERS(dns_sd.h) >+ >+ if test x"$ac_cv_header_dns_sd_h" != x"yes"; then >+ if test x"$with_dnssd_support" = x"yes"; then >+ AC_MSG_ERROR(dns_sd.h is needed to enable DNS service discovery support) >+ else >+ AC_MSG_WARN(dns_sd.h is needed to enable DNS service discovery support) >+ fi >+ with_dnssd_support=no >+ fi >+fi >+ >+if test x"$with_dnssd_support" != x"no"; then >+ >+ DNSSD_LIBS="" >+ AC_LIBTESTFUNC(dns_sd, DNSServiceRegister, >+ [ >+ case " $LIBS " in >+ *\ -ldns_sd\ *) >+ DNSSD_LIBS="-ldns_sd" >+ SMB_REMOVE_LIB(dns_sd) >+ ;; >+ esac >+ >+ with_dnssd_support=yes >+ AC_DEFINE(HAVE_LIBDNS_SD,1,[Whether to enable DNS service discovery support]) >+ ], >+ [ >+ if test x"$with_dnssd_support" = x"yes"; then >+ AC_MSG_ERROR(libdns_sd is needed to enable DNS service discovery support) >+ else >+ AC_MSG_WARN(libdns_sd is needed to enable DNS service discovery support) >+ fi >+ with_dnssd_support=no >+ ]) >+fi > ################################################# >+ >+ >+################################################# > # Check if the user wants Python > > # At the moment, you can use this to set which Python binary to link >@@ -6455,6 +6512,9 @@ > if test x"$with_dnsupdate_support" != x"no"; then > AC_MSG_RESULT([ UUID_LIBS = $UUID_LIBS]) > fi >+if test x"$with_dnssd_support" != x"no"; then >+ AC_MSG_RESULT([ DNSSD_LIBS = $DNSSD_LIBS]) >+fi > AC_MSG_RESULT([ AUTH_LIBS = $AUTH_LIBS]) > > ################################################# >Index: source/client/client.c >=================================================================== >--- source/client/client.c (revision 25440) >+++ source/client/client.c (working copy) >@@ -3920,6 +3920,9 @@ > { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" }, > { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" }, > { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" }, >+#ifdef HAVE_LIBDNS_SD >+ { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" }, >+#endif /*HAVE_LIBDNS_SD */ > POPT_COMMON_SAMBA > POPT_COMMON_CONNECTION > POPT_COMMON_CREDENTIALS >@@ -4043,6 +4046,11 @@ > case 'g': > grepable=True; > break; >+#ifdef HAVE_LIBDNS_SD >+ case 'B': >+ return(do_smb_browse()); >+#endif /* HAVE_LIBDNS_SD */ >+ > } > } > >Index: source/client/dnsbrowse.c >=================================================================== >--- source/client/dnsbrowse.c (revision 0) >+++ source/client/dnsbrowse.c (revision 0) >@@ -0,0 +1,210 @@ >+/* >+ Unix SMB/CIFS implementation. >+ SMB client DNS service discovery code >+ 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 2 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, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+*/ >+ >+#include "includes.h" >+ >+#ifdef HAVE_LIBDNS_SD >+ >+/* Holds service instances found during DNS browse */ >+struct mdns_smbsrv_result >+{ >+ char *serviceName; >+ char *regType; >+ char *domain; >+ uint32_t ifIndex; >+ struct mdns_smbsrv_result *nextResult; >+}; >+ >+/* Maintains state during DNS browse */ >+struct mdns_browse_state >+{ >+ struct mdns_smbsrv_result *listhead; /* Browse result list head */ >+ int browseDone; >+ >+}; >+ >+ >+static void >+do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags, >+ uint32_t interfaceIndex, DNSServiceErrorType errorCode, >+ const char *fullname, const char *hosttarget, uint16_t port, >+ uint16_t txtLen, const unsigned char *txtRecord, void *context) >+{ >+ printf("SMB service available on %s\n", hosttarget); >+} >+ >+ >+static void >+do_smb_resolve(struct mdns_smbsrv_result *browsesrv) >+{ >+ DNSServiceRef mdns_conn_sdref = NULL; >+ int mdnsfd; >+ int fdsetsz; >+ int ret; >+ fd_set *fdset = NULL; >+ struct timeval tv; >+ >+ if(DNSServiceResolve(&mdns_conn_sdref, NULL, browsesrv->ifIndex, >+ browsesrv->serviceName, browsesrv->regType, browsesrv->domain, >+ do_smb_resolve_reply, NULL) != kDNSServiceErr_NoError) >+ return; >+ >+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref); >+ for (;;) { >+ if (fdset != NULL) >+ free(fdset); >+ >+ fdsetsz = howmany(mdnsfd+1, NFDBITS) * sizeof(fd_mask); >+ fdset = (fd_set *)malloc(fdsetsz); >+ (void) memset(fdset, 0, fdsetsz); >+ FD_SET(mdnsfd, fdset); >+ >+ tv.tv_sec = 1; >+ tv.tv_usec = 0; >+ >+ /* Wait until response received from mDNS daemon */ >+ ret = select(mdnsfd+1, fdset, NULL, NULL, &tv); >+ if (ret <= 0 && errno != EINTR) >+ break; >+ >+ if (FD_ISSET(mdnsfd, fdset)) { >+ /* Invoke callback function */ >+ DNSServiceProcessResult(mdns_conn_sdref); >+ break; >+ } >+ } >+ >+ free(fdset); >+ DNSServiceRefDeallocate(mdns_conn_sdref); >+} >+ >+ >+static void >+do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags, >+ uint32_t interfaceIndex, DNSServiceErrorType errorCode, >+ const char *serviceName, const char *regtype, >+ const char *replyDomain, void *context) >+{ >+ struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context; >+ struct mdns_smbsrv_result *bresult; >+ >+ if (bstatep == NULL) >+ return; >+ >+ if (errorCode != kDNSServiceErr_NoError) { >+ bstatep->browseDone = 1; >+ return; >+ } >+ >+ if (flags & kDNSServiceFlagsMoreComing) >+ bstatep->browseDone = 0; >+ else >+ bstatep->browseDone = 1; >+ >+ if (!(flags & kDNSServiceFlagsAdd)) >+ return; >+ >+ bresult = (struct mdns_smbsrv_result *)calloc(1, sizeof(struct mdns_smbsrv_result)); >+ if (bresult == NULL) >+ return; >+ >+ if (bstatep->listhead != NULL) >+ bresult->nextResult = bstatep->listhead; >+ bresult->serviceName = strdup(serviceName); >+ bresult->regType = strdup(regtype); >+ bresult->domain = strdup(replyDomain); >+ bresult->ifIndex = interfaceIndex; >+ bstatep->listhead = bresult; >+} >+ >+ >+int do_smb_browse(void) >+{ >+ int mdnsfd; >+ int fdsetsz; >+ int ret; >+ fd_set *fdset = NULL; >+ struct mdns_browse_state bstate; >+ struct mdns_smbsrv_result *resptr; >+ struct timeval tv; >+ DNSServiceRef mdns_conn_sdref = NULL; >+ >+ (void) memset(&bstate, 0, sizeof(struct mdns_browse_state)); >+ >+ if(DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "", >+ do_smb_browse_reply, &bstate) != kDNSServiceErr_NoError) >+ { >+ d_printf("Error connecting to the Multicast DNS daemon\n"); >+ return 1; >+ } >+ >+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref); >+ for (;;) { >+ if (fdset != NULL) >+ free(fdset); >+ >+ fdsetsz = howmany(mdnsfd+1, NFDBITS) * sizeof(fd_mask); >+ fdset = (fd_set *)malloc(fdsetsz); >+ (void) memset(fdset, 0, fdsetsz); >+ FD_SET(mdnsfd, fdset); >+ >+ tv.tv_sec = 1; >+ tv.tv_usec = 0; >+ >+ /* Wait until response received from mDNS daemon */ >+ ret = select(mdnsfd+1, fdset, NULL, NULL, &tv); >+ if (ret <= 0 && errno != EINTR) >+ break; >+ >+ if (FD_ISSET(mdnsfd, fdset)) { >+ /* Invoke callback function */ >+ if (DNSServiceProcessResult(mdns_conn_sdref)) >+ break; >+ if (bstate.browseDone) >+ break; >+ } >+ } >+ >+ free(fdset); >+ DNSServiceRefDeallocate(mdns_conn_sdref); >+ >+ if (bstate.listhead != NULL) { >+ resptr = bstate.listhead; >+ while (resptr != NULL) { >+ struct mdns_smbsrv_result *oldresptr; >+ oldresptr = resptr; >+ >+ /* Resolve smb service instance */ >+ do_smb_resolve(resptr); >+ >+ /* Free result structure */ >+ free(resptr->domain); >+ free(resptr->serviceName); >+ free(resptr->regType); >+ resptr = resptr->nextResult; >+ free(oldresptr); >+ } >+ } >+ return 0; >+} >+ >+#endif /* HAVE_LIBDNS_SD */ >+ >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 4510
:
2391
|
2859
| 2934