Home | History | Annotate | Line # | Download | only in ifconfig
af_inet.c revision 1.25.2.1
      1  1.25.2.1    martin /*	$NetBSD: af_inet.c,v 1.25.2.1 2020/04/13 08:03:20 martin 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.25.2.1    martin __RCSID("$NetBSD: af_inet.c,v 1.25.2.1 2020/04/13 08:03:20 martin Exp $");
     35       1.1   thorpej #endif /* not lint */
     36       1.1   thorpej 
     37  1.25.2.1    martin #include <sys/param.h>
     38  1.25.2.1    martin #include <sys/ioctl.h>
     39       1.1   thorpej #include <sys/socket.h>
     40       1.1   thorpej 
     41  1.25.2.1    martin #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.24       kre 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