2 * The mrouted program is covered by the license in the accompanying file
3 * named "LICENSE". Use of the mrouted program represents acceptance of
4 * the terms and conditions listed in that file.
6 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
7 * Leland Stanford Junior University.
10 * config.c,v 3.8.4.10 1998/01/06 01:57:41 fenner Exp
12 * $FreeBSD: src/usr.sbin/mrouted/config.c,v 1.14 1999/08/28 01:17:03 peter Exp $
13 * $DragonFly: src/usr.sbin/mrouted/config.c,v 1.3 2004/03/15 18:10:28 dillon Exp $
22 * Query the kernel to find network interfaces that are multicast-capable
23 * and install them in the uvifs array.
26 config_vifs_from_kernel(void)
28 struct ifreq
*ifrp
, *ifend
;
32 u_int32 addr
, mask
, subnet
;
36 ifc
.ifc_len
= num_ifreq
* sizeof(struct ifreq
);
37 ifc
.ifc_buf
= malloc(ifc
.ifc_len
);
39 if (ioctl(udp_socket
, SIOCGIFCONF
, (char *)&ifc
) < 0)
40 log(LOG_ERR
, errno
, "ioctl SIOCGIFCONF");
43 * If the buffer was large enough to hold all the addresses
44 * then break out, otherwise increase the buffer size and
47 * The only way to know that we definitely had enough space
48 * is to know that there was enough space for at least one
49 * more struct ifreq. ???
51 if ((num_ifreq
* sizeof(struct ifreq
)) >=
52 ifc
.ifc_len
+ sizeof(struct ifreq
))
56 ifc
.ifc_len
= num_ifreq
* sizeof(struct ifreq
);
57 ifc
.ifc_buf
= realloc(ifc
.ifc_buf
, ifc
.ifc_len
);
59 if (ifc
.ifc_buf
== NULL
)
60 log(LOG_ERR
, 0, "config_vifs_from_kernel: ran out of memory");
62 ifrp
= (struct ifreq
*)ifc
.ifc_buf
;
63 ifend
= (struct ifreq
*)(ifc
.ifc_buf
+ ifc
.ifc_len
);
65 * Loop through all of the interfaces.
67 for (; ifrp
< ifend
; ifrp
= (struct ifreq
*)((char *)ifrp
+ n
)) {
70 n
= ifrp
->ifr_addr
.sa_len
+ sizeof(ifrp
->ifr_name
);
71 if (n
< sizeof(*ifrp
))
77 * Ignore any interface for an address family other than IP.
79 if (ifrp
->ifr_addr
.sa_family
!= AF_INET
)
82 addr
= ((struct sockaddr_in
*)&ifrp
->ifr_addr
)->sin_addr
.s_addr
;
85 * Need a template to preserve address info that is
86 * used below to locate the next entry. (Otherwise,
87 * SIOCGIFFLAGS stomps over it because the requests
88 * are returned in a union.)
90 bcopy(ifrp
->ifr_name
, ifr
.ifr_name
, sizeof(ifr
.ifr_name
));
93 * Ignore loopback interfaces and interfaces that do not support
96 if (ioctl(udp_socket
, SIOCGIFFLAGS
, (char *)&ifr
) < 0)
97 log(LOG_ERR
, errno
, "ioctl SIOCGIFFLAGS for %s", ifr
.ifr_name
);
98 flags
= ifr
.ifr_flags
;
99 if ((flags
& (IFF_LOOPBACK
|IFF_MULTICAST
)) != IFF_MULTICAST
) continue;
102 * Ignore any interface whose address and mask do not define a
103 * valid subnet number, or whose address is of the form {subnet,0}
106 if (ioctl(udp_socket
, SIOCGIFNETMASK
, (char *)&ifr
) < 0)
107 log(LOG_ERR
, errno
, "ioctl SIOCGIFNETMASK for %s", ifr
.ifr_name
);
108 mask
= ((struct sockaddr_in
*)&ifr
.ifr_addr
)->sin_addr
.s_addr
;
109 subnet
= addr
& mask
;
110 if (!inet_valid_subnet(subnet
, mask
) ||
112 addr
== (subnet
| ~mask
)) {
114 "ignoring %s, has invalid address (%s) and/or mask (%s)",
115 ifr
.ifr_name
, inet_fmt(addr
, s1
), inet_fmt(mask
, s2
));
120 * Ignore any interface that is connected to the same subnet as
121 * one already installed in the uvifs array.
123 for (vifi
= 0, v
= uvifs
; vifi
< numvifs
; ++vifi
, ++v
) {
124 if (strcmp(v
->uv_name
, ifr
.ifr_name
) == 0) {
125 log(LOG_DEBUG
, 0, "skipping %s (%s on subnet %s) (alias for vif#%u?)",
126 v
->uv_name
, inet_fmt(addr
, s1
),
127 inet_fmts(subnet
, mask
, s2
), vifi
);
130 if ((addr
& v
->uv_subnetmask
) == v
->uv_subnet
||
131 (v
->uv_subnet
& mask
) == subnet
) {
132 log(LOG_WARNING
, 0, "ignoring %s, same subnet as %s",
133 ifr
.ifr_name
, v
->uv_name
);
137 if (vifi
!= numvifs
) continue;
140 * If there is room in the uvifs array, install this interface.
142 if (numvifs
== MAXVIFS
) {
143 log(LOG_WARNING
, 0, "too many vifs, ignoring %s", ifr
.ifr_name
);
148 v
->uv_lcl_addr
= addr
;
149 v
->uv_subnet
= subnet
;
150 v
->uv_subnetmask
= mask
;
151 v
->uv_subnetbcast
= subnet
| ~mask
;
152 strncpy(v
->uv_name
, ifr
.ifr_name
, IFNAMSIZ
);
153 v
->uv_name
[IFNAMSIZ
-1] = '\0';
155 if (flags
& IFF_POINTOPOINT
)
156 v
->uv_flags
|= VIFF_REXMIT_PRUNES
;
158 log(LOG_INFO
,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d",
159 v
->uv_name
, inet_fmt(addr
, s1
), inet_fmts(subnet
, mask
, s2
),
160 numvifs
, v
->uv_rate_limit
);
165 * If the interface is not yet up, set the vifs_down flag to
166 * remind us to check again later.
168 if (!(flags
& IFF_UP
)) {
169 v
->uv_flags
|= VIFF_DOWN
;