Fix denial of service - memory corruption.
[Samba.git] / source / smbd / dnsregister.c
blob3c689b9cf3e9233088de523c25fb2bd57179877f
1 /*
2 Unix SMB/CIFS implementation.
3 DNS-SD registration
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/>.
20 #include <includes.h>
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
35 #include <dns_sd.h>
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) {
47 return;
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,
68 struct timeval now,
69 void *private_data)
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(),
86 NULL,
87 timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0),
88 dns_register_smbd_retry,
89 dns_state);
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
98 * better.
100 void 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)
106 int mdnsd_conn_fd;
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) {
114 return;
118 /* Quit if a re-try attempt has been scheduled. */
119 if (dns_state->retry_handler != NULL) {
120 return;
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 if (mdnsd_conn_fd < 0 || mdnsd_conn_fd >= FD_SETSIZE) {
129 return;
131 FD_SET(mdnsd_conn_fd, listen_set);
132 return;
135 DEBUG(6, ("registering _smb._tcp service on port %d\n", port));
137 /* Register service with DNS. Connects with the mDNS
138 * daemon running on the local system to perform DNS
139 * service registration.
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 */);
153 if (err != kDNSServiceErr_NoError) {
154 /* Failed to register service. Schedule a re-try attempt.
156 DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
157 schedule_dns_register_smbd_retry(dns_state, timeout);
158 return;
161 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
162 if (mdnsd_conn_fd < 0 || mdnsd_conn_fd >= FD_SETSIZE) {
163 return;
165 FD_SET(mdnsd_conn_fd, listen_set);
166 *maxfd = MAX(*maxfd, mdnsd_conn_fd);
167 *timeout = timeval_zero();
171 /* Processes reply from mDNS daemon. Returns true if a reply was received */
172 bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
173 fd_set *lfds, struct timeval *timeout)
175 int mdnsd_conn_fd = -1;
177 if ((dns_state == NULL) || (dns_state->srv_ref == NULL)) {
178 return false;
181 mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
183 /* Process reply from daemon. Handles any errors. */
184 if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) {
185 DNSServiceErrorType err;
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);
194 return true;
197 return false;
200 #else /* WITH_DNSSD_SUPPORT */
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)
209 void dns_register_close(struct dns_reg_state ** dns_state_ptr)
212 bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
213 fd_set *lfds, struct timeval *timeout)
215 return false;
218 #endif /* WITH_DNSSD_SUPPORT */