config.c revision 1.5 1 /* $NetBSD: config.c,v 1.5 1995/10/09 03:51:37 thorpej 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
13 #include "defs.h"
14
15
16 /*
17 * Query the kernel to find network interfaces that are multicast-capable
18 * and install them in the uvifs array.
19 */
20 void config_vifs_from_kernel()
21 {
22 struct ifreq ifbuf[32];
23 struct ifreq *ifrp, *ifend;
24 struct ifconf ifc;
25 register struct uvif *v;
26 register vifi_t vifi;
27 int n;
28 u_int32_t addr, mask, subnet;
29 short flags;
30
31 ifc.ifc_buf = (char *)ifbuf;
32 ifc.ifc_len = sizeof(ifbuf);
33 if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
34 log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
35
36 ifrp = (struct ifreq *)ifbuf;
37 ifend = (struct ifreq *)((char *)ifbuf + ifc.ifc_len);
38 /*
39 * Loop through all of the interfaces.
40 */
41 for (; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) {
42 struct ifreq ifr;
43 #if BSD >= 199006
44 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
45 if (n < sizeof(*ifrp))
46 n = sizeof(*ifrp);
47 #else
48 n = sizeof(*ifrp);
49 #endif
50 /*
51 * Ignore any interface for an address family other than IP.
52 */
53 if (ifrp->ifr_addr.sa_family != AF_INET)
54 continue;
55
56 addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr;
57
58 /*
59 * Need a template to preserve address info that is
60 * used below to locate the next entry. (Otherwise,
61 * SIOCGIFFLAGS stomps over it because the requests
62 * are returned in a union.)
63 */
64 bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
65
66 /*
67 * Ignore loopback interfaces and interfaces that do not support
68 * multicast.
69 */
70 if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0)
71 log(LOG_ERR, errno, "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name);
72 flags = ifr.ifr_flags;
73 if ((flags & (IFF_LOOPBACK|IFF_MULTICAST)) != IFF_MULTICAST) continue;
74
75 /*
76 * Ignore any interface whose address and mask do not define a
77 * valid subnet number, or whose address is of the form {subnet,0}
78 * or {subnet,-1}.
79 */
80 if (ioctl(udp_socket, SIOCGIFNETMASK, (char *)&ifr) < 0)
81 log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", ifr.ifr_name);
82 mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
83 subnet = addr & mask;
84 if (!inet_valid_subnet(subnet, mask) ||
85 addr == subnet ||
86 addr == (subnet | ~mask)) {
87 log(LOG_WARNING, 0,
88 "ignoring %s, has invalid address (%s) and/or mask (%s)",
89 ifr.ifr_name, inet_fmt(addr, s1), inet_fmt(mask, s2));
90 continue;
91 }
92
93 /*
94 * Ignore any interface that is connected to the same subnet as
95 * one already installed in the uvifs array.
96 */
97 for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
98 if ((addr & v->uv_subnetmask) == v->uv_subnet ||
99 (v->uv_subnet & mask) == subnet) {
100 log(LOG_WARNING, 0, "ignoring %s, same subnet as %s",
101 ifr.ifr_name, v->uv_name);
102 break;
103 }
104 }
105 if (vifi != numvifs) continue;
106
107 /*
108 * If there is room in the uvifs array, install this interface.
109 */
110 if (numvifs == MAXVIFS) {
111 log(LOG_WARNING, 0, "too many vifs, ignoring %s", ifr.ifr_name);
112 continue;
113 }
114 v = &uvifs[numvifs];
115 v->uv_flags = 0;
116 v->uv_metric = DEFAULT_METRIC;
117 v->uv_rate_limit = DEFAULT_PHY_RATE_LIMIT;
118 v->uv_threshold = DEFAULT_THRESHOLD;
119 v->uv_lcl_addr = addr;
120 v->uv_rmt_addr = 0;
121 v->uv_subnet = subnet;
122 v->uv_subnetmask = mask;
123 v->uv_subnetbcast = subnet | ~mask;
124 strncpy(v->uv_name, ifr.ifr_name, IFNAMSIZ);
125 v->uv_groups = NULL;
126 v->uv_neighbors = NULL;
127 v->uv_acl = NULL;
128 v->uv_addrs = NULL;
129
130 log(LOG_INFO,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d",
131 v->uv_name, inet_fmt(addr, s1), inet_fmts(subnet, mask, s2),
132 numvifs, v->uv_rate_limit);
133
134 ++numvifs;
135
136 /*
137 * If the interface is not yet up, set the vifs_down flag to
138 * remind us to check again later.
139 */
140 if (!(flags & IFF_UP)) {
141 v->uv_flags |= VIFF_DOWN;
142 vifs_down = TRUE;
143 }
144 }
145 }
146