WHATSNEW: Update changes since 3.3.0pre1 and release date.
[Samba.git] / source / client / dnsbrowse.c
blob5e3a4de9cff03afb16397a8a6ee03d0579d87326
1 /*
2 Unix SMB/CIFS implementation.
3 DNS-SD browse client
4 Copyright (C) Rishi Srivatsavai 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "client/client_proto.h"
23 #ifdef WITH_DNSSD_SUPPORT
25 #include <dns_sd.h>
27 /* Holds service instances found during DNS browse */
28 struct mdns_smbsrv_result
30 char *serviceName;
31 char *regType;
32 char *domain;
33 uint32_t ifIndex;
34 struct mdns_smbsrv_result *nextResult;
37 /* Maintains state during DNS browse */
38 struct mdns_browse_state
40 struct mdns_smbsrv_result *listhead; /* Browse result list head */
41 int browseDone;
46 static void
47 do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags,
48 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
49 const char *fullname, const char *hosttarget, uint16_t port,
50 uint16_t txtLen, const unsigned char *txtRecord, void *context)
52 printf("SMB service available on %s port %u\n",
53 hosttarget, ntohs(port));
57 static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
59 DNSServiceRef mdns_conn_sdref = NULL;
60 int mdnsfd;
61 int fdsetsz;
62 int ret;
63 fd_set *fdset = NULL;
64 struct timeval tv;
65 DNSServiceErrorType err;
67 TALLOC_CTX * ctx = talloc_tos();
69 err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
70 browsesrv->ifIndex,
71 browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
72 do_smb_resolve_reply, NULL);
74 if (err != kDNSServiceErr_NoError) {
75 return;
78 mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
79 for (;;) {
80 if (fdset != NULL) {
81 TALLOC_FREE(fdset);
84 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
85 fdset = TALLOC_ZERO(ctx, fdsetsz);
86 FD_SET(mdnsfd, fdset);
88 tv.tv_sec = 1;
89 tv.tv_usec = 0;
91 /* Wait until response received from mDNS daemon */
92 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
93 if (ret <= 0 && errno != EINTR) {
94 break;
97 if (FD_ISSET(mdnsfd, fdset)) {
98 /* Invoke callback function */
99 DNSServiceProcessResult(mdns_conn_sdref);
100 break;
104 TALLOC_FREE(fdset);
105 DNSServiceRefDeallocate(mdns_conn_sdref);
109 static void
110 do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
111 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
112 const char *serviceName, const char *regtype,
113 const char *replyDomain, void *context)
115 struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
116 struct mdns_smbsrv_result *bresult;
118 if (bstatep == NULL) {
119 return;
122 if (errorCode != kDNSServiceErr_NoError) {
123 bstatep->browseDone = 1;
124 return;
127 if (flags & kDNSServiceFlagsMoreComing) {
128 bstatep->browseDone = 0;
129 } else {
130 bstatep->browseDone = 1;
133 if (!(flags & kDNSServiceFlagsAdd)) {
134 return;
137 bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
138 if (bresult == NULL) {
139 return;
142 if (bstatep->listhead != NULL) {
143 bresult->nextResult = bstatep->listhead;
146 bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
147 bresult->regType = talloc_strdup(talloc_tos(), regtype);
148 bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
149 bresult->ifIndex = interfaceIndex;
150 bstatep->listhead = bresult;
153 int do_smb_browse(void)
155 int mdnsfd;
156 int fdsetsz;
157 int ret;
158 fd_set *fdset = NULL;
159 struct mdns_browse_state bstate;
160 struct mdns_smbsrv_result *resptr;
161 struct timeval tv;
162 DNSServiceRef mdns_conn_sdref = NULL;
163 DNSServiceErrorType err;
165 TALLOC_CTX * ctx = talloc_stackframe();
167 ZERO_STRUCT(bstate);
169 err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
170 do_smb_browse_reply, &bstate);
172 if (err != kDNSServiceErr_NoError) {
173 d_printf("Error connecting to the Multicast DNS daemon\n");
174 TALLOC_FREE(ctx);
175 return 1;
178 mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
179 for (;;) {
180 if (fdset != NULL) {
181 TALLOC_FREE(fdset);
184 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
185 fdset = TALLOC_ZERO(ctx, fdsetsz);
186 FD_SET(mdnsfd, fdset);
188 tv.tv_sec = 1;
189 tv.tv_usec = 0;
191 /* Wait until response received from mDNS daemon */
192 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
193 if (ret <= 0 && errno != EINTR) {
194 break;
197 if (FD_ISSET(mdnsfd, fdset)) {
198 /* Invoke callback function */
199 if (DNSServiceProcessResult(mdns_conn_sdref)) {
200 break;
202 if (bstate.browseDone) {
203 break;
208 DNSServiceRefDeallocate(mdns_conn_sdref);
210 if (bstate.listhead != NULL) {
211 resptr = bstate.listhead;
212 while (resptr != NULL) {
213 struct mdns_smbsrv_result *oldresptr;
214 oldresptr = resptr;
216 /* Resolve smb service instance */
217 do_smb_resolve(resptr);
219 resptr = resptr->nextResult;
223 TALLOC_FREE(ctx);
224 return 0;
227 #else /* WITH_DNSSD_SUPPORT */
229 int do_smb_browse(void)
231 d_printf("DNS-SD browsing is not supported on this platform\n");
232 return 1;
235 #endif /* WITH_DNSSD_SUPPORT */