Line data Source code
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 : #include "system/select.h"
27 :
28 : /* Holds service instances found during DNS browse */
29 : struct mdns_smbsrv_result
30 : {
31 : char *serviceName;
32 : char *regType;
33 : char *domain;
34 : uint32_t ifIndex;
35 : struct mdns_smbsrv_result *nextResult;
36 : };
37 :
38 : /* Maintains state during DNS browse */
39 : struct mdns_browse_state
40 : {
41 : struct mdns_smbsrv_result *listhead; /* Browse result list head */
42 : int browseDone;
43 :
44 : };
45 :
46 :
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)
52 : {
53 : printf("SMB service available on %s port %u\n",
54 : hosttarget, ntohs(port));
55 : }
56 :
57 :
58 : static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
59 : {
60 : DNSServiceRef mdns_conn_sdref = NULL;
61 : int mdnsfd;
62 : int fdsetsz;
63 : int ret;
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 : int revents;
81 :
82 : ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, 1000, &revents);
83 : if (ret <= 0 && errno != EINTR) {
84 : break;
85 : }
86 :
87 : if (revents & (POLLIN|POLLHUP|POLLERR)) {
88 : /* Invoke callback function */
89 : DNSServiceProcessResult(mdns_conn_sdref);
90 : break;
91 : }
92 : }
93 :
94 : TALLOC_FREE(fdset);
95 : DNSServiceRefDeallocate(mdns_conn_sdref);
96 : }
97 :
98 :
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)
104 : {
105 : struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
106 : struct mdns_smbsrv_result *bresult;
107 :
108 : if (bstatep == NULL) {
109 : return;
110 : }
111 :
112 : if (errorCode != kDNSServiceErr_NoError) {
113 : bstatep->browseDone = 1;
114 : return;
115 : }
116 :
117 : if (flags & kDNSServiceFlagsMoreComing) {
118 : bstatep->browseDone = 0;
119 : } else {
120 : bstatep->browseDone = 1;
121 : }
122 :
123 : if (!(flags & kDNSServiceFlagsAdd)) {
124 : return;
125 : }
126 :
127 : bresult = talloc_array(talloc_tos(), struct mdns_smbsrv_result, 1);
128 : if (bresult == NULL) {
129 : return;
130 : }
131 :
132 : if (bstatep->listhead != NULL) {
133 : bresult->nextResult = bstatep->listhead;
134 : }
135 :
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;
141 : }
142 :
143 : int do_smb_browse(void)
144 : {
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;
153 :
154 : TALLOC_CTX * ctx = talloc_stackframe();
155 :
156 : ZERO_STRUCT(bstate);
157 :
158 : err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
159 : do_smb_browse_reply, &bstate);
160 :
161 : if (err != kDNSServiceErr_NoError) {
162 : d_printf("Error connecting to the Multicast DNS daemon\n");
163 : TALLOC_FREE(ctx);
164 : return 1;
165 : }
166 :
167 : mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
168 : for (;;) {
169 : int revents;
170 :
171 : ret = poll_one_fd(mdnsfd, POLLIN|POLLHUP, 1000, &revents);
172 : if (ret <= 0 && errno != EINTR) {
173 : break;
174 : }
175 :
176 : if (revents & (POLLIN|POLLHUP|POLLERR)) {
177 : /* Invoke callback function */
178 : if (DNSServiceProcessResult(mdns_conn_sdref)) {
179 : break;
180 : }
181 : if (bstate.browseDone) {
182 : break;
183 : }
184 : }
185 : }
186 :
187 : DNSServiceRefDeallocate(mdns_conn_sdref);
188 :
189 : if (bstate.listhead != NULL) {
190 : resptr = bstate.listhead;
191 : while (resptr != NULL) {
192 : struct mdns_smbsrv_result *oldresptr;
193 : oldresptr = resptr;
194 :
195 : /* Resolve smb service instance */
196 : do_smb_resolve(resptr);
197 :
198 : resptr = resptr->nextResult;
199 : }
200 : }
201 :
202 : TALLOC_FREE(ctx);
203 : return 0;
204 : }
205 :
206 : #else /* WITH_DNSSD_SUPPORT */
207 :
208 0 : int do_smb_browse(void)
209 : {
210 0 : d_printf("DNS-SD browsing is not supported on this platform\n");
211 0 : return 1;
212 : }
213 :
214 : #endif /* WITH_DNSSD_SUPPORT */
215 :
216 :
|