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
27 /* Holds service instances found during DNS browse */
28 struct mdns_smbsrv_result
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 */
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
;
65 DNSServiceErrorType err
;
67 TALLOC_CTX
* ctx
= talloc_tos();
69 err
= DNSServiceResolve(&mdns_conn_sdref
, 0 /* flags */,
71 browsesrv
->serviceName
, browsesrv
->regType
, browsesrv
->domain
,
72 do_smb_resolve_reply
, NULL
);
74 if (err
!= kDNSServiceErr_NoError
) {
78 mdnsfd
= DNSServiceRefSockFD(mdns_conn_sdref
);
84 if (mdnsfd
< 0 || mdnsfd
>= FD_SETSIZE
) {
89 fdsetsz
= howmany(mdnsfd
+ 1, NFDBITS
) * sizeof(fd_mask
);
90 fdset
= TALLOC_ZERO(ctx
, fdsetsz
);
91 FD_SET(mdnsfd
, fdset
);
96 /* Wait until response received from mDNS daemon */
97 ret
= sys_select(mdnsfd
+ 1, fdset
, NULL
, NULL
, &tv
);
98 if (ret
<= 0 && errno
!= EINTR
) {
102 if (FD_ISSET(mdnsfd
, fdset
)) {
103 /* Invoke callback function */
104 DNSServiceProcessResult(mdns_conn_sdref
);
110 DNSServiceRefDeallocate(mdns_conn_sdref
);
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
)
120 struct mdns_browse_state
*bstatep
= (struct mdns_browse_state
*)context
;
121 struct mdns_smbsrv_result
*bresult
;
123 if (bstatep
== NULL
) {
127 if (errorCode
!= kDNSServiceErr_NoError
) {
128 bstatep
->browseDone
= 1;
132 if (flags
& kDNSServiceFlagsMoreComing
) {
133 bstatep
->browseDone
= 0;
135 bstatep
->browseDone
= 1;
138 if (!(flags
& kDNSServiceFlagsAdd
)) {
142 bresult
= TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result
, 1);
143 if (bresult
== NULL
) {
147 if (bstatep
->listhead
!= NULL
) {
148 bresult
->nextResult
= bstatep
->listhead
;
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
;
158 int do_smb_browse(void)
163 fd_set
*fdset
= NULL
;
164 struct mdns_browse_state bstate
;
165 struct mdns_smbsrv_result
*resptr
;
167 DNSServiceRef mdns_conn_sdref
= NULL
;
168 DNSServiceErrorType err
;
170 TALLOC_CTX
* ctx
= talloc_stackframe();
174 err
= DNSServiceBrowse(&mdns_conn_sdref
, 0, 0, "_smb._tcp", "",
175 do_smb_browse_reply
, &bstate
);
177 if (err
!= kDNSServiceErr_NoError
) {
178 d_printf("Error connecting to the Multicast DNS daemon\n");
183 mdnsfd
= DNSServiceRefSockFD(mdns_conn_sdref
);
189 if (mdnsfd
< 0 || mdnsfd
>= FD_SETSIZE
) {
195 fdsetsz
= howmany(mdnsfd
+ 1, NFDBITS
) * sizeof(fd_mask
);
196 fdset
= TALLOC_ZERO(ctx
, fdsetsz
);
197 FD_SET(mdnsfd
, fdset
);
202 /* Wait until response received from mDNS daemon */
203 ret
= sys_select(mdnsfd
+ 1, fdset
, NULL
, NULL
, &tv
);
204 if (ret
<= 0 && errno
!= EINTR
) {
208 if (FD_ISSET(mdnsfd
, fdset
)) {
209 /* Invoke callback function */
210 if (DNSServiceProcessResult(mdns_conn_sdref
)) {
213 if (bstate
.browseDone
) {
219 DNSServiceRefDeallocate(mdns_conn_sdref
);
221 if (bstate
.listhead
!= NULL
) {
222 resptr
= bstate
.listhead
;
223 while (resptr
!= NULL
) {
224 struct mdns_smbsrv_result
*oldresptr
;
227 /* Resolve smb service instance */
228 do_smb_resolve(resptr
);
230 resptr
= resptr
->nextResult
;
238 #else /* WITH_DNSSD_SUPPORT */
240 int do_smb_browse(void)
242 d_printf("DNS-SD browsing is not supported on this platform\n");
246 #endif /* WITH_DNSSD_SUPPORT */