1 /*        $NetBSD: config.c,v 1.13 2003/05/16 22:59:50 dsl Exp $      */
2 
3 /*
4  * The mrouted program is covered by the license in the accompanying file
5  * named "LICENSE".  Use of the mrouted program represents acceptance of
6  * the terms and conditions listed in that file.
7  *
8  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
9  * Leland Stanford Junior University.
10  */
11 
12 #include "defs.h"
13 #include <net/if.h>
14 #include <ifaddrs.h>
15 
16 
17 /*
18  * Query the kernel to find network interfaces that are multicast-capable
19  * and install them in the uvifs array.
20  */
21 void
config_vifs_from_kernel(void)22 config_vifs_from_kernel(void)
23 {
24     struct ifaddrs *ifa, *ifap;
25     struct uvif *v;
26     vifi_t vifi;
27     u_int32_t addr, mask, subnet;
28     short flags;
29 
30     if (getifaddrs(&ifap) < 0)
31           logit(LOG_ERR, errno, "getifaddrs");
32 
33     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
34           /*
35            * Ignore any interface for an address family other than IP.
36            */
37           if (ifa->ifa_addr->sa_family != AF_INET)
38               continue;
39 
40           addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
41 
42           /*
43            * Ignore loopback interfaces and interfaces that do not support
44            * multicast.
45            */
46           flags = ifa->ifa_flags;
47           if ((flags & (IFF_LOOPBACK|IFF_MULTICAST)) != IFF_MULTICAST)
48               continue;
49 
50           /*
51            * Ignore any interface whose address and mask do not define a
52            * valid subnet number, or whose address is of the form {subnet,0}
53            * or {subnet,-1}.
54            */
55           mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
56           subnet = addr & mask;
57           if (!inet_valid_subnet(subnet, mask) ||
58               addr == subnet ||
59               addr == (subnet | ~mask)) {
60               logit(LOG_WARNING, 0,
61                     "ignoring %s, has invalid address (%s) and/or mask (%s)",
62                     ifa->ifa_name, inet_fmt(addr),
63                     inet_fmt(mask));
64               continue;
65           }
66 
67           /*
68            * Ignore any interface that is connected to the same subnet as
69            * one already installed in the uvifs array.
70            */
71           for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
72               if ((addr & v->uv_subnetmask) == v->uv_subnet ||
73                     (v->uv_subnet & mask) == subnet) {
74                     logit(LOG_WARNING, 0, "ignoring %s, same subnet as %s",
75                         ifa->ifa_name, v->uv_name);
76                     break;
77               }
78           }
79           if (vifi != numvifs)
80               continue;
81 
82           /*
83            * If there is room in the uvifs array, install this interface.
84            */
85           if (numvifs == MAXVIFS) {
86               logit(LOG_WARNING, 0, "too many vifs, ignoring %s", ifa->ifa_name);
87               continue;
88           }
89           v  = &uvifs[numvifs];
90           v->uv_flags       = 0;
91           v->uv_metric      = DEFAULT_METRIC;
92           v->uv_rate_limit  = DEFAULT_PHY_RATE_LIMIT;
93           v->uv_threshold   = DEFAULT_THRESHOLD;
94           v->uv_lcl_addr    = addr;
95           v->uv_rmt_addr    = 0;
96           v->uv_subnet      = subnet;
97           v->uv_subnetmask  = mask;
98           v->uv_subnetbcast = subnet | ~mask;
99           strlcpy(v->uv_name, ifa->ifa_name, sizeof(v->uv_name));
100           v->uv_groups      = NULL;
101           v->uv_neighbors   = NULL;
102           v->uv_acl         = NULL;
103           v->uv_addrs           = NULL;
104 
105           logit(LOG_INFO,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d",
106               v->uv_name, inet_fmt(addr),
107               inet_fmts(subnet, mask),
108               numvifs, v->uv_rate_limit);
109 
110           ++numvifs;
111 
112           /*
113            * If the interface is not yet up, set the vifs_down flag to
114            * remind us to check again later.
115            */
116           if (!(flags & IFF_UP)) {
117               v->uv_flags |= VIFF_DOWN;
118               vifs_down = TRUE;
119           }
120     }
121 
122     freeifaddrs(ifap);
123 }
124