2 Unix SMB/CIFS implementation.
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/>.
21 #include "client/client_proto.h"
23 #ifdef WITH_DNSSD_SUPPORT
26 #include "system/select.h"
28 /* Holds service instances found during DNS browse */
29 struct mdns_smbsrv_result
35 struct mdns_smbsrv_result *nextResult;
38 /* Maintains state during DNS browse */
39 struct mdns_browse_state
41 struct mdns_smbsrv_result *listhead; /* Browse result list head */
48 do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags,
49 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
50 const char *fullname, const char *hosttarget, uint16_t port,
51 uint16_t txtLen, const unsigned char *txtRecord, void *context)
53 printf("SMB service available on %s port %u\n",
54 hosttarget, ntohs(port));
58 static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
60 DNSServiceRef mdns_conn_sdref = NULL;
66 DNSServiceErrorType err;
68 TALLOC_CTX * ctx = talloc_tos();
70 err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
72 browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
73 do_smb_resolve_reply, NULL);
75 if (err != kDNSServiceErr_NoError) {
79 mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
85 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
86 fdset = TALLOC_ZERO(ctx, fdsetsz);
87 FD_SET(mdnsfd, fdset);
92 /* Wait until response received from mDNS daemon */
93 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
94 if (ret <= 0 && errno != EINTR) {
98 if (FD_ISSET(mdnsfd, fdset)) {
99 /* Invoke callback function */
100 DNSServiceProcessResult(mdns_conn_sdref);
106 DNSServiceRefDeallocate(mdns_conn_sdref);
111 do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
112 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
113 const char *serviceName, const char *regtype,
114 const char *replyDomain, void *context)
116 struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
117 struct mdns_smbsrv_result *bresult;
119 if (bstatep == NULL) {
123 if (errorCode != kDNSServiceErr_NoError) {
124 bstatep->browseDone = 1;
128 if (flags & kDNSServiceFlagsMoreComing) {
129 bstatep->browseDone = 0;
131 bstatep->browseDone = 1;
134 if (!(flags & kDNSServiceFlagsAdd)) {
138 bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
139 if (bresult == NULL) {
143 if (bstatep->listhead != NULL) {
144 bresult->nextResult = bstatep->listhead;
147 bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
148 bresult->regType = talloc_strdup(talloc_tos(), regtype);
149 bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
150 bresult->ifIndex = interfaceIndex;
151 bstatep->listhead = bresult;
154 int do_smb_browse(void)
159 struct mdns_browse_state bstate;
160 struct mdns_smbsrv_result *resptr;
162 DNSServiceRef mdns_conn_sdref = NULL;
163 DNSServiceErrorType err;
165 TALLOC_CTX * ctx = talloc_stackframe();
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");
178 mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
182 ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, &revents, 1000);
183 if (ret <= 0 && errno != EINTR) {
187 if (revents & (POLLIN|POLLHUP|POLLERR)) {
188 /* Invoke callback function */
189 if (DNSServiceProcessResult(mdns_conn_sdref)) {
192 if (bstate.browseDone) {
198 DNSServiceRefDeallocate(mdns_conn_sdref);
200 if (bstate.listhead != NULL) {
201 resptr = bstate.listhead;
202 while (resptr != NULL) {
203 struct mdns_smbsrv_result *oldresptr;
206 /* Resolve smb service instance */
207 do_smb_resolve(resptr);
209 resptr = resptr->nextResult;
217 #else /* WITH_DNSSD_SUPPORT */
219 int do_smb_browse(void)
221 d_printf("DNS-SD browsing is not supported on this platform\n");
225 #endif /* WITH_DNSSD_SUPPORT */