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