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 #if defined(HAVE_IPV6)
92 void setup_linklocal_scope_id(struct sockaddr_storage
*pss
)
95 for (i
=local_interfaces
;i
;i
=i
->next
) {
96 if (addr_equal(&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(&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 interfaces do we have (v4 only) ?
135 **************************************************************************/
137 int iface_count_v4(void)
142 for (i
=local_interfaces
;i
;i
=i
->next
) {
143 if (i
->ip
.ss_family
== AF_INET
) {
150 /****************************************************************************
151 Return a pointer to the in_addr of the first IPv4 interface.
152 **************************************************************************/
154 const struct in_addr
*first_ipv4_iface(void)
158 for (i
=local_interfaces
;i
;i
=i
->next
) {
159 if (i
->ip
.ss_family
== AF_INET
) {
167 return &((const struct sockaddr_in
*)&i
->ip
)->sin_addr
;
170 /****************************************************************************
171 Return the Nth interface.
172 **************************************************************************/
174 struct interface
*get_interface(int n
)
178 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
188 /****************************************************************************
189 Return IP sockaddr_storage of the Nth interface.
190 **************************************************************************/
192 const struct sockaddr_storage
*iface_n_sockaddr_storage(int n
)
196 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
206 /****************************************************************************
207 Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
208 **************************************************************************/
210 const struct in_addr
*iface_n_ip_v4(int n
)
214 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
218 if (i
&& i
->ip
.ss_family
== AF_INET
) {
219 return &((const struct sockaddr_in
*)&i
->ip
)->sin_addr
;
224 /****************************************************************************
225 Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
226 **************************************************************************/
228 const struct in_addr
*iface_n_bcast_v4(int n
)
232 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
236 if (i
&& i
->ip
.ss_family
== AF_INET
) {
237 return &((const struct sockaddr_in
*)&i
->bcast
)->sin_addr
;
242 /****************************************************************************
243 Return bcast of the Nth interface.
244 **************************************************************************/
246 const struct sockaddr_storage
*iface_n_bcast(int n
)
250 for (i
=local_interfaces
;i
&& n
;i
=i
->next
) {
260 /* these 3 functions return the ip/bcast/nmask for the interface
261 most appropriate for the given ip address. If they can't find
262 an appropriate interface they return the requested field of the
263 first known interface. */
265 const struct sockaddr_storage
*iface_ip(const struct sockaddr_storage
*ip
)
267 struct interface
*i
= iface_find(ip
, true);
272 /* Search for the first interface with
273 * matching address family. */
275 for (i
=local_interfaces
;i
;i
=i
->next
) {
276 if (i
->ip
.ss_family
== ip
->ss_family
) {
284 return True if a IP is directly reachable on one of our interfaces
287 bool iface_local(const struct sockaddr_storage
*ip
)
289 return iface_find(ip
, True
) ? true : false;
292 /****************************************************************************
293 Add an interface to the linked list of interfaces.
294 ****************************************************************************/
296 static void add_interface(const struct iface_struct
*ifs
)
298 char addr
[INET6_ADDRSTRLEN
];
299 struct interface
*iface
;
301 if (iface_find(&ifs
->ip
, False
)) {
302 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
303 print_sockaddr(addr
, sizeof(addr
), &ifs
->ip
) ));
307 if (!(ifs
->flags
& (IFF_BROADCAST
|IFF_LOOPBACK
))) {
308 DEBUG(3,("not adding non-broadcast interface %s\n",
313 iface
= SMB_MALLOC_P(struct interface
);
318 ZERO_STRUCTPN(iface
);
320 iface
->name
= SMB_STRDUP(ifs
->name
);
325 iface
->flags
= ifs
->flags
;
327 iface
->netmask
= ifs
->netmask
;
328 iface
->bcast
= ifs
->bcast
;
330 DLIST_ADD(local_interfaces
, iface
);
332 DEBUG(2,("added interface %s ip=%s ",
334 print_sockaddr(addr
, sizeof(addr
), &iface
->ip
) ));
335 DEBUG(2,("bcast=%s ",
336 print_sockaddr(addr
, sizeof(addr
),
338 DEBUG(2,("netmask=%s\n",
339 print_sockaddr(addr
, sizeof(addr
),
343 /****************************************************************************
344 Interpret a single element from a interfaces= config line.
346 This handles the following different forms:
348 1) wildcard interface name
353 ****************************************************************************/
355 static void interpret_interface(char *token
)
357 struct sockaddr_storage ss
;
358 struct sockaddr_storage ss_mask
;
359 struct sockaddr_storage ss_net
;
360 struct sockaddr_storage ss_bcast
;
361 struct iface_struct ifs
;
365 bool goodaddr
= false;
367 /* first check if it is an interface name */
368 for (i
=0;i
<total_probed
;i
++) {
369 if (gen_fnmatch(token
, probed_ifaces
[i
].name
) == 0) {
370 add_interface(&probed_ifaces
[i
]);
378 /* maybe it is a DNS name */
379 p
= strchr_m(token
,'/');
381 if (!interpret_string_addr(&ss
, token
, 0)) {
382 DEBUG(2, ("interpret_interface: Can't find address "
387 for (i
=0;i
<total_probed
;i
++) {
388 if (addr_equal(&ss
, &probed_ifaces
[i
].ip
)) {
389 add_interface(&probed_ifaces
[i
]);
393 DEBUG(2,("interpret_interface: "
394 "can't determine interface for %s\n",
399 /* parse it into an IP address/netmasklength pair */
401 goodaddr
= interpret_string_addr(&ss
, token
, 0);
405 DEBUG(2,("interpret_interface: "
406 "can't determine interface for %s\n",
412 goodaddr
= interpret_string_addr(&ss_mask
, p
, 0);
414 DEBUG(2,("interpret_interface: "
415 "can't determine netmask from %s\n",
421 unsigned long val
= strtoul(p
, &endp
, 0);
422 if (p
== endp
|| (endp
&& *endp
!= '\0')) {
423 DEBUG(2,("interpret_interface: "
424 "can't determine netmask value from %s\n",
428 if (!make_netmask(&ss_mask
, &ss
, val
)) {
429 DEBUG(2,("interpret_interface: "
430 "can't apply netmask value %lu from %s\n",
437 make_bcast(&ss_bcast
, &ss
, &ss_mask
);
438 make_net(&ss_net
, &ss
, &ss_mask
);
440 /* Maybe the first component was a broadcast address. */
441 if (addr_equal(&ss_bcast
, &ss
) || addr_equal(&ss_net
, &ss
)) {
442 for (i
=0;i
<total_probed
;i
++) {
443 if (same_net(&ss
, &probed_ifaces
[i
].ip
, &ss_mask
)) {
444 /* Temporarily replace netmask on
445 * the detected interface - user knows
447 struct sockaddr_storage saved_mask
=
448 probed_ifaces
[i
].netmask
;
449 probed_ifaces
[i
].netmask
= ss_mask
;
450 DEBUG(2,("interpret_interface: "
451 "using netmask value %s from "
452 "config file on interface %s\n",
454 probed_ifaces
[i
].name
));
455 add_interface(&probed_ifaces
[i
]);
456 probed_ifaces
[i
].netmask
= saved_mask
;
460 DEBUG(2,("interpret_interface: Can't determine ip for "
461 "broadcast address %s\n",
466 /* Just fake up the interface definition. User knows best. */
468 DEBUG(2,("interpret_interface: Adding interface %s\n",
472 safe_strcpy(ifs
.name
, token
, sizeof(ifs
.name
)-1);
473 ifs
.flags
= IFF_BROADCAST
;
475 ifs
.netmask
= ss_mask
;
476 ifs
.bcast
= ss_bcast
;
480 /****************************************************************************
481 Load the list of network interfaces.
482 ****************************************************************************/
484 void load_interfaces(void)
486 struct iface_struct ifaces
[MAX_INTERFACES
];
487 const char **ptr
= lp_interfaces();
490 SAFE_FREE(probed_ifaces
);
492 /* dump the current interfaces if any */
493 while (local_interfaces
) {
494 struct interface
*iface
= local_interfaces
;
495 DLIST_REMOVE(local_interfaces
, local_interfaces
);
496 SAFE_FREE(iface
->name
);
500 /* Probe the kernel for interfaces */
501 total_probed
= get_interfaces(ifaces
, MAX_INTERFACES
);
503 if (total_probed
> 0) {
504 probed_ifaces
= (struct iface_struct
*)memdup(ifaces
,
505 sizeof(ifaces
[0])*total_probed
);
506 if (!probed_ifaces
) {
507 DEBUG(0,("ERROR: memdup failed\n"));
512 /* if we don't have a interfaces line then use all broadcast capable
513 interfaces except loopback */
514 if (!ptr
|| !*ptr
|| !**ptr
) {
515 if (total_probed
<= 0) {
516 DEBUG(0,("ERROR: Could not determine network "
517 "interfaces, you must use a interfaces config line\n"));
520 for (i
=0;i
<total_probed
;i
++) {
521 if (probed_ifaces
[i
].flags
& IFF_BROADCAST
) {
522 add_interface(&probed_ifaces
[i
]);
530 char *ptr_cpy
= SMB_STRDUP(*ptr
);
532 interpret_interface(ptr_cpy
);
539 if (!local_interfaces
) {
540 DEBUG(0,("WARNING: no network interfaces found\n"));
545 void gfree_interfaces(void)
547 while (local_interfaces
) {
548 struct interface
*iface
= local_interfaces
;
549 DLIST_REMOVE(local_interfaces
, local_interfaces
);
550 SAFE_FREE(iface
->name
);
554 SAFE_FREE(probed_ifaces
);
557 /****************************************************************************
558 Return True if the list of probed interfaces has changed.
559 ****************************************************************************/
561 bool interfaces_changed(void)
564 struct iface_struct ifaces
[MAX_INTERFACES
];
566 n
= get_interfaces(ifaces
, MAX_INTERFACES
);
568 if ((n
> 0 )&& (n
!= total_probed
||
569 memcmp(ifaces
, probed_ifaces
, sizeof(ifaces
[0])*n
))) {