Line data Source code
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 : #include "smbd/smbd.h"
22 :
23 : /* Uses DNS service discovery (libdns_sd) to
24 : * register the SMB service. SMB service is registered
25 : * on ".local" domain via Multicast DNS & any
26 : * other unicast DNS domains available.
27 : *
28 : * Users use the smbclient -B (Browse) option to
29 : * browse for advertised SMB services.
30 : */
31 :
32 : #define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */
33 :
34 : #ifdef WITH_DNSSD_SUPPORT
35 :
36 : #include <dns_sd.h>
37 :
38 : struct dns_reg_state {
39 : struct tevent_context *event_ctx;
40 : uint16_t port;
41 : DNSServiceRef srv_ref;
42 : struct tevent_timer *te;
43 : int fd;
44 : struct tevent_fd *fde;
45 : };
46 :
47 : static int dns_reg_state_destructor(struct dns_reg_state *dns_state)
48 : {
49 : if (dns_state->srv_ref != NULL) {
50 : /* Close connection to the mDNS daemon */
51 : DNSServiceRefDeallocate(dns_state->srv_ref);
52 : dns_state->srv_ref = NULL;
53 : }
54 :
55 : /* Clear event handler */
56 : TALLOC_FREE(dns_state->te);
57 : TALLOC_FREE(dns_state->fde);
58 : dns_state->fd = -1;
59 :
60 : return 0;
61 : }
62 :
63 : static void dns_register_smbd_retry(struct tevent_context *ctx,
64 : struct tevent_timer *te,
65 : struct timeval now,
66 : void *private_data);
67 : static void dns_register_smbd_fde_handler(struct tevent_context *ev,
68 : struct tevent_fd *fde,
69 : uint16_t flags,
70 : void *private_data);
71 :
72 : static bool dns_register_smbd_schedule(struct dns_reg_state *dns_state,
73 : struct timeval tval)
74 : {
75 : dns_reg_state_destructor(dns_state);
76 :
77 : dns_state->te = tevent_add_timer(dns_state->event_ctx,
78 : dns_state,
79 : tval,
80 : dns_register_smbd_retry,
81 : dns_state);
82 : if (!dns_state->te) {
83 : return false;
84 : }
85 :
86 : return true;
87 : }
88 :
89 : static void dns_register_smbd_retry(struct tevent_context *ctx,
90 : struct tevent_timer *te,
91 : struct timeval now,
92 : void *private_data)
93 : {
94 : struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
95 : struct dns_reg_state);
96 : DNSServiceErrorType err;
97 :
98 : dns_reg_state_destructor(dns_state);
99 :
100 : DEBUG(6, ("registering _smb._tcp service on port %d\n",
101 : dns_state->port));
102 :
103 : /* Register service with DNS. Connects with the mDNS
104 : * daemon running on the local system to perform DNS
105 : * service registration.
106 : */
107 : err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */,
108 : kDNSServiceInterfaceIndexAny,
109 : NULL /* service name */,
110 : "_smb._tcp" /* service type */,
111 : NULL /* domain */,
112 : "" /* SRV target host name */,
113 : htons(dns_state->port),
114 : 0 /* TXT record len */,
115 : NULL /* TXT record data */,
116 : NULL /* callback func */,
117 : NULL /* callback context */);
118 :
119 : if (err != kDNSServiceErr_NoError) {
120 : /* Failed to register service. Schedule a re-try attempt.
121 : */
122 : DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
123 : goto retry;
124 : }
125 :
126 : dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref);
127 : if (dns_state->fd == -1) {
128 : goto retry;
129 : }
130 :
131 : dns_state->fde = tevent_add_fd(dns_state->event_ctx,
132 : dns_state,
133 : dns_state->fd,
134 : TEVENT_FD_READ,
135 : dns_register_smbd_fde_handler,
136 : dns_state);
137 : if (!dns_state->fde) {
138 : goto retry;
139 : }
140 :
141 : return;
142 : retry:
143 : dns_register_smbd_schedule(dns_state,
144 : timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
145 : }
146 :
147 : /* Processes reply from mDNS daemon. Returns true if a reply was received */
148 : static void dns_register_smbd_fde_handler(struct tevent_context *ev,
149 : struct tevent_fd *fde,
150 : uint16_t flags,
151 : void *private_data)
152 : {
153 : struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
154 : struct dns_reg_state);
155 : DNSServiceErrorType err;
156 :
157 : err = DNSServiceProcessResult(dns_state->srv_ref);
158 : if (err != kDNSServiceErr_NoError) {
159 : DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
160 : err));
161 : goto retry;
162 : }
163 :
164 : talloc_free(dns_state);
165 : return;
166 :
167 : retry:
168 : dns_register_smbd_schedule(dns_state,
169 : timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
170 : }
171 :
172 : bool smbd_setup_mdns_registration(struct tevent_context *ev,
173 : TALLOC_CTX *mem_ctx,
174 : uint16_t port)
175 : {
176 : struct dns_reg_state *dns_state;
177 :
178 : dns_state = talloc_zero(mem_ctx, struct dns_reg_state);
179 : if (dns_state == NULL) {
180 : return false;
181 : }
182 : dns_state->event_ctx = ev;
183 : dns_state->port = port;
184 : dns_state->fd = -1;
185 :
186 : talloc_set_destructor(dns_state, dns_reg_state_destructor);
187 :
188 : return dns_register_smbd_schedule(dns_state, timeval_zero());
189 : }
190 :
191 : #else /* WITH_DNSSD_SUPPORT */
192 :
193 0 : bool smbd_setup_mdns_registration(struct tevent_context *ev,
194 : TALLOC_CTX *mem_ctx,
195 : uint16_t port)
196 : {
197 0 : return true;
198 : }
199 :
200 : #endif /* WITH_DNSSD_SUPPORT */
|