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