source: branches/samba-3.2.x/source/smbd/dnsregister.c@ 233

Last change on this file since 233 was 233, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.9

File size: 5.8 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 const 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 registration handler",
89 dns_register_smbd_retry,
90 dns_state);
91
92 dns_state->retry_handler = event;
93 get_timed_events_timeout(smbd_event_context(), timeout);
94}
95
96/* Kick off a mDNS request to register the "_smb._tcp" on the specified port.
97 * We really ought to register on all the ports we are listening on. This will
98 * have to be an exercise for some-one who knows the DNS registration API a bit
99 * better.
100 */
101void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
102 unsigned port,
103 int *maxfd,
104 fd_set *listen_set,
105 struct timeval *timeout)
106{
107 int mdnsd_conn_fd;
108 DNSServiceErrorType err;
109 struct dns_reg_state *dns_state = *dns_state_ptr;
110
111 if (dns_state == NULL) {
112 dns_state = talloc_zero(NULL, struct dns_reg_state);
113 *dns_state_ptr = dns_state;
114 if (dns_state == NULL) {
115 return;
116 }
117 }
118
119 /* Quit if a re-try attempt has been scheduled. */
120 if (dns_state->retry_handler != NULL) {
121 return;
122 }
123
124 /* If a registration is active add conn
125 * fd to select listen_set and return
126 */
127 if (dns_state->srv_ref != NULL) {
128 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
129 FD_SET(mdnsd_conn_fd, listen_set);
130 return;
131 }
132
133 DEBUG(6, ("registering _smb._tcp service on port %d\n", port));
134
135 /* Register service with DNS. Connects with the mDNS
136 * daemon running on the local system to perform DNS
137 * service registration.
138 */
139 err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */,
140 kDNSServiceInterfaceIndexAny,
141 NULL /* service name */,
142 "_smb._tcp" /* service type */,
143 NULL /* domain */,
144 "" /* SRV target host name */,
145 htons(port),
146 0 /* TXT record len */,
147 NULL /* TXT record data */,
148 NULL /* callback func */,
149 NULL /* callback context */);
150
151 if (err != kDNSServiceErr_NoError) {
152 /* Failed to register service. Schedule a re-try attempt.
153 */
154 DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
155 schedule_dns_register_smbd_retry(dns_state, timeout);
156 return;
157 }
158
159 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
160 FD_SET(mdnsd_conn_fd, listen_set);
161 *maxfd = MAX(*maxfd, mdnsd_conn_fd);
162 *timeout = timeval_zero();
163
164}
165
166/* Processes reply from mDNS daemon. Returns true if a reply was received */
167bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
168 fd_set *lfds, struct timeval *timeout)
169{
170 int mdnsd_conn_fd = -1;
171
172 if (dns_state->srv_ref == NULL) {
173 return false;
174 }
175
176 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
177
178 /* Process reply from daemon. Handles any errors. */
179 if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) {
180 DNSServiceErrorType err;
181
182 err = DNSServiceProcessResult(dns_state->srv_ref);
183 if (err != kDNSServiceErr_NoError) {
184 DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
185 err));
186 schedule_dns_register_smbd_retry(dns_state, timeout);
187 }
188
189 return true;
190 }
191
192 return false;
193}
194
195#else /* WITH_DNSSD_SUPPORT */
196
197 void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
198 unsigned port,
199 int *maxfd,
200 fd_set *listen_set,
201 struct timeval *timeout)
202{}
203
204 void dns_register_close(struct dns_reg_state ** dns_state_ptr)
205{}
206
207 bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
208 fd_set *lfds, struct timeval *timeout)
209{
210 return false;
211}
212
213#endif /* WITH_DNSSD_SUPPORT */
Note: See TracBrowser for help on using the repository browser.