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
*ip
)
35 for (i
=local_interfaces
;i
;i
=i
->next
) {
36 if (sockaddr_equal((struct sockaddr
*)&i
->ip
,ip
)) {
43 bool ismyip_v4(struct in_addr ip
)
45 struct sockaddr_storage ss
;
46 in_addr_to_sockaddr_storage(&ss
, ip
);
47 return ismyaddr((struct sockaddr
*)&ss
);
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
*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
, (struct sockaddr
*)&i
->ip
, (struct sockaddr
*)&i
->netmask
)) {
68 } else if (sockaddr_equal((struct sockaddr
*)&i
->ip
, ip
)) {
76 /****************************************************************************
77 Check if a packet is from a local (known) net.
78 **************************************************************************/
80 bool is_local_net(const struct sockaddr
*from
)
83 for (i
=local_interfaces
;i
;i
=i
->next
) {
84 if (same_net(from
, (struct sockaddr
*)&i
->ip
, (struct sockaddr
*)&i
->netmask
)) {
91 #if defined(HAVE_IPV6)
92 void setup_linklocal_scope_id(struct sockaddr
*pss
)
95 for (i
=local_interfaces
;i
;i
=i
->next
) {
96 if (sockaddr_equal((struct sockaddr
*)&i
->ip
,pss
)) {
97 struct sockaddr_in6
*psa6
=
98 (struct sockaddr_in6
*)pss
;
99 psa6
->sin6_scope_id
= if_nametoindex(i
->name
);
106 /****************************************************************************
107 Check if a packet is from a local (known) net.
108 **************************************************************************/
110 bool is_local_net_v4(struct in_addr from
)
112 struct sockaddr_storage ss
;
114 in_addr_to_sockaddr_storage(&ss
, from
);
115 return is_local_net((struct sockaddr
*)&ss
);
118 /****************************************************************************
119 How many interfaces do we have ?
120 **************************************************************************/
122 int iface_count(void)
127 for (i
=local_interfaces
;i
;i
=i
->next
) {
133 /****************************************************************************
134 How many non-loopback IPv4 interfaces do we have ?
135 **************************************************************************/
137 int iface_count_v4_nl(void)
142 for (i
=local_interfaces
;i
;i
=i
->next
) {
143 if (is_loopback_addr((struct sockaddr
*)&i
->ip
)) {
146 if (i
->ip
.ss_family
== AF_INET
) {
153 /****************************************************************************
154 Return a pointer to the in_addr of the first IPv4 interface that's
156 **************************************************************************/
158 const struct in_addr
*first_ipv4_iface(void)
162 for (i
=local_interfaces
;i
;i
=i
->next
) {
163 if ((i
->ip
.ss_family
== AF_INET
) &&
164 (!is_zero_ip_v4(((struct sockaddr_in
*)&i
->ip
)->sin_addr
)))
173 return &((const struct sockaddr_in
*)&i
->ip
)->sin_addr
;
176 /****************************************************************************
177 Return the Nth interface.
178 **************************************************************************/
180 struct interface
*get_interface(int n
)
184 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
194 /****************************************************************************
195 Return IP sockaddr_storage of the Nth interface.
196 **************************************************************************/
198 const struct sockaddr_storage
*iface_n_sockaddr_storage(int n
)
202 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
212 /****************************************************************************
213 Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
214 **************************************************************************/
216 const struct in_addr
*iface_n_ip_v4(int n
)
220 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
224 if (i
&& i
->ip
.ss_family
== AF_INET
) {
225 return &((const struct sockaddr_in
*)&i
->ip
)->sin_addr
;
230 /****************************************************************************
231 Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
232 **************************************************************************/
234 const struct in_addr
*iface_n_bcast_v4(int n
)
238 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
242 if (i
&& i
->ip
.ss_family
== AF_INET
) {
243 return &((const struct sockaddr_in
*)&i
->bcast
)->sin_addr
;
248 /****************************************************************************
249 Return bcast of the Nth interface.
250 **************************************************************************/
252 const struct sockaddr_storage
*iface_n_bcast(int n
)
256 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
266 /* these 3 functions return the ip/bcast/nmask for the interface
267 most appropriate for the given ip address. If they can't find
268 an appropriate interface they return the requested field of the
269 first known interface. */
271 const struct sockaddr_storage
*iface_ip(const struct sockaddr
*ip
)
273 struct interface
*i
= iface_find(ip
, true);
278 /* Search for the first interface with
279 * matching address family. */
281 for (i
=local_interfaces
;i
;i
=i
->next
) {
282 if (i
->ip
.ss_family
== ip
->sa_family
) {
290 return True if a IP is directly reachable on one of our interfaces
293 bool iface_local(const struct sockaddr
*ip
)
295 return iface_find(ip
, true) ? true : false;
298 /****************************************************************************
299 Add an interface to the linked list of interfaces.
300 ****************************************************************************/
302 static void add_interface(const struct iface_struct
*ifs
)
304 char addr
[INET6_ADDRSTRLEN
];
305 struct interface
*iface
;
307 if (iface_find((struct sockaddr
*)&ifs
->ip
, False
)) {
308 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
309 print_sockaddr(addr
, sizeof(addr
), &ifs
->ip
) ));
313 if (!(ifs
->flags
& (IFF_BROADCAST
|IFF_LOOPBACK
))) {
314 DEBUG(3,("not adding non-broadcast interface %s\n",
319 iface
= SMB_MALLOC_P(struct interface
);
324 ZERO_STRUCTPN(iface
);
326 iface
->name
= SMB_STRDUP(ifs
->name
);
331 iface
->flags
= ifs
->flags
;
333 iface
->netmask
= ifs
->netmask
;
334 iface
->bcast
= ifs
->bcast
;
336 DLIST_ADD(local_interfaces
, iface
);
338 DEBUG(2,("added interface %s ip=%s ",
340 print_sockaddr(addr
, sizeof(addr
), &iface
->ip
) ));
341 DEBUG(2,("bcast=%s ",
342 print_sockaddr(addr
, sizeof(addr
),
344 DEBUG(2,("netmask=%s\n",
345 print_sockaddr(addr
, sizeof(addr
),
349 /****************************************************************************
350 Interpret a single element from a interfaces= config line.
352 This handles the following different forms:
354 1) wildcard interface name
359 ****************************************************************************/
361 static void interpret_interface(char *token
)
363 struct sockaddr_storage ss
;
364 struct sockaddr_storage ss_mask
;
365 struct sockaddr_storage ss_net
;
366 struct sockaddr_storage ss_bcast
;
367 struct iface_struct ifs
;
371 bool goodaddr
= false;
373 /* first check if it is an interface name */
374 for (i
=0;i
<total_probed
;i
++) {
375 if (gen_fnmatch(token
, probed_ifaces
[i
].name
) == 0) {
376 add_interface(&probed_ifaces
[i
]);
384 /* maybe it is a DNS name */
385 p
= strchr_m(token
,'/');
387 if (!interpret_string_addr(&ss
, token
, 0)) {
388 DEBUG(2, ("interpret_interface: Can't find address "
393 for (i
=0;i
<total_probed
;i
++) {
394 if (sockaddr_equal((struct sockaddr
*)&ss
, (struct sockaddr
*)&probed_ifaces
[i
].ip
)) {
395 add_interface(&probed_ifaces
[i
]);
399 DEBUG(2,("interpret_interface: "
400 "can't determine interface for %s\n",
405 /* parse it into an IP address/netmasklength pair */
407 goodaddr
= interpret_string_addr(&ss
, token
, 0);
411 DEBUG(2,("interpret_interface: "
412 "can't determine interface for %s\n",
418 goodaddr
= interpret_string_addr(&ss_mask
, p
, 0);
420 DEBUG(2,("interpret_interface: "
421 "can't determine netmask from %s\n",
427 unsigned long val
= strtoul(p
, &endp
, 0);
428 if (p
== endp
|| (endp
&& *endp
!= '\0')) {
429 DEBUG(2,("interpret_interface: "
430 "can't determine netmask value from %s\n",
434 if (!make_netmask(&ss_mask
, &ss
, val
)) {
435 DEBUG(2,("interpret_interface: "
436 "can't apply netmask value %lu from %s\n",
443 make_bcast(&ss_bcast
, &ss
, &ss_mask
);
444 make_net(&ss_net
, &ss
, &ss_mask
);
446 /* Maybe the first component was a broadcast address. */
447 if (sockaddr_equal((struct sockaddr
*)&ss_bcast
, (struct sockaddr
*)&ss
) ||
448 sockaddr_equal((struct sockaddr
*)&ss_net
, (struct sockaddr
*)&ss
)) {
449 for (i
=0;i
<total_probed
;i
++) {
450 if (same_net((struct sockaddr
*)&ss
,
451 (struct sockaddr
*)&probed_ifaces
[i
].ip
,
452 (struct sockaddr
*)&ss_mask
)) {
453 /* Temporarily replace netmask on
454 * the detected interface - user knows
456 struct sockaddr_storage saved_mask
=
457 probed_ifaces
[i
].netmask
;
458 probed_ifaces
[i
].netmask
= ss_mask
;
459 DEBUG(2,("interpret_interface: "
460 "using netmask value %s from "
461 "config file on interface %s\n",
463 probed_ifaces
[i
].name
));
464 add_interface(&probed_ifaces
[i
]);
465 probed_ifaces
[i
].netmask
= saved_mask
;
469 DEBUG(2,("interpret_interface: Can't determine ip for "
470 "broadcast address %s\n",
475 /* Just fake up the interface definition. User knows best. */
477 DEBUG(2,("interpret_interface: Adding interface %s\n",
481 (void)strlcpy(ifs
.name
, token
, sizeof(ifs
.name
));
482 ifs
.flags
= IFF_BROADCAST
;
484 ifs
.netmask
= ss_mask
;
485 ifs
.bcast
= ss_bcast
;
489 /****************************************************************************
490 Load the list of network interfaces.
491 ****************************************************************************/
493 void load_interfaces(void)
495 struct iface_struct ifaces
[MAX_INTERFACES
];
496 const char **ptr
= lp_interfaces();
499 SAFE_FREE(probed_ifaces
);
501 /* dump the current interfaces if any */
502 while (local_interfaces
) {
503 struct interface
*iface
= local_interfaces
;
504 DLIST_REMOVE(local_interfaces
, local_interfaces
);
505 SAFE_FREE(iface
->name
);
509 /* Probe the kernel for interfaces */
510 total_probed
= get_interfaces(ifaces
, MAX_INTERFACES
);
512 if (total_probed
> 0) {
513 probed_ifaces
= (struct iface_struct
*)memdup(ifaces
,
514 sizeof(ifaces
[0])*total_probed
);
515 if (!probed_ifaces
) {
516 DEBUG(0,("ERROR: memdup failed\n"));
521 /* if we don't have a interfaces line then use all broadcast capable
522 interfaces except loopback */
523 if (!ptr
|| !*ptr
|| !**ptr
) {
524 if (total_probed
<= 0) {
525 DEBUG(0,("ERROR: Could not determine network "
526 "interfaces, you must use a interfaces config line\n"));
529 for (i
=0;i
<total_probed
;i
++) {
530 if (probed_ifaces
[i
].flags
& IFF_BROADCAST
) {
531 add_interface(&probed_ifaces
[i
]);
539 char *ptr_cpy
= SMB_STRDUP(*ptr
);
541 interpret_interface(ptr_cpy
);
548 if (!local_interfaces
) {
549 DEBUG(0,("WARNING: no network interfaces found\n"));
554 void gfree_interfaces(void)
556 while (local_interfaces
) {
557 struct interface
*iface
= local_interfaces
;
558 DLIST_REMOVE(local_interfaces
, local_interfaces
);
559 SAFE_FREE(iface
->name
);
563 SAFE_FREE(probed_ifaces
);
566 /****************************************************************************
567 Return True if the list of probed interfaces has changed.
568 ****************************************************************************/
570 bool interfaces_changed(void)
573 struct iface_struct ifaces
[MAX_INTERFACES
];
575 n
= get_interfaces(ifaces
, MAX_INTERFACES
);
577 if ((n
> 0 )&& (n
!= total_probed
||
578 memcmp(ifaces
, probed_ifaces
, sizeof(ifaces
[0])*n
))) {