1 /*
2    Unix SMB/CIFS implementation.
3    multiple interface handling
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2007
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "includes.h"
22 #include "lib/socket/interfaces.h"
23 #include "librpc/gen_ndr/ioctl.h"
24 
25 static struct iface_struct *probed_ifaces;
26 static int total_probed;
27 
28 static struct interface *local_interfaces;
29 
30 /****************************************************************************
31  Check if an IP is one of mine.
32 **************************************************************************/
33 
ismyaddr(const struct sockaddr * ip)34 bool ismyaddr(const struct sockaddr *ip)
35 {
36 	struct interface *i;
37 	for (i=local_interfaces;i;i=i->next) {
38 		if (sockaddr_equal((struct sockaddr *)&i->ip,ip)) {
39 			return true;
40 		}
41 	}
42 	return false;
43 }
44 
ismyip_v4(struct in_addr ip)45 bool ismyip_v4(struct in_addr ip)
46 {
47 	struct sockaddr_storage ss;
48 	in_addr_to_sockaddr_storage(&ss, ip);
49 	return ismyaddr((struct sockaddr *)&ss);
50 }
51 
52 /****************************************************************************
53  Try and find an interface that matches an ip. If we cannot, return NULL.
54 **************************************************************************/
55 
iface_find(const struct sockaddr * ip,bool check_mask)56 static struct interface *iface_find(const struct sockaddr *ip,
57 				bool check_mask)
58 {
59 	struct interface *i;
60 
61 	if (is_address_any(ip)) {
62 		return local_interfaces;
63 	}
64 
65 	for (i=local_interfaces;i;i=i->next) {
66 		if (check_mask) {
67 			if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
68 				return i;
69 			}
70 		} else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
71 			return i;
72 		}
73 	}
74 
75 	return NULL;
76 }
77 
78 /****************************************************************************
79  Check if a packet is from a local (known) net.
80 **************************************************************************/
81 
is_local_net(const struct sockaddr * from)82 bool is_local_net(const struct sockaddr *from)
83 {
84 	struct interface *i;
85 	for (i=local_interfaces;i;i=i->next) {
86 		if (same_net(from, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
87 			return true;
88 		}
89 	}
90 	return false;
91 }
92 
93 #if defined(HAVE_IPV6)
setup_linklocal_scope_id(struct sockaddr * pss)94 void setup_linklocal_scope_id(struct sockaddr *pss)
95 {
96 	struct interface *i;
97 	for (i=local_interfaces;i;i=i->next) {
98 		if (sockaddr_equal((struct sockaddr *)&i->ip,pss)) {
99 			struct sockaddr_in6 *psa6 =
100 				(struct sockaddr_in6 *)pss;
101 			psa6->sin6_scope_id = if_nametoindex(i->name);
102 			return;
103 		}
104 	}
105 }
106 #endif
107 
108 /****************************************************************************
109  Check if a packet is from a local (known) net.
110 **************************************************************************/
111 
is_local_net_v4(struct in_addr from)112 bool is_local_net_v4(struct in_addr from)
113 {
114 	struct sockaddr_storage ss;
115 
116 	in_addr_to_sockaddr_storage(&ss, from);
117 	return is_local_net((struct sockaddr *)&ss);
118 }
119 
120 /****************************************************************************
121  How many interfaces do we have ?
122 **************************************************************************/
123 
iface_count(void)124 int iface_count(void)
125 {
126 	int ret = 0;
127 	struct interface *i;
128 
129 	for (i=local_interfaces;i;i=i->next) {
130 		ret++;
131 	}
132 	return ret;
133 }
134 
135 /****************************************************************************
136  How many non-loopback IPv4 interfaces do we have ?
137 **************************************************************************/
138 
iface_count_v4_nl(void)139 int iface_count_v4_nl(void)
140 {
141 	int ret = 0;
142 	struct interface *i;
143 
144 	for (i=local_interfaces;i;i=i->next) {
145 		if (is_loopback_addr((struct sockaddr *)&i->ip)) {
146 			continue;
147 		}
148 		if (i->ip.ss_family == AF_INET) {
149 			ret++;
150 		}
151 	}
152 	return ret;
153 }
154 
155 /****************************************************************************
156  Return a pointer to the in_addr of the first IPv4 interface that's
157  not 0.0.0.0.
158 **************************************************************************/
159 
first_ipv4_iface(void)160 const struct in_addr *first_ipv4_iface(void)
161 {
162 	struct interface *i;
163 
164 	for (i=local_interfaces;i ;i=i->next) {
165 		if ((i->ip.ss_family == AF_INET) &&
166 		    (!is_zero_ip_v4(((struct sockaddr_in *)&i->ip)->sin_addr)))
167 		{
168 			break;
169 		}
170 	}
171 
172 	if (!i) {
173 		return NULL;
174 	}
175 	return &((const struct sockaddr_in *)&i->ip)->sin_addr;
176 }
177 
178 /****************************************************************************
179  Return the Nth interface.
180 **************************************************************************/
181 
get_interface(int n)182 struct interface *get_interface(int n)
183 {
184 	struct interface *i;
185 
186 	for (i=local_interfaces;i && n;i=i->next) {
187 		n--;
188 	}
189 
190 	if (i) {
191 		return i;
192 	}
193 	return NULL;
194 }
195 
196 /****************************************************************************
197  Return IP sockaddr_storage of the Nth interface.
198 **************************************************************************/
199 
iface_n_sockaddr_storage(int n)200 const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
201 {
202 	struct interface *i;
203 
204 	for (i=local_interfaces;i && n;i=i->next) {
205 		n--;
206 	}
207 
208 	if (i) {
209 		return &i->ip;
210 	}
211 	return NULL;
212 }
213 
214 /****************************************************************************
215  Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
216 **************************************************************************/
217 
iface_n_ip_v4(int n)218 const struct in_addr *iface_n_ip_v4(int n)
219 {
220 	struct interface *i;
221 
222 	for (i=local_interfaces;i && n;i=i->next) {
223 		n--;
224 	}
225 
226 	if (i && i->ip.ss_family == AF_INET) {
227 		return &((const struct sockaddr_in *)&i->ip)->sin_addr;
228 	}
229 	return NULL;
230 }
231 
232 /****************************************************************************
233  Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
234 **************************************************************************/
235 
iface_n_bcast_v4(int n)236 const struct in_addr *iface_n_bcast_v4(int n)
237 {
238 	struct interface *i;
239 
240 	for (i=local_interfaces;i && n;i=i->next) {
241 		n--;
242 	}
243 
244 	if (i && i->ip.ss_family == AF_INET) {
245 		return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
246 	}
247 	return NULL;
248 }
249 
250 /****************************************************************************
251  Return bcast of the Nth interface.
252 **************************************************************************/
253 
iface_n_bcast(int n)254 const struct sockaddr_storage *iface_n_bcast(int n)
255 {
256 	struct interface *i;
257 
258 	for (i=local_interfaces;i && n;i=i->next) {
259 		n--;
260 	}
261 
262 	if (i) {
263 		return &i->bcast;
264 	}
265 	return NULL;
266 }
267 
268 /* these 3 functions return the ip/bcast/nmask for the interface
269    most appropriate for the given ip address. If they can't find
270    an appropriate interface they return the requested field of the
271    first known interface. */
272 
iface_ip(const struct sockaddr * ip)273 const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
274 {
275 	struct interface *i = iface_find(ip, true);
276 	if (i) {
277 		return &i->ip;
278 	}
279 
280 	/* Search for the first interface with
281 	 * matching address family. */
282 
283 	for (i=local_interfaces;i;i=i->next) {
284 		if (i->ip.ss_family == ip->sa_family) {
285 			return &i->ip;
286 		}
287 	}
288 	return NULL;
289 }
290 
291 /*
292   return True if a IP is directly reachable on one of our interfaces
293 */
294 
iface_local(const struct sockaddr * ip)295 bool iface_local(const struct sockaddr *ip)
296 {
297 	return iface_find(ip, true) ? true : false;
298 }
299 
300 /****************************************************************************
301  Add an interface to the linked list of interfaces.
302 ****************************************************************************/
303 
add_interface(const struct iface_struct * ifs)304 static void add_interface(const struct iface_struct *ifs)
305 {
306 	char addr[INET6_ADDRSTRLEN];
307 	struct interface *iface;
308 
309 	if (iface_find((const struct sockaddr *)&ifs->ip, False)) {
310 		DEBUG(3,("add_interface: not adding duplicate interface %s\n",
311 			print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
312 		return;
313 	}
314 
315 	if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
316 		DEBUG(3,("not adding non-broadcast interface %s\n",
317 					ifs->name ));
318 		return;
319 	}
320 
321 	iface = SMB_MALLOC_P(struct interface);
322 	if (!iface) {
323 		return;
324 	}
325 
326 	ZERO_STRUCTPN(iface);
327 
328 	iface->name = SMB_STRDUP(ifs->name);
329 	if (!iface->name) {
330 		SAFE_FREE(iface);
331 		return;
332 	}
333 	iface->flags = ifs->flags;
334 	iface->ip = ifs->ip;
335 	iface->netmask = ifs->netmask;
336 	iface->bcast = ifs->bcast;
337 	iface->linkspeed = ifs->linkspeed;
338 	iface->capability = ifs->capability;
339 	iface->if_index = ifs->if_index;
340 
341 	DLIST_ADD(local_interfaces, iface);
342 
343 	DEBUG(2,("added interface %s ip=%s ",
344 		iface->name,
345 		print_sockaddr(addr, sizeof(addr), &iface->ip) ));
346 	DEBUG(2,("bcast=%s ",
347 		print_sockaddr(addr, sizeof(addr),
348 			&iface->bcast) ));
349 	DEBUG(2,("netmask=%s\n",
350 		print_sockaddr(addr, sizeof(addr),
351 			&iface->netmask) ));
352 }
353 
354 
parse_extra_info(char * key,uint64_t * speed,uint32_t * cap,uint32_t * if_index)355 static void parse_extra_info(char *key, uint64_t *speed, uint32_t *cap,
356 			     uint32_t *if_index)
357 {
358 	while (key != NULL && *key != '\0') {
359 		char *next_key;
360 		char *val;
361 		int error = 0;
362 
363 		next_key = strchr_m(key, ',');
364 		if (next_key != NULL) {
365 			*next_key++ = 0;
366 		}
367 
368 		val = strchr_m(key, '=');
369 		if (val != NULL) {
370 			*val++ = 0;
371 
372 			if (strequal_m(key, "speed")) {
373 				*speed = (uint64_t)smb_strtoull(val,
374 								NULL,
375 								0,
376 								&error,
377 								SMB_STR_STANDARD);
378 				if (error != 0) {
379 					DBG_DEBUG("Invalid speed value (%s)\n", val);
380 				}
381 			} else if (strequal_m(key, "capability")) {
382 				if (strequal_m(val, "RSS")) {
383 					*cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
384 				} else if (strequal(val, "RDMA")) {
385 					*cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
386 				} else {
387 					DBG_WARNING("Capability unknown: "
388 						    "'%s'\n", val);
389 				}
390 			} else if (strequal_m(key, "if_index")) {
391 				*if_index = (uint32_t)smb_strtoul(val,
392 								  NULL,
393 								  0,
394 								  &error,
395 								  SMB_STR_STANDARD);
396 				if (error != 0) {
397 					DBG_DEBUG("Invalid key value (%s)\n", val);
398 				}
399 			} else {
400 				DBG_DEBUG("Key unknown: '%s'\n", key);
401 			}
402 		}
403 
404 		key = next_key;
405 	}
406 }
407 
408 /****************************************************************************
409  Interpret a single element from a interfaces= config line.
410 
411  This handles the following different forms:
412 
413  1) wildcard interface name
414  2) DNS name
415  3) IP/masklen
416  4) ip/mask
417  5) bcast/mask
418 
419  Additional information for an interface can be specified with
420  this extended syntax:
421 
422     interface[;key1=value1[,key2=value2[...]]]
423 
424  where
425  - keys known: 'speed', 'capability', 'if_index'
426  - speed is in bits per second
427  - capabilites known: 'RSS', 'RDMA'
428  - if_index should be used with care, because
429    these indexes should not conicide with indexes
430    the kernel sets...
431 
432 ****************************************************************************/
433 
interpret_interface(char * token)434 static void interpret_interface(char *token)
435 {
436 	struct sockaddr_storage ss;
437 	struct sockaddr_storage ss_mask;
438 	struct sockaddr_storage ss_net;
439 	struct sockaddr_storage ss_bcast;
440 	struct iface_struct ifs;
441 	char *p;
442 	int i;
443 	bool added=false;
444 	bool goodaddr = false;
445 	uint64_t speed = 0;
446 	uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
447 	uint32_t if_index = 0;
448 	bool speed_set = false;
449 	bool cap_set = false;
450 	bool if_index_set = false;
451 
452 	/* first check if it is an interface name */
453 	for (i=0;i<total_probed;i++) {
454 		if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
455 			add_interface(&probed_ifaces[i]);
456 			added = true;
457 		}
458 	}
459 	if (added) {
460 		return;
461 	}
462 
463 	/*
464 	 * extract speed / capability information if present
465 	 */
466 	p = strchr_m(token, ';');
467 	if (p != NULL) {
468 		*p++ = 0;
469 		parse_extra_info(p, &speed, &cap, &if_index);
470 		if (speed != 0) {
471 			speed_set = true;
472 		}
473 		if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
474 			cap_set = true;
475 		}
476 		if (if_index != 0) {
477 			if_index_set = true;
478 		}
479 	}
480 
481 	p = strchr_m(token,'/');
482 	if (p == NULL) {
483 		if (!interpret_string_addr(&ss, token, 0)) {
484 			DEBUG(2, ("interpret_interface: Can't find address "
485 				  "for %s\n", token));
486 			return;
487 		}
488 
489 		for (i=0;i<total_probed;i++) {
490 			if (sockaddr_equal((struct sockaddr *)&ss,
491 				(struct sockaddr *)&probed_ifaces[i].ip))
492 			{
493 				if (speed_set) {
494 					probed_ifaces[i].linkspeed = speed;
495 				}
496 				if (cap_set) {
497 					probed_ifaces[i].capability = cap;
498 				}
499 				if (if_index_set) {
500 					probed_ifaces[i].if_index = if_index;
501 				}
502 				add_interface(&probed_ifaces[i]);
503 				return;
504 			}
505 		}
506 		DEBUG(2,("interpret_interface: "
507 			"can't determine interface for %s\n",
508 			token));
509 		return;
510 	}
511 
512 	/* parse it into an IP address/netmasklength pair */
513 	*p = 0;
514 	goodaddr = interpret_string_addr(&ss, token, 0);
515 	*p++ = '/';
516 
517 	if (!goodaddr) {
518 		DEBUG(2,("interpret_interface: "
519 			"can't determine interface for %s\n",
520 			token));
521 		return;
522 	}
523 
524 	if (strlen(p) > 2) {
525 		goodaddr = interpret_string_addr(&ss_mask, p, 0);
526 		if (!goodaddr) {
527 			DEBUG(2,("interpret_interface: "
528 				"can't determine netmask from %s\n",
529 				p));
530 			return;
531 		}
532 	} else {
533 		int error = 0;
534 		unsigned long val;
535 
536 		val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
537 		if (error != 0) {
538 			DEBUG(2,("interpret_interface: "
539 				"can't determine netmask value from %s\n",
540 				p));
541 			return;
542 		}
543 		if (!make_netmask(&ss_mask, &ss, val)) {
544 			DEBUG(2,("interpret_interface: "
545 				"can't apply netmask value %lu from %s\n",
546 				val,
547 				p));
548 			return;
549 		}
550 	}
551 
552 	make_bcast(&ss_bcast, &ss, &ss_mask);
553 	make_net(&ss_net, &ss, &ss_mask);
554 
555 	/* Maybe the first component was a broadcast address. */
556 	if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
557 		sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
558 		for (i=0;i<total_probed;i++) {
559 			if (same_net((struct sockaddr *)&ss,
560 						 (struct sockaddr *)&probed_ifaces[i].ip,
561 						 (struct sockaddr *)&ss_mask)) {
562 				/* Temporarily replace netmask on
563 				 * the detected interface - user knows
564 				 * best.... */
565 				struct sockaddr_storage saved_mask =
566 					probed_ifaces[i].netmask;
567 				probed_ifaces[i].netmask = ss_mask;
568 				DEBUG(2,("interpret_interface: "
569 					"using netmask value %s from "
570 					"config file on interface %s\n",
571 					p,
572 					probed_ifaces[i].name));
573 				if (speed_set) {
574 					probed_ifaces[i].linkspeed = speed;
575 				}
576 				if (cap_set) {
577 					probed_ifaces[i].capability = cap;
578 				}
579 				if (if_index_set) {
580 					probed_ifaces[i].if_index = if_index;
581 				}
582 				add_interface(&probed_ifaces[i]);
583 				probed_ifaces[i].netmask = saved_mask;
584 				return;
585 			}
586 		}
587 		DEBUG(2,("interpret_interface: Can't determine ip for "
588 			"broadcast address %s\n",
589 			token));
590 		return;
591 	}
592 
593 	/* Just fake up the interface definition. User knows best. */
594 
595 	DEBUG(2,("interpret_interface: Adding interface %s\n",
596 		token));
597 
598 	ZERO_STRUCT(ifs);
599 	(void)strlcpy(ifs.name, token, sizeof(ifs.name));
600 	ifs.flags = IFF_BROADCAST;
601 	ifs.ip = ss;
602 	ifs.netmask = ss_mask;
603 	ifs.bcast = ss_bcast;
604 	if (if_index_set) {
605 		ifs.if_index = if_index;
606 	}
607 	if (speed_set) {
608 		ifs.linkspeed = speed;
609 	} else {
610 		ifs.linkspeed = 1000 * 1000 * 1000;
611 	}
612 	ifs.capability = cap;
613 	add_interface(&ifs);
614 }
615 
616 /****************************************************************************
617  Load the list of network interfaces.
618 ****************************************************************************/
619 
load_interfaces(void)620 void load_interfaces(void)
621 {
622 	struct iface_struct *ifaces = NULL;
623 	const char **ptr = lp_interfaces();
624 	int i;
625 
626 	gfree_interfaces();
627 
628 	/* Probe the kernel for interfaces */
629 	total_probed = get_interfaces(talloc_tos(), &ifaces);
630 
631 	if (total_probed > 0) {
632 		probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
633 				sizeof(ifaces[0])*total_probed);
634 		if (!probed_ifaces) {
635 			DEBUG(0,("ERROR: smb_memdup failed\n"));
636 			exit(1);
637 		}
638 	}
639 	TALLOC_FREE(ifaces);
640 
641 	/* if we don't have a interfaces line then use all broadcast capable
642 	   interfaces except loopback */
643 	if (!ptr || !*ptr || !**ptr) {
644 		if (total_probed <= 0) {
645 			DEBUG(0,("ERROR: Could not determine network "
646 			"interfaces, you must use a interfaces config line\n"));
647 			exit(1);
648 		}
649 		for (i=0;i<total_probed;i++) {
650 			if (probed_ifaces[i].flags & IFF_BROADCAST) {
651 				add_interface(&probed_ifaces[i]);
652 			}
653 		}
654 		return;
655 	}
656 
657 	if (ptr) {
658 		while (*ptr) {
659 			char *ptr_cpy = SMB_STRDUP(*ptr);
660 			if (ptr_cpy) {
661 				interpret_interface(ptr_cpy);
662 				free(ptr_cpy);
663 			}
664 			ptr++;
665 		}
666 	}
667 
668 	if (!local_interfaces) {
669 		DEBUG(0,("WARNING: no network interfaces found\n"));
670 	}
671 }
672 
673 
gfree_interfaces(void)674 void gfree_interfaces(void)
675 {
676 	while (local_interfaces) {
677 		struct interface *iface = local_interfaces;
678 		DLIST_REMOVE(local_interfaces, local_interfaces);
679 		SAFE_FREE(iface->name);
680 		SAFE_FREE(iface);
681 	}
682 
683 	SAFE_FREE(probed_ifaces);
684 }
685 
686 /****************************************************************************
687  Return True if the list of probed interfaces has changed.
688 ****************************************************************************/
689 
interfaces_changed(void)690 bool interfaces_changed(void)
691 {
692 	bool ret = false;
693 	int n;
694 	struct iface_struct *ifaces = NULL;
695 
696 	n = get_interfaces(talloc_tos(), &ifaces);
697 
698 	if ((n > 0 )&& (n != total_probed ||
699 			memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
700 		ret = true;
701 	}
702 
703 	TALLOC_FREE(ifaces);
704 	return ret;
705 }
706