selftest/known: samba3.smb2.session.*reconnect passes now
[Samba/gebeck_regimport.git] / source3 / client / dnsbrowse.c
blob03f87afe140031d1640f295246a9c873d55956bf
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>
26 #include "system/select.h"
28 /* Holds service instances found during DNS browse */
29 struct mdns_smbsrv_result
31 char *serviceName;
32 char *regType;
33 char *domain;
34 uint32_t ifIndex;
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 */
42 int browseDone;
47 static void
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;
61 int mdnsfd;
62 int fdsetsz;
63 int ret;
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 int revents;
82 ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, 1000, &revents);
83 if (ret <= 0 && errno != EINTR) {
84 break;
87 if (revents & (POLLIN|POLLHUP|POLLERR)) {
88 /* Invoke callback function */
89 DNSServiceProcessResult(mdns_conn_sdref);
90 break;
94 TALLOC_FREE(fdset);
95 DNSServiceRefDeallocate(mdns_conn_sdref);
99 static void
100 do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
101 uint32_t interfaceIndex, DNSServiceErrorType errorCode,
102 const char *serviceName, const char *regtype,
103 const char *replyDomain, void *context)
105 struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
106 struct mdns_smbsrv_result *bresult;
108 if (bstatep == NULL) {
109 return;
112 if (errorCode != kDNSServiceErr_NoError) {
113 bstatep->browseDone = 1;
114 return;
117 if (flags & kDNSServiceFlagsMoreComing) {
118 bstatep->browseDone = 0;
119 } else {
120 bstatep->browseDone = 1;
123 if (!(flags & kDNSServiceFlagsAdd)) {
124 return;
127 bresult = talloc_array(talloc_tos(), struct mdns_smbsrv_result, 1);
128 if (bresult == NULL) {
129 return;
132 if (bstatep->listhead != NULL) {
133 bresult->nextResult = bstatep->listhead;
136 bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
137 bresult->regType = talloc_strdup(talloc_tos(), regtype);
138 bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
139 bresult->ifIndex = interfaceIndex;
140 bstatep->listhead = bresult;
143 int do_smb_browse(void)
145 int mdnsfd;
146 int fdsetsz;
147 int ret;
148 struct mdns_browse_state bstate;
149 struct mdns_smbsrv_result *resptr;
150 struct timeval tv;
151 DNSServiceRef mdns_conn_sdref = NULL;
152 DNSServiceErrorType err;
154 TALLOC_CTX * ctx = talloc_stackframe();
156 ZERO_STRUCT(bstate);
158 err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
159 do_smb_browse_reply, &bstate);
161 if (err != kDNSServiceErr_NoError) {
162 d_printf("Error connecting to the Multicast DNS daemon\n");
163 TALLOC_FREE(ctx);
164 return 1;
167 mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
168 for (;;) {
169 int revents;
171 ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, &revents, 1000);
172 if (ret <= 0 && errno != EINTR) {
173 break;
176 if (revents & (POLLIN|POLLHUP|POLLERR)) {
177 /* Invoke callback function */
178 if (DNSServiceProcessResult(mdns_conn_sdref)) {
179 break;
181 if (bstate.browseDone) {
182 break;
187 DNSServiceRefDeallocate(mdns_conn_sdref);
189 if (bstate.listhead != NULL) {
190 resptr = bstate.listhead;
191 while (resptr != NULL) {
192 struct mdns_smbsrv_result *oldresptr;
193 oldresptr = resptr;
195 /* Resolve smb service instance */
196 do_smb_resolve(resptr);
198 resptr = resptr->nextResult;
202 TALLOC_FREE(ctx);
203 return 0;
206 #else /* WITH_DNSSD_SUPPORT */
208 int do_smb_browse(void)
210 d_printf("DNS-SD browsing is not supported on this platform\n");
211 return 1;
214 #endif /* WITH_DNSSD_SUPPORT */