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