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 
add_subnet(struct subnet_record * subrec)46 static void add_subnet(struct subnet_record *subrec)
47 {
48 	DLIST_ADD(subnetlist, subrec);
49 }
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 
close_subnet(struct subnet_record * subrec)57 void close_subnet(struct subnet_record *subrec)
58 {
59 	if (subrec->nmb_sock != -1) {
60 		close(subrec->nmb_sock);
61 		subrec->nmb_sock = -1;
62 	}
63 	if (subrec->nmb_bcast != -1) {
64 		close(subrec->nmb_bcast);
65 		subrec->nmb_bcast = -1;
66 	}
67 	if (subrec->dgram_sock != -1) {
68 		close(subrec->dgram_sock);
69 		subrec->dgram_sock = -1;
70 	}
71 	if (subrec->dgram_bcast != -1) {
72 		close(subrec->dgram_bcast);
73 		subrec->dgram_bcast = -1;
74 	}
75 
76 	DLIST_REMOVE(subnetlist, subrec);
77 }
78 
79 /****************************************************************************
80   Create a subnet entry.
81   ****************************************************************************/
82 
make_subnet(const char * name,enum subnet_type type,struct in_addr myip,struct in_addr bcast_ip,struct in_addr mask_ip)83 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 	struct subnet_record *subrec = NULL;
88 	int nmb_sock = -1;
89 	int dgram_sock = -1;
90 	int nmb_bcast = -1;
91 	int dgram_bcast = -1;
92 	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 	if (type == NORMAL_SUBNET) {
98 		struct sockaddr_storage ss;
99 		struct sockaddr_storage ss_bcast;
100 
101 		in_addr_to_sockaddr_storage(&ss, myip);
102 		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 		nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,
111 					  0, &ss, true);
112 		if (nmb_sock == -1) {
113 			DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
114 			DEBUGADD(0,("  Failed to open nmb socket on interface %s ",
115 				    inet_ntoa(myip)));
116 			DEBUGADD(0,("for port %d.  ", global_nmb_port));
117 			DEBUGADD(0,("Error was %s\n", strerror(errno)));
118 			goto failed;
119 		}
120 		set_socket_options(nmb_sock,"SO_BROADCAST");
121 		set_blocking(nmb_sock, false);
122 
123 		if (bind_bcast) {
124 			nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port,
125 						   0, &ss_bcast, true);
126 			if (nmb_bcast == -1) {
127 				DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
128 				DEBUGADD(0,("  Failed to open nmb bcast socket on interface %s ",
129 					    inet_ntoa(bcast_ip)));
130 				DEBUGADD(0,("for port %d.  ", global_nmb_port));
131 				DEBUGADD(0,("Error was %s\n", strerror(errno)));
132 				goto failed;
133 			}
134 			set_socket_options(nmb_bcast, "SO_BROADCAST");
135 			set_blocking(nmb_bcast, false);
136 		}
137 
138 		dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
139 					    3, &ss, true);
140 		if (dgram_sock == -1) {
141 			DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
142 			DEBUGADD(0,("  Failed to open dgram socket on interface %s ",
143 				    inet_ntoa(myip)));
144 			DEBUGADD(0,("for port %d.  ", DGRAM_PORT));
145 			DEBUGADD(0,("Error was %s\n", strerror(errno)));
146 			goto failed;
147 		}
148 		set_socket_options(dgram_sock, "SO_BROADCAST");
149 		set_blocking(dgram_sock, false);
150 
151 		if (bind_bcast) {
152 			dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
153 						     3, &ss_bcast, true);
154 			if (dgram_bcast == -1) {
155 				DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
156 				DEBUGADD(0,("  Failed to open dgram bcast socket on interface %s ",
157 					    inet_ntoa(bcast_ip)));
158 				DEBUGADD(0,("for port %d.  ", DGRAM_PORT));
159 				DEBUGADD(0,("Error was %s\n", strerror(errno)));
160 				goto failed;
161 			}
162 			set_socket_options(dgram_bcast, "SO_BROADCAST");
163 			set_blocking(dgram_bcast, false);
164 		}
165 	}
166 
167 	subrec = SMB_MALLOC_P(struct subnet_record);
168 	if (!subrec) {
169 		DEBUG(0,("make_subnet: malloc fail !\n"));
170 		goto failed;
171 	}
172 
173 	ZERO_STRUCTP(subrec);
174 
175 	if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
176 		DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
177 		goto failed;
178 	}
179 
180 	DEBUG(2, ("making subnet name:%s ", name ));
181 	DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
182 	DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
183 
184 	subrec->namelist_changed = False;
185 	subrec->work_changed = False;
186 
187 	subrec->bcast_ip = bcast_ip;
188 	subrec->mask_ip  = mask_ip;
189 	subrec->myip = myip;
190 	subrec->type = type;
191 	subrec->nmb_sock = nmb_sock;
192 	subrec->nmb_bcast = nmb_bcast;
193 	subrec->dgram_sock = dgram_sock;
194 	subrec->dgram_bcast = dgram_bcast;
195 
196 	return subrec;
197 
198 failed:
199 	SAFE_FREE(subrec);
200 	if (nmb_sock != -1) {
201 		close(nmb_sock);
202 	}
203 	if (nmb_bcast != -1) {
204 		close(nmb_bcast);
205 	}
206 	if (dgram_sock != -1) {
207 		close(dgram_sock);
208 	}
209 	if (dgram_bcast != -1) {
210 		close(dgram_bcast);
211 	}
212 	return NULL;
213 }
214 
215 /****************************************************************************
216   Create a normal subnet
217 **************************************************************************/
218 
make_normal_subnet(const struct interface * iface)219 struct subnet_record *make_normal_subnet(const struct interface *iface)
220 {
221 
222 	struct subnet_record *subrec;
223 	const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
224 	const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
225 	const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
226 
227 	subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
228 			     *pip, *pbcast, *pnmask);
229 	if (subrec) {
230 		add_subnet(subrec);
231 	}
232 	return subrec;
233 }
234 
235 /****************************************************************************
236   Create subnet entries.
237 **************************************************************************/
238 
create_subnets(void)239 bool create_subnets(void)
240 {
241 	/* We only count IPv4 interfaces whilst we're waiting. */
242 	int num_interfaces;
243 	int i;
244 	struct in_addr unicast_ip, ipzero;
245 
246   try_interfaces_again:
247 
248 	/* Only count IPv4, non-loopback interfaces. */
249 	if (iface_count_v4_nl() == 0) {
250 		daemon_status("nmbd",
251 			      "No local IPv4 non-loopback interfaces "
252 			      "available, waiting for interface ...");
253 		DEBUG(0,("NOTE: NetBIOS name resolution is not supported for "
254 			 "Internet Protocol Version 6 (IPv6).\n"));
255 	}
256 
257 	/* We only count IPv4, non-loopback interfaces here. */
258 	while (iface_count_v4_nl() == 0) {
259 		void (*saved_handler)(int);
260 
261 		/*
262 		 * Whilst we're waiting for an interface, allow SIGTERM to
263 		 * cause us to exit.
264 		 */
265 
266 		saved_handler = CatchSignal(SIGTERM, SIG_DFL);
267 
268 		sleep(5);
269 		load_interfaces();
270 
271 		/*
272 		 * We got an interface, restore our normal term handler.
273 		 */
274 
275 		CatchSignal(SIGTERM, saved_handler);
276 	}
277 
278 	/*
279 	 * Here we count v4 and v6 - we know there's at least one
280 	 * IPv4 interface and we filter on it below.
281 	 */
282 	num_interfaces = iface_count();
283 
284 	/*
285 	 * Create subnets from all the local interfaces and thread them onto
286 	 * the linked list.
287 	 */
288 
289 	for (i = 0 ; i < num_interfaces; i++) {
290 		const struct interface *iface = get_interface(i);
291 
292 		if (!iface) {
293 			DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
294 			continue;
295 		}
296 
297 		/* Ensure we're only dealing with IPv4 here. */
298 		if (iface->ip.ss_family != AF_INET) {
299 			DEBUG(2,("create_subnets: "
300 				"ignoring non IPv4 interface.\n"));
301 			continue;
302 		}
303 
304 		/*
305 		 * We don't want to add a loopback interface, in case
306 		 * someone has added 127.0.0.1 for smbd, nmbd needs to
307 		 * ignore it here. JRA.
308 		 */
309 
310 		if (is_loopback_addr((const struct sockaddr *)&iface->ip)) {
311 			DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
312 			continue;
313 		}
314 
315 		if (!make_normal_subnet(iface))
316 			return False;
317 	}
318 
319         /* We must have at least one subnet. */
320 	if (subnetlist == NULL) {
321 		void (*saved_handler)(int);
322 
323 		DEBUG(0,("create_subnets: Unable to create any subnet from "
324 				"given interfaces. Is your interface line in "
325 				"smb.conf correct ?\n"));
326 
327 		saved_handler = CatchSignal(SIGTERM, SIG_DFL);
328 
329 		sleep(5);
330 		load_interfaces();
331 
332 		CatchSignal(SIGTERM, saved_handler);
333 		goto try_interfaces_again;
334 	}
335 
336 	if (lp_we_are_a_wins_server()) {
337 		/* Pick the first interface IPv4 address as the WINS server
338 		 * ip. */
339 		const struct in_addr *nip = first_ipv4_iface();
340 
341 		if (!nip) {
342 			return False;
343 		}
344 
345 		unicast_ip = *nip;
346 	} else {
347 		/* note that we do not set the wins server IP here. We just
348 			set it at zero and let the wins registration code cope
349 			with getting the IPs right for each packet */
350 		zero_ip_v4(&unicast_ip);
351 	}
352 
353 	/*
354 	 * Create the unicast and remote broadcast subnets.
355 	 * Don't put these onto the linked list.
356 	 * The ip address of the unicast subnet is set to be
357 	 * the WINS server address, if it exists, or ipzero if not.
358 	 */
359 
360 	unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
361 				unicast_ip, unicast_ip, unicast_ip);
362 
363 	zero_ip_v4(&ipzero);
364 
365 	remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
366 				REMOTE_BROADCAST_SUBNET,
367 				ipzero, ipzero, ipzero);
368 
369 	if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
370 		return False;
371 
372 	/*
373 	 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
374 	 * the linked list.
375 	 */
376 
377 	if (lp_we_are_a_wins_server()) {
378 		if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
379 						WINS_SERVER_SUBNET,
380 						ipzero, ipzero, ipzero )) == NULL )
381 			return False;
382 	}
383 
384 	return True;
385 }
386 
387 /*******************************************************************
388 Function to tell us if we can use the unicast subnet.
389 ******************************************************************/
390 
we_are_a_wins_client(void)391 bool we_are_a_wins_client(void)
392 {
393 	if (wins_srv_count() > 0) {
394 		return True;
395 	}
396 
397 	return False;
398 }
399 
400 /*******************************************************************
401 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
402 ******************************************************************/
403 
get_next_subnet_maybe_unicast(struct subnet_record * subrec)404 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
405 {
406 	if(subrec == unicast_subnet)
407 		return NULL;
408 	else if((subrec->next == NULL) && we_are_a_wins_client())
409 		return unicast_subnet;
410 	else
411 		return subrec->next;
412 }
413 
414 /*******************************************************************
415  Access function used by retransmit_or_expire_response_records() in
416  nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
417  Needed when we need to enumerate all the broadcast, unicast and
418  WINS subnets.
419 ******************************************************************/
420 
get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record * subrec)421 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
422 {
423 	if(subrec == unicast_subnet) {
424 		if(wins_server_subnet)
425 			return wins_server_subnet;
426 		else
427 			return NULL;
428 	}
429 
430 	if(wins_server_subnet && subrec == wins_server_subnet)
431 		return NULL;
432 
433 	if((subrec->next == NULL) && we_are_a_wins_client())
434 		return unicast_subnet;
435 	else
436 		return subrec->next;
437 }
438