source: branches/samba-3.3.x/source/smbd/dnsregister.c@ 578

Last change on this file since 578 was 578, checked in by Herwig Bauernfeind, 14 years ago

Update Samba 3.3 to 3.3.15 (security update)

File size: 6.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 DNS-SD registration
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
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.
26 *
27 * Users use the smbclient -B (Browse) option to
28 * browse for advertised SMB services.
29 */
30
31#define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */
32
33#ifdef WITH_DNSSD_SUPPORT
34
35#include <dns_sd.h>
36
37struct dns_reg_state {
38 DNSServiceRef srv_ref;
39 struct timed_event *retry_handler;
40};
41
42void dns_register_close(struct dns_reg_state **dns_state_ptr)
43{
44 struct dns_reg_state *dns_state = *dns_state_ptr;
45
46 if (dns_state == NULL) {
47 return;
48 }
49
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;
54 }
55
56 /* Clear event handler */
57 if (dns_state->retry_handler != NULL) {
58 TALLOC_FREE(dns_state->retry_handler);
59 dns_state->retry_handler = NULL;
60 }
61
62 talloc_free(dns_state);
63 *dns_state_ptr = NULL;
64}
65
66static void dns_register_smbd_retry(struct event_context *ctx,
67 struct timed_event *te,
68 struct timeval now,
69 void *private_data)
70{
71 struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data;
72
73 /* Clear previous registration state to force new
74 * registration attempt. Clears event handler.
75 */
76 dns_register_close(&dns_state);
77}
78
79static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state,
80 struct timeval *timeout)
81{
82 struct timed_event * event;
83
84 dns_state->srv_ref = NULL;
85 event= event_add_timed(smbd_event_context(),
86 NULL,
87 timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0),
88 dns_register_smbd_retry,
89 dns_state);
90
91 dns_state->retry_handler = event;
92 get_timed_events_timeout(smbd_event_context(), timeout);
93}
94
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
98 * better.
99 */
100void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
101 unsigned port,
102 int *maxfd,
103 fd_set *listen_set,
104 struct timeval *timeout)
105{
106 int mdnsd_conn_fd;
107 DNSServiceErrorType err;
108 struct dns_reg_state *dns_state = *dns_state_ptr;
109
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) {
114 return;
115 }
116 }
117
118 /* Quit if a re-try attempt has been scheduled. */
119 if (dns_state->retry_handler != NULL) {
120 return;
121 }
122
123 /* If a registration is active add conn
124 * fd to select listen_set and return
125 */
126 if (dns_state->srv_ref != NULL) {
127 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
128 if (mdnsd_conn_fd < 0 || mdnsd_conn_fd >= FD_SETSIZE) {
129 return;
130 }
131 FD_SET(mdnsd_conn_fd, listen_set);
132 return;
133 }
134
135 DEBUG(6, ("registering _smb._tcp service on port %d\n", port));
136
137 /* Register service with DNS. Connects with the mDNS
138 * daemon running on the local system to perform DNS
139 * service registration.
140 */
141 err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */,
142 kDNSServiceInterfaceIndexAny,
143 NULL /* service name */,
144 "_smb._tcp" /* service type */,
145 NULL /* domain */,
146 "" /* SRV target host name */,
147 htons(port),
148 0 /* TXT record len */,
149 NULL /* TXT record data */,
150 NULL /* callback func */,
151 NULL /* callback context */);
152
153 if (err != kDNSServiceErr_NoError) {
154 /* Failed to register service. Schedule a re-try attempt.
155 */
156 DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
157 schedule_dns_register_smbd_retry(dns_state, timeout);
158 return;
159 }
160
161 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
162 if (mdnsd_conn_fd < 0 || mdnsd_conn_fd >= FD_SETSIZE) {
163 return;
164 }
165 FD_SET(mdnsd_conn_fd, listen_set);
166 *maxfd = MAX(*maxfd, mdnsd_conn_fd);
167 *timeout = timeval_zero();
168
169}
170
171/* Processes reply from mDNS daemon. Returns true if a reply was received */
172bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
173 fd_set *lfds, struct timeval *timeout)
174{
175 int mdnsd_conn_fd = -1;
176
177 if ((dns_state == NULL) || (dns_state->srv_ref == NULL)) {
178 return false;
179 }
180
181 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
182
183 /* Process reply from daemon. Handles any errors. */
184 if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) {
185 DNSServiceErrorType err;
186
187 err = DNSServiceProcessResult(dns_state->srv_ref);
188 if (err != kDNSServiceErr_NoError) {
189 DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
190 err));
191 schedule_dns_register_smbd_retry(dns_state, timeout);
192 }
193
194 return true;
195 }
196
197 return false;
198}
199
200#else /* WITH_DNSSD_SUPPORT */
201
202 void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
203 unsigned port,
204 int *maxfd,
205 fd_set *listen_set,
206 struct timeval *timeout)
207{}
208
209 void dns_register_close(struct dns_reg_state ** dns_state_ptr)
210{}
211
212 bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
213 fd_set *lfds, struct timeval *timeout)
214{
215 return false;
216}
217
218#endif /* WITH_DNSSD_SUPPORT */
Note: See TracBrowser for help on using the repository browser.