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_ptr
= dns_state
= talloc(NULL
, struct dns_reg_state
);
112 if (dns_state
== NULL
) {
117 /* Quit if a re-try attempt has been scheduled. */
118 if (dns_state
->retry_handler
!= NULL
) {
122 /* If a registration is active add conn
123 * fd to select listen_set and return
125 if (dns_state
->srv_ref
!= NULL
) {
126 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
127 FD_SET(mdnsd_conn_fd
, listen_set
);
131 DEBUG(6, ("registering _smb._tcp service on port %d\n", port
));
133 /* Register service with DNS. Connects with the mDNS
134 * daemon running on the local system to perform DNS
135 * service registration.
137 err
= DNSServiceRegister(&dns_state
->srv_ref
, 0 /* flags */,
138 kDNSServiceInterfaceIndexAny
,
139 NULL
/* service name */,
140 "_smb._tcp" /* service type */,
142 "" /* SRV target host name */,
144 0 /* TXT record len */,
145 NULL
/* TXT record data */,
146 NULL
/* callback func */,
147 NULL
/* callback context */);
149 if (err
!= kDNSServiceErr_NoError
) {
150 /* Failed to register service. Schedule a re-try attempt.
152 DEBUG(3, ("unable to register with mDNS (err %d)\n", err
));
153 schedule_dns_register_smbd_retry(dns_state
, timeout
);
157 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
158 FD_SET(mdnsd_conn_fd
, listen_set
);
159 *maxfd
= MAX(*maxfd
, mdnsd_conn_fd
);
160 *timeout
= timeval_zero();
164 /* Processes reply from mDNS daemon. Returns true if a reply was received */
165 bool dns_register_smbd_reply(struct dns_reg_state
*dns_state
,
166 fd_set
*lfds
, struct timeval
*timeout
)
168 int mdnsd_conn_fd
= -1;
170 if (dns_state
->srv_ref
== NULL
) {
174 mdnsd_conn_fd
= DNSServiceRefSockFD(dns_state
->srv_ref
);
176 /* Process reply from daemon. Handles any errors. */
177 if ((mdnsd_conn_fd
!= -1) && (FD_ISSET(mdnsd_conn_fd
,lfds
)) ) {
178 DNSServiceErrorType err
;
180 err
= DNSServiceProcessResult(dns_state
->srv_ref
);
181 if (err
!= kDNSServiceErr_NoError
) {
182 DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
184 schedule_dns_register_smbd_retry(dns_state
, timeout
);
193 #else /* WITH_DNSSD_SUPPORT */
195 void dns_register_smbd(struct dns_reg_state
** dns_state_ptr
,
199 struct timeval
*timeout
)
202 void dns_register_close(struct dns_reg_state
** dns_state_ptr
)
205 bool dns_register_smbd_reply(struct dns_reg_state
*dns_state
,
206 fd_set
*lfds
, struct timeval
*timeout
)
211 #endif /* WITH_DNSSD_SUPPORT */