Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : NBT netbios routines and daemon - version 2
4 : Copyright (C) Andrew Tridgell 1994-1998
5 : Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 : Copyright (C) Jeremy Allison 1994-1998
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 :
21 : Revision History:
22 :
23 : */
24 :
25 : #include "includes.h"
26 : #include "nmbd/nmbd.h"
27 :
28 : extern int global_nmb_port;
29 :
30 : /* This is the broadcast subnets database. */
31 : struct subnet_record *subnetlist = NULL;
32 :
33 : /* Extra subnets - keep these separate so enumeration code doesn't
34 : run onto it by mistake. */
35 :
36 : struct subnet_record *unicast_subnet = NULL;
37 : struct subnet_record *remote_broadcast_subnet = NULL;
38 : struct subnet_record *wins_server_subnet = NULL;
39 :
40 : extern uint16_t samba_nb_type; /* Samba's NetBIOS name type. */
41 :
42 : /****************************************************************************
43 : Add a subnet into the list.
44 : **************************************************************************/
45 :
46 43 : static void add_subnet(struct subnet_record *subrec)
47 : {
48 43 : DLIST_ADD(subnetlist, subrec);
49 43 : }
50 :
51 : /****************************************************************************
52 : stop listening on a subnet
53 : we don't free the record as we don't have proper reference counting for it
54 : yet and it may be in use by a response record
55 : ****************************************************************************/
56 :
57 0 : void close_subnet(struct subnet_record *subrec)
58 : {
59 0 : if (subrec->nmb_sock != -1) {
60 0 : close(subrec->nmb_sock);
61 0 : subrec->nmb_sock = -1;
62 : }
63 0 : if (subrec->nmb_bcast != -1) {
64 0 : close(subrec->nmb_bcast);
65 0 : subrec->nmb_bcast = -1;
66 : }
67 0 : if (subrec->dgram_sock != -1) {
68 0 : close(subrec->dgram_sock);
69 0 : subrec->dgram_sock = -1;
70 : }
71 0 : if (subrec->dgram_bcast != -1) {
72 0 : close(subrec->dgram_bcast);
73 0 : subrec->dgram_bcast = -1;
74 : }
75 :
76 0 : DLIST_REMOVE(subnetlist, subrec);
77 0 : }
78 :
79 : /****************************************************************************
80 : Create a subnet entry.
81 : ****************************************************************************/
82 :
83 129 : static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
84 : struct in_addr myip, struct in_addr bcast_ip,
85 : struct in_addr mask_ip)
86 : {
87 129 : struct subnet_record *subrec = NULL;
88 129 : int nmb_sock = -1;
89 129 : int dgram_sock = -1;
90 129 : int nmb_bcast = -1;
91 129 : int dgram_bcast = -1;
92 129 : bool bind_bcast = lp_nmbd_bind_explicit_broadcast();
93 :
94 : /* Check if we are creating a non broadcast subnet - if so don't create
95 : sockets. */
96 :
97 129 : if (type == NORMAL_SUBNET) {
98 : struct sockaddr_storage ss;
99 : struct sockaddr_storage ss_bcast;
100 :
101 43 : in_addr_to_sockaddr_storage(&ss, myip);
102 43 : in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip);
103 :
104 : /*
105 : * Attempt to open the sockets on port 137/138 for this interface
106 : * and bind them.
107 : * Fail the subnet creation if this fails.
108 : */
109 :
110 43 : nmb_sock = open_socket_in(
111 : SOCK_DGRAM, &ss, global_nmb_port, true);
112 43 : if (nmb_sock < 0) {
113 0 : DBG_ERR("Failed to open nmb socket on interface %s "
114 : "for port %d: %s\n",
115 : inet_ntoa(myip),
116 : global_nmb_port,
117 : strerror(-nmb_sock));
118 0 : goto failed;
119 : }
120 43 : set_socket_options(nmb_sock,"SO_BROADCAST");
121 43 : set_blocking(nmb_sock, false);
122 :
123 43 : if (bind_bcast) {
124 43 : nmb_bcast = open_socket_in(
125 : SOCK_DGRAM, &ss_bcast, global_nmb_port, true);
126 43 : if (nmb_bcast < 0) {
127 0 : DBG_ERR("Failed to open nmb bcast socket on "
128 : "interface %s for port %d: %s\n",
129 : inet_ntoa(myip),
130 : global_nmb_port,
131 : strerror(-nmb_bcast));
132 0 : goto failed;
133 : }
134 43 : set_socket_options(nmb_bcast, "SO_BROADCAST");
135 43 : set_blocking(nmb_bcast, false);
136 : }
137 :
138 43 : dgram_sock = open_socket_in(SOCK_DGRAM, &ss, DGRAM_PORT, true);
139 43 : if (dgram_sock < 0) {
140 0 : DBG_ERR("Failed to open dgram socket on "
141 : "interface %s for port %d: %s\n",
142 : inet_ntoa(myip),
143 : DGRAM_PORT,
144 : strerror(-dgram_sock));
145 0 : goto failed;
146 : }
147 43 : set_socket_options(dgram_sock, "SO_BROADCAST");
148 43 : set_blocking(dgram_sock, false);
149 :
150 43 : if (bind_bcast) {
151 43 : dgram_bcast = open_socket_in(
152 : SOCK_DGRAM, &ss_bcast, DGRAM_PORT, true);
153 43 : if (dgram_bcast < 0) {
154 0 : DBG_ERR("Failed to open dgram bcast socket on "
155 : "interface %s for port %d: %s\n",
156 : inet_ntoa(myip),
157 : DGRAM_PORT,
158 : strerror(-dgram_bcast));
159 0 : goto failed;
160 : }
161 43 : set_socket_options(dgram_bcast, "SO_BROADCAST");
162 43 : set_blocking(dgram_bcast, false);
163 : }
164 : }
165 :
166 129 : subrec = SMB_MALLOC_P(struct subnet_record);
167 129 : if (!subrec) {
168 0 : DEBUG(0,("make_subnet: malloc fail !\n"));
169 0 : goto failed;
170 : }
171 :
172 129 : ZERO_STRUCTP(subrec);
173 :
174 129 : if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
175 0 : DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
176 0 : goto failed;
177 : }
178 :
179 129 : DEBUG(2, ("making subnet name:%s ", name ));
180 129 : DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
181 129 : DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
182 :
183 129 : subrec->namelist_changed = False;
184 129 : subrec->work_changed = False;
185 :
186 129 : subrec->bcast_ip = bcast_ip;
187 129 : subrec->mask_ip = mask_ip;
188 129 : subrec->myip = myip;
189 129 : subrec->type = type;
190 129 : subrec->nmb_sock = nmb_sock;
191 129 : subrec->nmb_bcast = nmb_bcast;
192 129 : subrec->dgram_sock = dgram_sock;
193 129 : subrec->dgram_bcast = dgram_bcast;
194 :
195 129 : return subrec;
196 :
197 0 : failed:
198 0 : SAFE_FREE(subrec);
199 0 : if (nmb_sock >= 0) {
200 0 : close(nmb_sock);
201 : }
202 0 : if (nmb_bcast >= 0) {
203 0 : close(nmb_bcast);
204 : }
205 0 : if (dgram_sock >= 0) {
206 0 : close(dgram_sock);
207 : }
208 0 : if (dgram_bcast >= 0) {
209 0 : close(dgram_bcast);
210 : }
211 0 : return NULL;
212 : }
213 :
214 : /****************************************************************************
215 : Create a normal subnet
216 : **************************************************************************/
217 :
218 43 : struct subnet_record *make_normal_subnet(const struct interface *iface)
219 : {
220 :
221 : struct subnet_record *subrec;
222 43 : const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
223 43 : const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
224 43 : const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
225 :
226 43 : subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
227 : *pip, *pbcast, *pnmask);
228 43 : if (subrec) {
229 43 : add_subnet(subrec);
230 : }
231 43 : return subrec;
232 : }
233 :
234 : /****************************************************************************
235 : Create subnet entries.
236 : **************************************************************************/
237 :
238 43 : bool create_subnets(void)
239 : {
240 : /* We only count IPv4 interfaces whilst we're waiting. */
241 : int num_interfaces;
242 : int i;
243 : struct in_addr unicast_ip, ipzero;
244 :
245 43 : try_interfaces_again:
246 :
247 : /* Only count IPv4, non-loopback interfaces. */
248 43 : if (iface_count_v4_nl() == 0) {
249 0 : daemon_status("nmbd",
250 : "No local IPv4 non-loopback interfaces "
251 : "available, waiting for interface ...");
252 0 : DEBUG(0,("NOTE: NetBIOS name resolution is not supported for "
253 : "Internet Protocol Version 6 (IPv6).\n"));
254 : }
255 :
256 : /* We only count IPv4, non-loopback interfaces here. */
257 43 : while (iface_count_v4_nl() == 0) {
258 : void (*saved_handler)(int);
259 :
260 : /*
261 : * Whilst we're waiting for an interface, allow SIGTERM to
262 : * cause us to exit.
263 : */
264 :
265 0 : saved_handler = CatchSignal(SIGTERM, SIG_DFL);
266 :
267 0 : usleep(NMBD_WAIT_INTERFACES_TIME_USEC);
268 0 : load_interfaces();
269 :
270 : /*
271 : * We got an interface, restore our normal term handler.
272 : */
273 :
274 0 : CatchSignal(SIGTERM, saved_handler);
275 : }
276 :
277 : /*
278 : * Here we count v4 and v6 - we know there's at least one
279 : * IPv4 interface and we filter on it below.
280 : */
281 43 : num_interfaces = iface_count();
282 :
283 : /*
284 : * Create subnets from all the local interfaces and thread them onto
285 : * the linked list.
286 : */
287 :
288 129 : for (i = 0 ; i < num_interfaces; i++) {
289 86 : const struct interface *iface = get_interface(i);
290 :
291 86 : if (!iface) {
292 0 : DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
293 0 : continue;
294 : }
295 :
296 : /* Ensure we're only dealing with IPv4 here. */
297 86 : if (iface->ip.ss_family != AF_INET) {
298 43 : DEBUG(2,("create_subnets: "
299 : "ignoring non IPv4 interface.\n"));
300 43 : continue;
301 : }
302 :
303 : /*
304 : * We don't want to add a loopback interface, in case
305 : * someone has added 127.0.0.1 for smbd, nmbd needs to
306 : * ignore it here. JRA.
307 : */
308 :
309 43 : if (is_loopback_addr((const struct sockaddr *)&iface->ip)) {
310 0 : DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
311 0 : continue;
312 : }
313 :
314 43 : if (!make_normal_subnet(iface))
315 0 : return False;
316 : }
317 :
318 : /* We must have at least one subnet. */
319 43 : if (subnetlist == NULL) {
320 : void (*saved_handler)(int);
321 :
322 0 : DEBUG(0,("create_subnets: Unable to create any subnet from "
323 : "given interfaces. Is your interface line in "
324 : "smb.conf correct ?\n"));
325 :
326 0 : saved_handler = CatchSignal(SIGTERM, SIG_DFL);
327 :
328 0 : usleep(NMBD_WAIT_INTERFACES_TIME_USEC);
329 0 : load_interfaces();
330 :
331 0 : CatchSignal(SIGTERM, saved_handler);
332 0 : goto try_interfaces_again;
333 : }
334 :
335 43 : if (lp_we_are_a_wins_server()) {
336 : /* Pick the first interface IPv4 address as the WINS server
337 : * ip. */
338 0 : const struct in_addr *nip = first_ipv4_iface();
339 :
340 0 : if (!nip) {
341 0 : return False;
342 : }
343 :
344 0 : unicast_ip = *nip;
345 : } else {
346 : /* note that we do not set the wins server IP here. We just
347 : set it at zero and let the wins registration code cope
348 : with getting the IPs right for each packet */
349 43 : zero_ip_v4(&unicast_ip);
350 : }
351 :
352 : /*
353 : * Create the unicast and remote broadcast subnets.
354 : * Don't put these onto the linked list.
355 : * The ip address of the unicast subnet is set to be
356 : * the WINS server address, if it exists, or ipzero if not.
357 : */
358 :
359 43 : unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
360 : unicast_ip, unicast_ip, unicast_ip);
361 :
362 43 : zero_ip_v4(&ipzero);
363 :
364 43 : remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
365 : REMOTE_BROADCAST_SUBNET,
366 : ipzero, ipzero, ipzero);
367 :
368 43 : if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
369 0 : return False;
370 :
371 : /*
372 : * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
373 : * the linked list.
374 : */
375 :
376 43 : if (lp_we_are_a_wins_server()) {
377 0 : if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
378 : WINS_SERVER_SUBNET,
379 : ipzero, ipzero, ipzero )) == NULL )
380 0 : return False;
381 : }
382 :
383 43 : return True;
384 : }
385 :
386 : /*******************************************************************
387 : Function to tell us if we can use the unicast subnet.
388 : ******************************************************************/
389 :
390 87636 : bool we_are_a_wins_client(void)
391 : {
392 87636 : if (wins_srv_count() > 0) {
393 0 : return True;
394 : }
395 :
396 87636 : return False;
397 : }
398 :
399 : /*******************************************************************
400 : Access function used by NEXT_SUBNET_INCLUDING_UNICAST
401 : ******************************************************************/
402 :
403 15114 : struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
404 : {
405 15114 : if(subrec == unicast_subnet)
406 0 : return NULL;
407 15114 : else if((subrec->next == NULL) && we_are_a_wins_client())
408 0 : return unicast_subnet;
409 : else
410 15114 : return subrec->next;
411 : }
412 :
413 : /*******************************************************************
414 : Access function used by retransmit_or_expire_response_records() in
415 : nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
416 : Needed when we need to enumerate all the broadcast, unicast and
417 : WINS subnets.
418 : ******************************************************************/
419 :
420 17147 : struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
421 : {
422 17147 : if(subrec == unicast_subnet) {
423 0 : if(wins_server_subnet)
424 0 : return wins_server_subnet;
425 : else
426 0 : return NULL;
427 : }
428 :
429 17147 : if(wins_server_subnet && subrec == wins_server_subnet)
430 0 : return NULL;
431 :
432 17147 : if((subrec->next == NULL) && we_are_a_wins_client())
433 0 : return unicast_subnet;
434 : else
435 17147 : return subrec->next;
436 : }
|