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