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/>.
22 /* Uses DNS service discovery (libdns_sd) to
23 * register the SMB service. SMB service is registered
24 * on ".local" domain via Multicast DNS & any
25 * other unicast DNS domains available.
27 * Users use the smbclient -B (Browse) option to
28 * browse for advertised SMB services.
31 #define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */
33 #ifdef WITH_DNSSD_SUPPORT
37 struct dns_reg_state
{
38 DNSServiceRef srv_ref
;
39 struct timed_event
*retry_handler
;
42 void dns_register_close(struct dns_reg_state
**dns_state_ptr
)
44 struct dns_reg_state
*dns_state
= *dns_state_ptr
;
46 if (dns_state
== NULL
) {
50 if (dns_state
->srv_ref
!= NULL
) {
51 /* Close connection to the mDNS daemon */
52 DNSServiceRefDeallocate(dns_state
->srv_ref
);
53 dns_state
->srv_ref
= NULL
;
56 /* Clear event handler */
57 if (dns_state
->retry_handler
!= NULL
) {
58 TALLOC_FREE(dns_state
->retry_handler
);
59 dns_state
->retry_handler
= NULL
;
62 talloc_free(dns_state
);
63 *dns_state_ptr
= NULL
;
66 static void dns_register_smbd_retry(struct event_context
*ctx
,
67 struct timed_event
*te
,
71 struct dns_reg_state
*dns_state
= (struct dns_reg_state
*)private_data
;
73 /* Clear previous registration state to force new
74 * registration attempt. Clears event handler.
76 dns_register_close(&dns_state
);
79 static void schedule_dns_register_smbd_retry(struct dns_reg_state
*dns_state
,
80 struct timeval
*timeout
)
82 struct timed_event
* event
;
84 dns_state
->srv_ref
= NULL
;
85 event
= event_add_timed(smbd_event_context(),
87 timeval_current_ofs(DNS_REG_RETRY_INTERVAL
, 0),
88 dns_register_smbd_retry
,
91 dns_state
->retry_handler
= event
;
92 get_timed_events_timeout(smbd_event_context(), timeout
);
95 /* Kick off a mDNS request to register the "_smb._tcp" on the specified port.
96 * We really ought to register on all the ports we are listening on. This will
97 * have to be an exercise for some-one who knows the DNS registration API a bit
100 void dns_register_smbd(struct dns_reg_state
** dns_state_ptr
,
104 struct timeval
*timeout
)
107 DNSServiceErrorType err
;
108 struct dns_reg_state
*dns_state
= *dns_state_ptr
;
110 if (dns_state
== NULL
) {
111 dns_state
= talloc_zero(NULL
, struct dns_reg_state
);
112 *dns_state_ptr
= dns_state
;
113 if (dns_state
== NULL
) {
118 /* Quit if a re-try attempt has been scheduled. */
119 if (dns_state
->retry_handler
!= NULL
) {
123 /* If a registration is active add conn
124 * fd to select listen_set and return
126 if (dns_state
->srv_ref
!= NULL
) {
127 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
128 FD_SET(mdnsd_conn_fd
, listen_set
);
132 DEBUG(6, ("registering _smb._tcp service on port %d\n", port
));
134 /* Register service with DNS. Connects with the mDNS
135 * daemon running on the local system to perform DNS
136 * service registration.
138 err
= DNSServiceRegister(&dns_state
->srv_ref
, 0 /* flags */,
139 kDNSServiceInterfaceIndexAny
,
140 NULL
/* service name */,
141 "_smb._tcp" /* service type */,
143 "" /* SRV target host name */,
145 0 /* TXT record len */,
146 NULL
/* TXT record data */,
147 NULL
/* callback func */,
148 NULL
/* callback context */);
150 if (err
!= kDNSServiceErr_NoError
) {
151 /* Failed to register service. Schedule a re-try attempt.
153 DEBUG(3, ("unable to register with mDNS (err %d)\n", err
));
154 schedule_dns_register_smbd_retry(dns_state
, timeout
);
158 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
159 FD_SET(mdnsd_conn_fd
, listen_set
);
160 *maxfd
= MAX(*maxfd
, mdnsd_conn_fd
);
161 *timeout
= timeval_zero();
165 /* Processes reply from mDNS daemon. Returns true if a reply was received */
166 bool dns_register_smbd_reply(struct dns_reg_state
*dns_state
,
167 fd_set
*lfds
, struct timeval
*timeout
)
169 int mdnsd_conn_fd
= -1;
171 if (dns_state
->srv_ref
== NULL
) {
175 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
177 /* Process reply from daemon. Handles any errors. */
178 if ((mdnsd_conn_fd
!= -1) && (FD_ISSET(mdnsd_conn_fd
,lfds
)) ) {
179 DNSServiceErrorType err
;
181 err
= DNSServiceProcessResult(dns_state
->srv_ref
);
182 if (err
!= kDNSServiceErr_NoError
) {
183 DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
185 schedule_dns_register_smbd_retry(dns_state
, timeout
);
194 #else /* WITH_DNSSD_SUPPORT */
196 void dns_register_smbd(struct dns_reg_state
** dns_state_ptr
,
200 struct timeval
*timeout
)
203 void dns_register_close(struct dns_reg_state
** dns_state_ptr
)
206 bool dns_register_smbd_reply(struct dns_reg_state
*dns_state
,
207 fd_set
*lfds
, struct timeval
*timeout
)
212 #endif /* WITH_DNSSD_SUPPORT */