quota: add supprt for gfs2
[samba.git] / source3 / client / dnsbrowse.c
1 /*
2    Unix SMB/CIFS implementation.
3    DNS-SD browse client
4    Copyright (C) Rishi Srivatsavai 2007
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "client/client_proto.h"
22
23 #ifdef WITH_DNSSD_SUPPORT
24
25 #include <dns_sd.h>
26
27 /* Holds service instances found during DNS browse */
28 struct mdns_smbsrv_result
29 {
30         char *serviceName;
31         char *regType;
32         char *domain;
33         uint32_t ifIndex;
34         struct mdns_smbsrv_result *nextResult;
35 };
36
37 /* Maintains state during DNS browse */
38 struct mdns_browse_state
39 {
40         struct mdns_smbsrv_result *listhead; /* Browse result list head */
41         int browseDone;
42
43 };
44
45
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)
51 {
52         printf("SMB service available on %s port %u\n",
53                 hosttarget, ntohs(port));
54 }
55
56
57 static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
58 {
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;
66
67         TALLOC_CTX * ctx = talloc_tos();
68
69         err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
70                 browsesrv->ifIndex,
71                 browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
72                 do_smb_resolve_reply, NULL);
73
74         if (err != kDNSServiceErr_NoError) {
75                 return;
76         }
77
78         mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
79         for (;;)  {
80                 if (fdset != NULL) {
81                         TALLOC_FREE(fdset);
82                 }
83
84                 if (mdnsfd < 0 || mdnsfd >= FD_SETSIZE) {
85                         errno = EBADF;
86                         break;
87                 }
88
89                 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
90                 fdset = TALLOC_ZERO(ctx, fdsetsz);
91                 FD_SET(mdnsfd, fdset);
92
93                 tv.tv_sec = 1;
94                 tv.tv_usec = 0;
95
96                 /* Wait until response received from mDNS daemon */
97                 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
98                 if (ret <= 0 && errno != EINTR) {
99                         break;
100                 }
101
102                 if (FD_ISSET(mdnsfd, fdset)) {
103                         /* Invoke callback function */
104                         DNSServiceProcessResult(mdns_conn_sdref);
105                         break;
106                 }
107         }
108
109         TALLOC_FREE(fdset);
110         DNSServiceRefDeallocate(mdns_conn_sdref);
111 }
112
113
114 static void
115 do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
116         uint32_t interfaceIndex, DNSServiceErrorType errorCode,
117         const char  *serviceName, const char *regtype,
118         const char  *replyDomain, void  *context)
119 {
120         struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
121         struct mdns_smbsrv_result *bresult;
122
123         if (bstatep == NULL) {
124                 return;
125         }
126
127         if (errorCode != kDNSServiceErr_NoError) {
128                 bstatep->browseDone = 1;
129                 return;
130         }
131
132         if (flags & kDNSServiceFlagsMoreComing) {
133                 bstatep->browseDone = 0;
134         } else {
135                 bstatep->browseDone = 1;
136         }
137
138         if (!(flags & kDNSServiceFlagsAdd)) {
139                 return;
140         }
141
142         bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
143         if (bresult == NULL) {
144                 return;
145         }
146
147         if (bstatep->listhead != NULL) {
148                 bresult->nextResult = bstatep->listhead;
149         }
150
151         bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
152         bresult->regType = talloc_strdup(talloc_tos(), regtype);
153         bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
154         bresult->ifIndex = interfaceIndex;
155         bstatep->listhead = bresult;
156 }
157
158 int do_smb_browse(void)
159 {
160         int mdnsfd;
161         int fdsetsz;
162         int ret;
163         fd_set *fdset = NULL;
164         struct mdns_browse_state bstate;
165         struct mdns_smbsrv_result *resptr;
166         struct timeval tv;
167         DNSServiceRef mdns_conn_sdref = NULL;
168         DNSServiceErrorType err;
169
170         TALLOC_CTX * ctx = talloc_stackframe();
171
172         ZERO_STRUCT(bstate);
173
174         err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
175                         do_smb_browse_reply, &bstate);
176
177         if (err != kDNSServiceErr_NoError) {
178                 d_printf("Error connecting to the Multicast DNS daemon\n");
179                 TALLOC_FREE(ctx);
180                 return 1;
181         }
182
183         mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
184         for (;;)  {
185                 if (fdset != NULL) {
186                         TALLOC_FREE(fdset);
187                 }
188
189                 if (mdnsfd < 0 || mdnsfd >= FD_SETSIZE) {
190                         errno = EBADF;
191                         TALLOC_FREE(ctx);
192                         return 1;
193                 }
194
195                 fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
196                 fdset = TALLOC_ZERO(ctx, fdsetsz);
197                 FD_SET(mdnsfd, fdset);
198
199                 tv.tv_sec = 1;
200                 tv.tv_usec = 0;
201
202                 /* Wait until response received from mDNS daemon */
203                 ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
204                 if (ret <= 0 && errno != EINTR) {
205                         break;
206                 }
207
208                 if (FD_ISSET(mdnsfd, fdset)) {
209                         /* Invoke callback function */
210                         if (DNSServiceProcessResult(mdns_conn_sdref)) {
211                                 break;
212                         }
213                         if (bstate.browseDone) {
214                                 break;
215                         }
216                 }
217         }
218
219         DNSServiceRefDeallocate(mdns_conn_sdref);
220
221         if (bstate.listhead != NULL) {
222                 resptr = bstate.listhead;
223                 while (resptr != NULL) {
224                         struct mdns_smbsrv_result *oldresptr;
225                         oldresptr = resptr;
226
227                         /* Resolve smb service instance */
228                         do_smb_resolve(resptr);
229
230                         resptr = resptr->nextResult;
231                 }
232         }
233
234         TALLOC_FREE(ctx);
235         return 0;
236 }
237
238 #else /* WITH_DNSSD_SUPPORT */
239
240 int do_smb_browse(void)
241 {
242     d_printf("DNS-SD browsing is not supported on this platform\n");
243     return 1;
244 }
245
246 #endif /* WITH_DNSSD_SUPPORT */
247
248