xref: /netbsd/usr.sbin/mrouted/config.c (revision bf9ec67e)
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