2 Unix SMB/CIFS implementation.
3 multiple interface handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007
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.
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.
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/>.
23 static struct iface_struct *probed_ifaces;
24 static int total_probed;
26 static struct interface *local_interfaces;
28 /****************************************************************************
29 Check if an IP is one of mine.
30 **************************************************************************/
32 bool ismyaddr(const struct sockaddr_storage *ip)
35 for (i=local_interfaces;i;i=i->next) {
36 if (addr_equal(&i->ip,ip)) {
43 bool ismyip_v4(struct in_addr ip)
45 struct sockaddr_storage ss;
46 in_addr_to_sockaddr_storage(&ss, ip);
50 /****************************************************************************
51 Try and find an interface that matches an ip. If we cannot, return NULL.
52 **************************************************************************/
54 static struct interface *iface_find(const struct sockaddr_storage *ip,
59 if (is_address_any(ip)) {
60 return local_interfaces;
63 for (i=local_interfaces;i;i=i->next) {
65 if (same_net(ip, &i->ip, &i->netmask)) {
68 } else if (addr_equal(&i->ip, ip)) {
76 /****************************************************************************
77 Check if a packet is from a local (known) net.
78 **************************************************************************/
80 bool is_local_net(const struct sockaddr_storage *from)
83 for (i=local_interfaces;i;i=i->next) {
84 if (same_net(from, &i->ip, &i->netmask)) {
91 /****************************************************************************
92 Check if a packet is from a local (known) net.
93 **************************************************************************/
95 bool is_local_net_v4(struct in_addr from)
97 struct sockaddr_storage ss;
99 in_addr_to_sockaddr_storage(&ss, from);
100 return is_local_net(&ss);
103 /****************************************************************************
104 How many interfaces do we have ?
105 **************************************************************************/
107 int iface_count(void)
112 for (i=local_interfaces;i;i=i->next) {
118 /****************************************************************************
119 How many interfaces do we have (v4 only) ?
120 **************************************************************************/
122 int iface_count_v4(void)
127 for (i=local_interfaces;i;i=i->next) {
128 if (i->ip.ss_family == AF_INET) {
135 /****************************************************************************
136 Return a pointer to the in_addr of the first IPv4 interface.
137 **************************************************************************/
139 const struct in_addr *first_ipv4_iface(void)
143 for (i=local_interfaces;i ;i=i->next) {
144 if (i->ip.ss_family == AF_INET) {
152 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
155 /****************************************************************************
156 Return the Nth interface.
157 **************************************************************************/
159 struct interface *get_interface(int n)
163 for (i=local_interfaces;i && n;i=i->next) {
173 /****************************************************************************
174 Return IP sockaddr_storage of the Nth interface.
175 **************************************************************************/
177 const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
181 for (i=local_interfaces;i && n;i=i->next) {
191 /****************************************************************************
192 Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
193 **************************************************************************/
195 const struct in_addr *iface_n_ip_v4(int n)
199 for (i=local_interfaces;i && n;i=i->next) {
203 if (i && i->ip.ss_family == AF_INET) {
204 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
209 /****************************************************************************
210 Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
211 **************************************************************************/
213 const struct in_addr *iface_n_bcast_v4(int n)
217 for (i=local_interfaces;i && n;i=i->next) {
221 if (i && i->ip.ss_family == AF_INET) {
222 return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
227 /****************************************************************************
228 Return bcast of the Nth interface.
229 **************************************************************************/
231 const struct sockaddr_storage *iface_n_bcast(int n)
235 for (i=local_interfaces;i && n;i=i->next) {
245 /* these 3 functions return the ip/bcast/nmask for the interface
246 most appropriate for the given ip address. If they can't find
247 an appropriate interface they return the requested field of the
248 first known interface. */
250 const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip)
252 struct interface *i = iface_find(ip, true);
257 /* Search for the first interface with
258 * matching address family. */
260 for (i=local_interfaces;i;i=i->next) {
261 if (i->ip.ss_family == ip->ss_family) {
269 return True if a IP is directly reachable on one of our interfaces
272 bool iface_local(const struct sockaddr_storage *ip)
274 return iface_find(ip, True) ? true : false;
277 /****************************************************************************
278 Add an interface to the linked list of interfaces.
279 ****************************************************************************/
281 static void add_interface(const struct iface_struct *ifs)
283 char addr[INET6_ADDRSTRLEN];
284 struct interface *iface;
286 if (iface_find(&ifs->ip, False)) {
287 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
288 print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
292 if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
293 DEBUG(3,("not adding non-broadcast interface %s\n",
298 iface = SMB_MALLOC_P(struct interface);
303 ZERO_STRUCTPN(iface);
305 iface->name = SMB_STRDUP(ifs->name);
310 iface->flags = ifs->flags;
312 iface->netmask = ifs->netmask;
313 iface->bcast = ifs->bcast;
315 DLIST_ADD(local_interfaces, iface);
317 DEBUG(2,("added interface %s ip=%s ",
319 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
320 DEBUG(2,("bcast=%s ",
321 print_sockaddr(addr, sizeof(addr),
323 DEBUG(2,("netmask=%s\n",
324 print_sockaddr(addr, sizeof(addr),
328 /****************************************************************************
329 Create a struct sockaddr_storage with the netmask bits set to 1.
330 ****************************************************************************/
332 bool make_netmask(struct sockaddr_storage *pss_out,
333 const struct sockaddr_storage *pss_in,
334 unsigned long masklen)
337 /* Now apply masklen bits of mask. */
338 #if defined(HAVE_IPV6)
339 if (pss_in->ss_family == AF_INET6) {
340 char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
346 for (i = 0; masklen >= 8; masklen -= 8, i++) {
349 /* Deal with the partial byte. */
350 *p++ &= (0xff & ~(0xff>>masklen));
352 for (;i < sizeof(struct in6_addr); i++) {
358 if (pss_in->ss_family == AF_INET) {
362 ((struct sockaddr_in *)pss_out)->sin_addr.s_addr =
363 htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL));
369 /****************************************************************************
370 Create a struct sockaddr_storage set to the broadcast or network adress from
371 an incoming sockaddr_storage.
372 ****************************************************************************/
374 static void make_bcast_or_net(struct sockaddr_storage *pss_out,
375 const struct sockaddr_storage *pss_in,
376 const struct sockaddr_storage *nmask,
379 unsigned int i = 0, len = 0;
384 /* Set all zero netmask bits to 1. */
385 #if defined(HAVE_IPV6)
386 if (pss_in->ss_family == AF_INET6) {
387 p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
388 pmask = (char *)&((struct sockaddr_in6 *)nmask)->sin6_addr;
392 if (pss_in->ss_family == AF_INET) {
393 p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr;
394 pmask = (char *)&((struct sockaddr_in *)nmask)->sin_addr;
398 for (i = 0; i < len; i++, p++, pmask++) {
400 *p = (*p & *pmask) | (*pmask ^ 0xff);
408 static void make_bcast(struct sockaddr_storage *pss_out,
409 const struct sockaddr_storage *pss_in,
410 const struct sockaddr_storage *nmask)
412 make_bcast_or_net(pss_out, pss_in, nmask, true);
415 static void make_net(struct sockaddr_storage *pss_out,
416 const struct sockaddr_storage *pss_in,
417 const struct sockaddr_storage *nmask)
419 make_bcast_or_net(pss_out, pss_in, nmask, false);
422 /****************************************************************************
423 Interpret a single element from a interfaces= config line.
425 This handles the following different forms:
427 1) wildcard interface name
432 ****************************************************************************/
434 static void interpret_interface(char *token)
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;
444 bool goodaddr = false;
446 /* first check if it is an interface name */
447 for (i=0;i<total_probed;i++) {
448 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
449 add_interface(&probed_ifaces[i]);
457 /* maybe it is a DNS name */
458 p = strchr_m(token,'/');
460 if (!interpret_string_addr(&ss, token, 0)) {
461 DEBUG(2, ("interpret_interface: Can't find address "
466 for (i=0;i<total_probed;i++) {
467 if (addr_equal(&ss, &probed_ifaces[i].ip)) {
468 add_interface(&probed_ifaces[i]);
472 DEBUG(2,("interpret_interface: "
473 "can't determine interface for %s\n",
478 /* parse it into an IP address/netmasklength pair */
480 goodaddr = interpret_string_addr(&ss, token, 0);
484 DEBUG(2,("interpret_interface: "
485 "can't determine interface for %s\n",
491 goodaddr = interpret_string_addr(&ss_mask, p, 0);
493 DEBUG(2,("interpret_interface: "
494 "can't determine netmask from %s\n",
500 unsigned long val = strtoul(p, &endp, 0);
501 if (p == endp || (endp && *endp != '\0')) {
502 DEBUG(2,("interpret_interface: "
503 "can't determine netmask value from %s\n",
507 if (!make_netmask(&ss_mask, &ss, val)) {
508 DEBUG(2,("interpret_interface: "
509 "can't apply netmask value %lu from %s\n",
516 make_bcast(&ss_bcast, &ss, &ss_mask);
517 make_net(&ss_net, &ss, &ss_mask);
519 /* Maybe the first component was a broadcast address. */
520 if (addr_equal(&ss_bcast, &ss) || addr_equal(&ss_net, &ss)) {
521 for (i=0;i<total_probed;i++) {
522 if (same_net(&ss, &probed_ifaces[i].ip, &ss_mask)) {
523 /* Temporarily replace netmask on
524 * the detected interface - user knows
526 struct sockaddr_storage saved_mask =
527 probed_ifaces[i].netmask;
528 probed_ifaces[i].netmask = ss_mask;
529 DEBUG(2,("interpret_interface: "
530 "using netmask value %s from "
531 "config file on interface %s\n",
533 probed_ifaces[i].name));
534 add_interface(&probed_ifaces[i]);
535 probed_ifaces[i].netmask = saved_mask;
539 DEBUG(2,("interpret_interface: Can't determine ip for "
540 "broadcast address %s\n",
545 /* Just fake up the interface definition. User knows best. */
547 DEBUG(2,("interpret_interface: Adding interface %s\n",
551 safe_strcpy(ifs.name, token, sizeof(ifs.name)-1);
552 ifs.flags = IFF_BROADCAST;
554 ifs.netmask = ss_mask;
555 ifs.bcast = ss_bcast;
559 /****************************************************************************
560 Load the list of network interfaces.
561 ****************************************************************************/
563 void load_interfaces(void)
565 struct iface_struct ifaces[MAX_INTERFACES];
566 const char **ptr = lp_interfaces();
569 SAFE_FREE(probed_ifaces);
571 /* dump the current interfaces if any */
572 while (local_interfaces) {
573 struct interface *iface = local_interfaces;
574 DLIST_REMOVE(local_interfaces, local_interfaces);
575 SAFE_FREE(iface->name);
579 /* Probe the kernel for interfaces */
580 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
582 if (total_probed > 0) {
583 probed_ifaces = (struct iface_struct *)memdup(ifaces,
584 sizeof(ifaces[0])*total_probed);
585 if (!probed_ifaces) {
586 DEBUG(0,("ERROR: memdup failed\n"));
591 /* if we don't have a interfaces line then use all broadcast capable
592 interfaces except loopback */
593 if (!ptr || !*ptr || !**ptr) {
594 if (total_probed <= 0) {
595 DEBUG(0,("ERROR: Could not determine network "
596 "interfaces, you must use a interfaces config line\n"));
599 for (i=0;i<total_probed;i++) {
600 if (probed_ifaces[i].flags & IFF_BROADCAST) {
601 add_interface(&probed_ifaces[i]);
609 char *ptr_cpy = SMB_STRDUP(*ptr);
611 interpret_interface(ptr_cpy);
618 if (!local_interfaces) {
619 DEBUG(0,("WARNING: no network interfaces found\n"));
624 void gfree_interfaces(void)
626 while (local_interfaces) {
627 struct interface *iface = local_interfaces;
628 DLIST_REMOVE(local_interfaces, local_interfaces);
629 SAFE_FREE(iface->name);
633 SAFE_FREE(probed_ifaces);
636 /****************************************************************************
637 Return True if the list of probed interfaces has changed.
638 ****************************************************************************/
640 bool interfaces_changed(void)
643 struct iface_struct ifaces[MAX_INTERFACES];
645 n = get_interfaces(ifaces, MAX_INTERFACES);
647 if ((n > 0 )&& (n != total_probed ||
648 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {