config.c revision 1.1
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 */ 20void 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