summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in8
-rw-r--r--source3/client/client.c7
-rw-r--r--source3/client/dnsbrowse.c236
-rw-r--r--source3/configure.in1
4 files changed, 250 insertions, 2 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 21fc8cebf7..eda3297d23 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -673,6 +673,7 @@ LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) \
$(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(LDB_OBJ)
CLIENT_OBJ1 = client/client.o client/clitar.o rpc_client/cli_pipe.o \
+ client/dnsbrowse.o \
$(RPC_CLIENT_OBJ1) \
$(RPC_PARSE_OBJ2)
@@ -1140,7 +1141,8 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @BUILD_POPT@
@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) $(DNSSD_LIBS) \
+ @POPTLIBS@ @SMBD_LIBS@
bin/nmbd@EXEEXT@: $(BINARY_PREREQS) $(NMBD_OBJ) @BUILD_POPT@
@echo Linking $@
@@ -1159,7 +1161,9 @@ bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@
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/net@EXEEXT@: $(BINARY_PREREQS) $(NET_OBJ) @BUILD_POPT@
@echo Linking $@
diff --git a/source3/client/client.c b/source3/client/client.c
index d59af9e6cf..97d7cf0e0b 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -28,10 +28,13 @@
#define REGISTER 0
#endif
+extern int do_smb_browse(void); /* mDNS browsing */
+
extern bool AllowDebugChange;
extern bool override_logfile;
extern char tar_type;
extern bool in_client;
+
static int port = 0;
static char *service;
static char *desthost;
@@ -4512,6 +4515,7 @@ static int do_message_op(void)
{ "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" },
+ { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
@@ -4654,6 +4658,9 @@ static int do_message_op(void)
case 'g':
grepable=true;
break;
+ case 'B':
+ return(do_smb_browse());
+
}
}
diff --git a/source3/client/dnsbrowse.c b/source3/client/dnsbrowse.c
new file mode 100644
index 0000000000..c4819cebfa
--- /dev/null
+++ b/source3/client/dnsbrowse.c
@@ -0,0 +1,236 @@
+/*
+ Unix SMB/CIFS implementation.
+ DNS-SD browse client
+ 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"
+
+#ifdef WITH_DNSSD_SUPPORT
+
+#include <dns_sd.h>
+
+/* 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 port %u\n",
+ hosttarget, ntohs(port));
+}
+
+
+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;
+ DNSServiceErrorType err;
+
+ TALLOC_CTX * ctx = talloc_tos();
+
+ err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
+ browsesrv->ifIndex,
+ browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
+ do_smb_resolve_reply, NULL);
+
+ if (err != kDNSServiceErr_NoError) {
+ return;
+ }
+
+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
+ for (;;) {
+ if (fdset != NULL) {
+ TALLOC_FREE(fdset);
+ }
+
+ fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
+ fdset = TALLOC_ZERO(ctx, fdsetsz);
+ FD_SET(mdnsfd, fdset);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ /* Wait until response received from mDNS daemon */
+ ret = sys_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;
+ }
+ }
+
+ TALLOC_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 = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
+ if (bresult == NULL) {
+ return;
+ }
+
+ if (bstatep->listhead != NULL) {
+ bresult->nextResult = bstatep->listhead;
+ }
+
+ bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
+ bresult->regType = talloc_strdup(talloc_tos(), regtype);
+ bresult->domain = talloc_strdup(talloc_tos(), 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;
+ DNSServiceErrorType err;
+
+ TALLOC_CTX * ctx = talloc_stackframe();
+
+ ZERO_STRUCT(bstate);
+
+ err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
+ do_smb_browse_reply, &bstate);
+
+ if (err != kDNSServiceErr_NoError) {
+ d_printf("Error connecting to the Multicast DNS daemon\n");
+ TALLOC_FREE(ctx);
+ return 1;
+ }
+
+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
+ for (;;) {
+ if (fdset != NULL) {
+ TALLOC_FREE(fdset);
+ }
+
+ fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
+ fdset = TALLOC_ZERO(ctx, fdsetsz);
+ FD_SET(mdnsfd, fdset);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ /* Wait until response received from mDNS daemon */
+ ret = sys_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;
+ }
+ }
+ }
+
+ 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);
+
+ resptr = resptr->nextResult;
+ }
+ }
+
+ TALLOC_FREE(ctx);
+ return 0;
+}
+
+#else /* WITH_DNSSD_SUPPORT */
+
+int do_smb_browse(void)
+{
+ d_printf("DNS-SD browsing is not supported on this platform\n");
+ return 1;
+}
+
+#endif /* WITH_DNSSD_SUPPORT */
+
+
diff --git a/source3/configure.in b/source3/configure.in
index ac60b6f645..6015837a2e 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -6191,6 +6191,7 @@ AC_SUBST(FLAGS1)
AC_ARG_ENABLE(dnssd,
[ --enable-dnssd Enable DNS service discovery support (default=auto)])
+AC_SUBST(DNSSD_LIBS)
if test x"$enable_dnssd" != x"no"; then
have_dnssd_support=yes