1 1.28 msaitoh /* $NetBSD: af_inet.c,v 1.28 2020/05/14 08:34:17 msaitoh Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 1983, 1993 5 1.1 thorpej * The Regents of the University of California. All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * Redistribution and use in source and binary forms, with or without 8 1.1 thorpej * modification, are permitted provided that the following conditions 9 1.1 thorpej * are met: 10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 11 1.1 thorpej * notice, this list of conditions and the following disclaimer. 12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 14 1.1 thorpej * documentation and/or other materials provided with the distribution. 15 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors 16 1.1 thorpej * may be used to endorse or promote products derived from this software 17 1.1 thorpej * without specific prior written permission. 18 1.1 thorpej * 19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 thorpej * SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.1 thorpej #include <sys/cdefs.h> 33 1.1 thorpej #ifndef lint 34 1.28 msaitoh __RCSID("$NetBSD: af_inet.c,v 1.28 2020/05/14 08:34:17 msaitoh Exp $"); 35 1.1 thorpej #endif /* not lint */ 36 1.1 thorpej 37 1.26 msaitoh #include <sys/param.h> 38 1.26 msaitoh #include <sys/ioctl.h> 39 1.1 thorpej #include <sys/socket.h> 40 1.1 thorpej 41 1.26 msaitoh #include <net/if.h> 42 1.1 thorpej #include <netinet/in.h> 43 1.1 thorpej #include <netinet/in_var.h> 44 1.1 thorpej 45 1.1 thorpej #include <arpa/inet.h> 46 1.1 thorpej 47 1.6 dyoung #include <assert.h> 48 1.1 thorpej #include <err.h> 49 1.1 thorpej #include <errno.h> 50 1.1 thorpej #include <ifaddrs.h> 51 1.1 thorpej #include <netdb.h> 52 1.1 thorpej #include <string.h> 53 1.1 thorpej #include <stdlib.h> 54 1.1 thorpej #include <stdio.h> 55 1.4 christos #include <util.h> 56 1.1 thorpej 57 1.6 dyoung #include "env.h" 58 1.1 thorpej #include "extern.h" 59 1.8 dyoung #include "af_inetany.h" 60 1.15 pooka #include "prog_ops.h" 61 1.1 thorpej 62 1.12 dyoung static void in_constructor(void) __attribute__((constructor)); 63 1.12 dyoung static void in_status(prop_dictionary_t, prop_dictionary_t, bool); 64 1.12 dyoung static void in_commit_address(prop_dictionary_t, prop_dictionary_t); 65 1.18 roy static bool in_addr_tentative(struct ifaddrs *); 66 1.18 roy static bool in_addr_tentative_or_detached(struct ifaddrs *); 67 1.28 msaitoh static in_addr_t in_netmask(struct sockaddr *); 68 1.23 roy static int in_prefixlen(struct sockaddr *); 69 1.22 roy static void in_alias(struct ifaddrs *, prop_dictionary_t, prop_dictionary_t); 70 1.5 dyoung 71 1.12 dyoung static struct afswtch af = { 72 1.12 dyoung .af_name = "inet", .af_af = AF_INET, .af_status = in_status, 73 1.16 roy .af_addr_commit = in_commit_address, 74 1.18 roy .af_addr_tentative = in_addr_tentative, 75 1.18 roy .af_addr_tentative_or_detached = in_addr_tentative_or_detached 76 1.12 dyoung }; 77 1.12 dyoung 78 1.24 kre static in_addr_t 79 1.24 kre in_netmask(struct sockaddr *sa) 80 1.24 kre { 81 1.24 kre struct sockaddr_in sin; 82 1.24 kre 83 1.24 kre memset(&sin, 0, sizeof(sin)); 84 1.24 kre memcpy(&sin, sa, sa->sa_len); 85 1.24 kre return ntohl(sin.sin_addr.s_addr); 86 1.24 kre } 87 1.24 kre 88 1.23 roy static int 89 1.23 roy in_prefixlen(struct sockaddr *sa) 90 1.23 roy { 91 1.23 roy in_addr_t mask; 92 1.23 roy int cidr; 93 1.23 roy 94 1.24 kre mask = in_netmask(sa); 95 1.24 kre if (mask == 0) /* mask 0 ==> /0 */ 96 1.24 kre return 0; 97 1.24 kre 98 1.24 kre cidr = 33 - ffs(mask); /* 33 - (1 .. 32) -> 32 .. 1 */ 99 1.24 kre 100 1.24 kre if (cidr < 32) { /* more than 1 bit in mask */ 101 1.24 kre /* check for non-contig netmask */ 102 1.25 kamil if ((mask ^ (((1U << cidr) - 1) << (32 - cidr))) != 0) 103 1.24 kre return -1; /* noncontig, no pfxlen */ 104 1.24 kre } 105 1.24 kre 106 1.23 roy return cidr; 107 1.23 roy } 108 1.23 roy 109 1.11 dyoung static void 110 1.22 roy in_alias(struct ifaddrs *ifa, prop_dictionary_t env, prop_dictionary_t oenv) 111 1.1 thorpej { 112 1.13 dyoung char hbuf[NI_MAXHOST]; 113 1.13 dyoung const int niflag = Nflag ? 0 : NI_NUMERICHOST; 114 1.24 kre int pfxlen; 115 1.21 roy char fbuf[1024]; 116 1.1 thorpej 117 1.1 thorpej if (lflag) 118 1.1 thorpej return; 119 1.1 thorpej 120 1.21 roy if (getnameinfo(ifa->ifa_addr, ifa->ifa_addr->sa_len, 121 1.13 dyoung hbuf, sizeof(hbuf), NULL, 0, niflag)) 122 1.13 dyoung strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 123 1.22 roy printf("\tinet %s", hbuf); 124 1.24 kre pfxlen = in_prefixlen(ifa->ifa_netmask); 125 1.24 kre if (pfxlen >= 0) 126 1.24 kre printf("/%d", pfxlen); 127 1.6 dyoung 128 1.21 roy if (ifa->ifa_flags & IFF_POINTOPOINT) { 129 1.21 roy if (getnameinfo(ifa->ifa_dstaddr, ifa->ifa_dstaddr->sa_len, 130 1.13 dyoung hbuf, sizeof(hbuf), NULL, 0, niflag)) 131 1.13 dyoung strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 132 1.13 dyoung printf(" -> %s", hbuf); 133 1.13 dyoung } 134 1.1 thorpej 135 1.24 kre if (pfxlen < 0) 136 1.24 kre printf(" netmask %#x", in_netmask(ifa->ifa_netmask)); 137 1.24 kre 138 1.21 roy if (ifa->ifa_flags & IFF_BROADCAST) { 139 1.21 roy if (getnameinfo(ifa->ifa_broadaddr, ifa->ifa_broadaddr->sa_len, 140 1.13 dyoung hbuf, sizeof(hbuf), NULL, 0, niflag)) 141 1.13 dyoung strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 142 1.13 dyoung printf(" broadcast %s", hbuf); 143 1.1 thorpej } 144 1.16 roy 145 1.21 roy (void)snprintb(fbuf, sizeof(fbuf), IN_IFFBITS, ifa->ifa_addrflags); 146 1.21 roy printf(" flags %s", fbuf); 147 1.5 dyoung } 148 1.5 dyoung 149 1.12 dyoung static void 150 1.7 dyoung in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force) 151 1.1 thorpej { 152 1.1 thorpej struct ifaddrs *ifap, *ifa; 153 1.14 dyoung bool printprefs = false; 154 1.6 dyoung const char *ifname; 155 1.6 dyoung 156 1.6 dyoung if ((ifname = getifname(env)) == NULL) 157 1.6 dyoung err(EXIT_FAILURE, "%s: getifname", __func__); 158 1.1 thorpej 159 1.1 thorpej if (getifaddrs(&ifap) != 0) 160 1.1 thorpej err(EXIT_FAILURE, "getifaddrs"); 161 1.10 dyoung 162 1.14 dyoung printprefs = ifa_any_preferences(ifname, ifap, AF_INET); 163 1.14 dyoung 164 1.10 dyoung for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 165 1.6 dyoung if (strcmp(ifname, ifa->ifa_name) != 0) 166 1.1 thorpej continue; 167 1.1 thorpej if (ifa->ifa_addr->sa_family != AF_INET) 168 1.1 thorpej continue; 169 1.21 roy /* The first address is not an alias. */ 170 1.22 roy in_alias(ifa, env, oenv); 171 1.5 dyoung if (printprefs) 172 1.14 dyoung ifa_print_preference(ifa->ifa_name, ifa->ifa_addr); 173 1.5 dyoung printf("\n"); 174 1.5 dyoung } 175 1.1 thorpej freeifaddrs(ifap); 176 1.1 thorpej } 177 1.8 dyoung 178 1.12 dyoung static void 179 1.8 dyoung in_commit_address(prop_dictionary_t env, prop_dictionary_t oenv) 180 1.8 dyoung { 181 1.8 dyoung struct ifreq in_ifr; 182 1.8 dyoung struct in_aliasreq in_ifra; 183 1.8 dyoung struct afparam inparam = { 184 1.8 dyoung .req = BUFPARAM(in_ifra) 185 1.8 dyoung , .dgreq = BUFPARAM(in_ifr) 186 1.8 dyoung , .name = { 187 1.8 dyoung {.buf = in_ifr.ifr_name, 188 1.8 dyoung .buflen = sizeof(in_ifr.ifr_name)} 189 1.8 dyoung , {.buf = in_ifra.ifra_name, 190 1.8 dyoung .buflen = sizeof(in_ifra.ifra_name)} 191 1.8 dyoung } 192 1.8 dyoung , .dgaddr = BUFPARAM(in_ifr.ifr_addr) 193 1.8 dyoung , .addr = BUFPARAM(in_ifra.ifra_addr) 194 1.8 dyoung , .dst = BUFPARAM(in_ifra.ifra_dstaddr) 195 1.8 dyoung , .brd = BUFPARAM(in_ifra.ifra_broadaddr) 196 1.8 dyoung , .mask = BUFPARAM(in_ifra.ifra_mask) 197 1.8 dyoung , .aifaddr = IFADDR_PARAM(SIOCAIFADDR) 198 1.8 dyoung , .difaddr = IFADDR_PARAM(SIOCDIFADDR) 199 1.8 dyoung , .gifaddr = IFADDR_PARAM(SIOCGIFADDR) 200 1.8 dyoung , .defmask = {.buf = NULL, .buflen = 0} 201 1.8 dyoung }; 202 1.9 dyoung memset(&in_ifr, 0, sizeof(in_ifr)); 203 1.9 dyoung memset(&in_ifra, 0, sizeof(in_ifra)); 204 1.8 dyoung commit_address(env, oenv, &inparam); 205 1.8 dyoung } 206 1.12 dyoung 207 1.18 roy #ifdef SIOCGIFAFLAG_IN 208 1.16 roy static bool 209 1.18 roy in_addr_flags(struct ifaddrs *ifa, int flags) 210 1.16 roy { 211 1.16 roy int s; 212 1.16 roy struct ifreq ifr; 213 1.16 roy 214 1.16 roy memset(&ifr, 0, sizeof(ifr)); 215 1.19 riastrad estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 216 1.16 roy ifr.ifr_addr = *ifa->ifa_addr; 217 1.16 roy if ((s = getsock(AF_INET)) == -1) 218 1.16 roy err(EXIT_FAILURE, "%s: getsock", __func__); 219 1.17 roy if (prog_ioctl(s, SIOCGIFAFLAG_IN, &ifr) == -1) 220 1.16 roy err(EXIT_FAILURE, "SIOCGIFAFLAG_IN"); 221 1.18 roy return ifr.ifr_addrflags & flags ? true : false; 222 1.18 roy } 223 1.18 roy #endif 224 1.18 roy 225 1.18 roy static bool 226 1.18 roy in_addr_tentative(struct ifaddrs *ifa) 227 1.18 roy { 228 1.18 roy 229 1.21 roy #ifdef SIOCGIFAFLAG_IN 230 1.18 roy return in_addr_flags(ifa, IN_IFF_TENTATIVE); 231 1.18 roy #else 232 1.18 roy return false; 233 1.18 roy #endif 234 1.18 roy } 235 1.18 roy 236 1.18 roy static bool 237 1.18 roy in_addr_tentative_or_detached(struct ifaddrs *ifa) 238 1.18 roy { 239 1.18 roy 240 1.21 roy #ifdef SIOCGIFAFLAG_IN 241 1.18 roy return in_addr_flags(ifa, IN_IFF_TENTATIVE | IN_IFF_DETACHED); 242 1.16 roy #else 243 1.16 roy return false; 244 1.16 roy #endif 245 1.16 roy } 246 1.16 roy 247 1.12 dyoung static void 248 1.12 dyoung in_constructor(void) 249 1.12 dyoung { 250 1.12 dyoung register_family(&af); 251 1.12 dyoung } 252