xref: /freebsd/sbin/ifconfig/ifconfig.c (revision 7029da5c36f2d3cf6bb6c81bf551229f416399e8)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifndef lint
33 static const char copyright[] =
34 "@(#) Copyright (c) 1983, 1993\n\
35 	The Regents of the University of California.  All rights reserved.\n";
36 #endif /* not lint */
37 
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
41 #endif
42 static const char rcsid[] =
43   "$FreeBSD$";
44 #endif /* not lint */
45 
46 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/module.h>
49 #include <sys/linker.h>
50 #include <sys/queue.h>
51 #include <sys/socket.h>
52 #include <sys/time.h>
53 
54 #include <net/ethernet.h>
55 #include <net/if.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 #include <net/route.h>
59 
60 /* IP */
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <arpa/inet.h>
64 #include <netdb.h>
65 
66 #include <ifaddrs.h>
67 #include <ctype.h>
68 #include <err.h>
69 #include <errno.h>
70 #include <fcntl.h>
71 #ifdef JAIL
72 #include <jail.h>
73 #endif
74 #include <stdbool.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <unistd.h>
79 
80 #include "ifconfig.h"
81 
82 /*
83  * Since "struct ifreq" is composed of various union members, callers
84  * should pay special attention to interpret the value.
85  * (.e.g. little/big endian difference in the structure.)
86  */
87 struct	ifreq ifr;
88 
89 char	name[IFNAMSIZ];
90 char	*descr = NULL;
91 size_t	descrlen = 64;
92 int	setaddr;
93 int	setmask;
94 int	doalias;
95 int	clearaddr;
96 int	newaddr = 1;
97 int	verbose;
98 int	noload;
99 int	printifname = 0;
100 
101 int	supmedia = 0;
102 int	printkeys = 0;		/* Print keying material for interfaces. */
103 int	exit_code = 0;
104 
105 /* Formatter Strings */
106 char	*f_inet, *f_inet6, *f_ether, *f_addr;
107 
108 static	int ifconfig(int argc, char *const *argv, int iscreate,
109 		const struct afswtch *afp);
110 static	void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
111 		struct ifaddrs *ifa);
112 static	void tunnel_status(int s);
113 static _Noreturn void usage(void);
114 
115 static int getifflags(const char *ifname, int us);
116 
117 static struct afswtch *af_getbyname(const char *name);
118 static struct afswtch *af_getbyfamily(int af);
119 static void af_other_status(int);
120 
121 void printifnamemaybe(void);
122 
123 static struct option *opts = NULL;
124 
125 struct ifa_order_elt {
126 	int if_order;
127 	int af_orders[255];
128 	struct ifaddrs *ifa;
129 	TAILQ_ENTRY(ifa_order_elt) link;
130 };
131 
132 TAILQ_HEAD(ifa_queue, ifa_order_elt);
133 
134 static struct module_map_entry {
135 	const char *ifname;
136 	const char *kldname;
137 } module_map[] = {
138 	{
139 		.ifname = "tun",
140 		.kldname = "if_tuntap",
141 	},
142 	{
143 		.ifname = "tap",
144 		.kldname = "if_tuntap",
145 	},
146 	{
147 		.ifname = "vmnet",
148 		.kldname = "if_tuntap",
149 	},
150 	{
151 		.ifname = "ipsec",
152 		.kldname = "ipsec",
153 	},
154 	{
155 		/*
156 		 * This mapping exists because there is a conflicting enc module
157 		 * in CAM.  ifconfig's guessing behavior will attempt to match
158 		 * the ifname to a module as well as if_${ifname} and clash with
159 		 * CAM enc.  This is an assertion of the correct module to load.
160 		 */
161 		.ifname = "enc",
162 		.kldname = "if_enc",
163 	},
164 };
165 
166 
167 void
168 opt_register(struct option *p)
169 {
170 	p->next = opts;
171 	opts = p;
172 }
173 
174 static void
175 usage(void)
176 {
177 	char options[1024];
178 	struct option *p;
179 
180 	/* XXX not right but close enough for now */
181 	options[0] = '\0';
182 	for (p = opts; p != NULL; p = p->next) {
183 		strlcat(options, p->opt_usage, sizeof(options));
184 		strlcat(options, " ", sizeof(options));
185 	}
186 
187 	fprintf(stderr,
188 	"usage: ifconfig [-f type:format] %sinterface address_family\n"
189 	"                [address [dest_address]] [parameters]\n"
190 	"       ifconfig interface create\n"
191 	"       ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
192 	"       ifconfig -l [-d] [-u] [address_family]\n"
193 	"       ifconfig %s[-d] [-m] [-u] [-v]\n",
194 		options, options, options);
195 	exit(1);
196 }
197 
198 #define ORDERS_SIZE(x) sizeof(x) / sizeof(x[0])
199 
200 static int
201 calcorders(struct ifaddrs *ifa, struct ifa_queue *q)
202 {
203 	struct ifaddrs *prev;
204 	struct ifa_order_elt *cur;
205 	unsigned int ord, af, ifa_ord;
206 
207 	prev = NULL;
208 	cur = NULL;
209 	ord = 0;
210 	ifa_ord = 0;
211 
212 	while (ifa != NULL) {
213 		if (prev == NULL ||
214 		    strcmp(ifa->ifa_name, prev->ifa_name) != 0) {
215 			cur = calloc(1, sizeof(*cur));
216 
217 			if (cur == NULL)
218 				return (-1);
219 
220 			TAILQ_INSERT_TAIL(q, cur, link);
221 			cur->if_order = ifa_ord ++;
222 			cur->ifa = ifa;
223 			ord = 0;
224 		}
225 
226 		if (ifa->ifa_addr) {
227 			af = ifa->ifa_addr->sa_family;
228 
229 			if (af < ORDERS_SIZE(cur->af_orders) &&
230 			    cur->af_orders[af] == 0)
231 				cur->af_orders[af] = ++ord;
232 		}
233 		prev = ifa;
234 		ifa = ifa->ifa_next;
235 	}
236 
237 	return (0);
238 }
239 
240 static int
241 cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q)
242 {
243 	struct ifa_order_elt *cur, *e1, *e2;
244 	unsigned int af1, af2;
245 	int ret;
246 
247 	e1 = e2 = NULL;
248 
249 	ret = strcmp(a->ifa_name, b->ifa_name);
250 	if (ret != 0) {
251 		TAILQ_FOREACH(cur, q, link) {
252 			if (e1 && e2)
253 				break;
254 
255 			if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0)
256 				e1 = cur;
257 			else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0)
258 				e2 = cur;
259 		}
260 
261 		if (!e1 || !e2)
262 			return (0);
263 		else
264 			return (e1->if_order - e2->if_order);
265 
266 	} else if (a->ifa_addr != NULL && b->ifa_addr != NULL) {
267 		TAILQ_FOREACH(cur, q, link) {
268 			if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) {
269 				e1 = cur;
270 				break;
271 			}
272 		}
273 
274 		if (!e1)
275 			return (0);
276 
277 		af1 = a->ifa_addr->sa_family;
278 		af2 = b->ifa_addr->sa_family;
279 
280 		if (af1 < ORDERS_SIZE(e1->af_orders) &&
281 		    af2 < ORDERS_SIZE(e1->af_orders))
282 			return (e1->af_orders[af1] - e1->af_orders[af2]);
283 	}
284 
285 	return (0);
286 }
287 
288 static void freeformat(void)
289 {
290 
291 	if (f_inet != NULL)
292 		free(f_inet);
293 	if (f_inet6 != NULL)
294 		free(f_inet6);
295 	if (f_ether != NULL)
296 		free(f_ether);
297 	if (f_addr != NULL)
298 		free(f_addr);
299 }
300 
301 static void setformat(char *input)
302 {
303 	char	*formatstr, *category, *modifier;
304 
305 	formatstr = strdup(input);
306 	while ((category = strsep(&formatstr, ",")) != NULL) {
307 		modifier = strchr(category, ':');
308 		if (modifier == NULL || modifier[1] == '\0') {
309 			warnx("Skipping invalid format specification: %s\n",
310 			    category);
311 			continue;
312 		}
313 
314 		/* Split the string on the separator, then seek past it */
315 		modifier[0] = '\0';
316 		modifier++;
317 
318 		if (strcmp(category, "addr") == 0)
319 			f_addr = strdup(modifier);
320 		else if (strcmp(category, "ether") == 0)
321 			f_ether = strdup(modifier);
322 		else if (strcmp(category, "inet") == 0)
323 			f_inet = strdup(modifier);
324 		else if (strcmp(category, "inet6") == 0)
325 			f_inet6 = strdup(modifier);
326 	}
327 	free(formatstr);
328 }
329 
330 #undef ORDERS_SIZE
331 
332 static struct ifaddrs *
333 sortifaddrs(struct ifaddrs *list,
334     int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *),
335     struct ifa_queue *q)
336 {
337 	struct ifaddrs *right, *temp, *last, *result, *next, *tail;
338 
339 	right = list;
340 	temp = list;
341 	last = list;
342 	result = NULL;
343 	next = NULL;
344 	tail = NULL;
345 
346 	if (!list || !list->ifa_next)
347 		return (list);
348 
349 	while (temp && temp->ifa_next) {
350 		last = right;
351 		right = right->ifa_next;
352 		temp = temp->ifa_next->ifa_next;
353 	}
354 
355 	last->ifa_next = NULL;
356 
357 	list = sortifaddrs(list, compare, q);
358 	right = sortifaddrs(right, compare, q);
359 
360 	while (list || right) {
361 
362 		if (!right) {
363 			next = list;
364 			list = list->ifa_next;
365 		} else if (!list) {
366 			next = right;
367 			right = right->ifa_next;
368 		} else if (compare(list, right, q) <= 0) {
369 			next = list;
370 			list = list->ifa_next;
371 		} else {
372 			next = right;
373 			right = right->ifa_next;
374 		}
375 
376 		if (!result)
377 			result = next;
378 		else
379 			tail->ifa_next = next;
380 
381 		tail = next;
382 	}
383 
384 	return (result);
385 }
386 
387 void printifnamemaybe()
388 {
389 	if (printifname)
390 		printf("%s\n", name);
391 }
392 
393 int
394 main(int argc, char *argv[])
395 {
396 	int c, all, namesonly, downonly, uponly;
397 	const struct afswtch *afp = NULL;
398 	int ifindex;
399 	struct ifaddrs *ifap, *sifap, *ifa;
400 	struct ifreq paifr;
401 	const struct sockaddr_dl *sdl;
402 	char options[1024], *cp, *envformat, *namecp = NULL;
403 	struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
404 	struct ifa_order_elt *cur, *tmp;
405 	const char *ifname;
406 	struct option *p;
407 	size_t iflen;
408 	int flags;
409 
410 	all = downonly = uponly = namesonly = noload = verbose = 0;
411 	f_inet = f_inet6 = f_ether = f_addr = NULL;
412 
413 	envformat = getenv("IFCONFIG_FORMAT");
414 	if (envformat != NULL)
415 		setformat(envformat);
416 
417 	/*
418 	 * Ensure we print interface name when expected to,
419 	 * even if we terminate early due to error.
420 	 */
421 	atexit(printifnamemaybe);
422 
423 	/* Parse leading line options */
424 	strlcpy(options, "f:adklmnuv", sizeof(options));
425 	for (p = opts; p != NULL; p = p->next)
426 		strlcat(options, p->opt, sizeof(options));
427 	while ((c = getopt(argc, argv, options)) != -1) {
428 		switch (c) {
429 		case 'a':	/* scan all interfaces */
430 			all++;
431 			break;
432 		case 'd':	/* restrict scan to "down" interfaces */
433 			downonly++;
434 			break;
435 		case 'f':
436 			if (optarg == NULL)
437 				usage();
438 			setformat(optarg);
439 			break;
440 		case 'k':
441 			printkeys++;
442 			break;
443 		case 'l':	/* scan interface names only */
444 			namesonly++;
445 			break;
446 		case 'm':	/* show media choices in status */
447 			supmedia = 1;
448 			break;
449 		case 'n':	/* suppress module loading */
450 			noload++;
451 			break;
452 		case 'u':	/* restrict scan to "up" interfaces */
453 			uponly++;
454 			break;
455 		case 'v':
456 			verbose++;
457 			break;
458 		default:
459 			for (p = opts; p != NULL; p = p->next)
460 				if (p->opt[0] == c) {
461 					p->cb(optarg);
462 					break;
463 				}
464 			if (p == NULL)
465 				usage();
466 			break;
467 		}
468 	}
469 	argc -= optind;
470 	argv += optind;
471 
472 	/* -l cannot be used with -a or -m */
473 	if (namesonly && (all || supmedia))
474 		usage();
475 
476 	/* nonsense.. */
477 	if (uponly && downonly)
478 		usage();
479 
480 	/* no arguments is equivalent to '-a' */
481 	if (!namesonly && argc < 1)
482 		all = 1;
483 
484 	/* -a and -l allow an address family arg to limit the output */
485 	if (all || namesonly) {
486 		if (argc > 1)
487 			usage();
488 
489 		ifname = NULL;
490 		ifindex = 0;
491 		if (argc == 1) {
492 			afp = af_getbyname(*argv);
493 			if (afp == NULL) {
494 				warnx("Address family '%s' unknown.", *argv);
495 				usage();
496 			}
497 			if (afp->af_name != NULL)
498 				argc--, argv++;
499 			/* leave with afp non-zero */
500 		}
501 	} else {
502 		/* not listing, need an argument */
503 		if (argc < 1)
504 			usage();
505 
506 		ifname = *argv;
507 		argc--, argv++;
508 
509 		/* check and maybe load support for this interface */
510 		ifmaybeload(ifname);
511 
512 		ifindex = if_nametoindex(ifname);
513 		if (ifindex == 0) {
514 			/*
515 			 * NOTE:  We must special-case the `create' command
516 			 * right here as we would otherwise fail when trying
517 			 * to find the interface.
518 			 */
519 			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
520 			    strcmp(argv[0], "plumb") == 0)) {
521 				iflen = strlcpy(name, ifname, sizeof(name));
522 				if (iflen >= sizeof(name))
523 					errx(1, "%s: cloning name too long",
524 					    ifname);
525 				ifconfig(argc, argv, 1, NULL);
526 				exit(exit_code);
527 			}
528 #ifdef JAIL
529 			/*
530 			 * NOTE:  We have to special-case the `-vnet' command
531 			 * right here as we would otherwise fail when trying
532 			 * to find the interface as it lives in another vnet.
533 			 */
534 			if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) {
535 				iflen = strlcpy(name, ifname, sizeof(name));
536 				if (iflen >= sizeof(name))
537 					errx(1, "%s: interface name too long",
538 					    ifname);
539 				ifconfig(argc, argv, 0, NULL);
540 				exit(exit_code);
541 			}
542 #endif
543 			errx(1, "interface %s does not exist", ifname);
544 		} else {
545 			/*
546 			 * Do not allow use `create` command as hostname if
547 			 * address family is not specified.
548 			 */
549 			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
550 			    strcmp(argv[0], "plumb") == 0)) {
551 				if (argc == 1)
552 					errx(1, "interface %s already exists",
553 					    ifname);
554 				argc--, argv++;
555 			}
556 		}
557 	}
558 
559 	/* Check for address family */
560 	if (argc > 0) {
561 		afp = af_getbyname(*argv);
562 		if (afp != NULL)
563 			argc--, argv++;
564 	}
565 
566 	/*
567 	 * Check for a requested configuration action on a single interface,
568 	 * which doesn't require building, sorting, and searching the entire
569 	 * system address list
570 	 */
571 	if ((argc > 0) && (ifname != NULL)) {
572 		iflen = strlcpy(name, ifname, sizeof(name));
573 		if (iflen >= sizeof(name)) {
574 			warnx("%s: interface name too long, skipping", ifname);
575 		} else {
576 			flags = getifflags(name, -1);
577 			if (!(((flags & IFF_CANTCONFIG) != 0) ||
578 				(downonly && (flags & IFF_UP) != 0) ||
579 				(uponly && (flags & IFF_UP) == 0)))
580 				ifconfig(argc, argv, 0, afp);
581 		}
582 		goto done;
583 	}
584 
585 	if (getifaddrs(&ifap) != 0)
586 		err(EXIT_FAILURE, "getifaddrs");
587 
588 	cp = NULL;
589 
590 	if (calcorders(ifap, &q) != 0)
591 		err(EXIT_FAILURE, "calcorders");
592 
593 	sifap = sortifaddrs(ifap, cmpifaddrs, &q);
594 
595 	TAILQ_FOREACH_SAFE(cur, &q, link, tmp)
596 		free(cur);
597 
598 	ifindex = 0;
599 	for (ifa = sifap; ifa; ifa = ifa->ifa_next) {
600 		memset(&paifr, 0, sizeof(paifr));
601 		strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
602 		if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
603 			memcpy(&paifr.ifr_addr, ifa->ifa_addr,
604 			    ifa->ifa_addr->sa_len);
605 		}
606 
607 		if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
608 			continue;
609 		if (ifa->ifa_addr->sa_family == AF_LINK)
610 			sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
611 		else
612 			sdl = NULL;
613 		if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly)
614 			continue;
615 		iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
616 		if (iflen >= sizeof(name)) {
617 			warnx("%s: interface name too long, skipping",
618 			    ifa->ifa_name);
619 			continue;
620 		}
621 		cp = ifa->ifa_name;
622 
623 		if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0)
624 			continue;
625 		if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
626 			continue;
627 		if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
628 			continue;
629 		/*
630 		 * Are we just listing the interfaces?
631 		 */
632 		if (namesonly) {
633 			if (namecp == cp)
634 				continue;
635 			if (afp != NULL) {
636 				/* special case for "ether" address family */
637 				if (!strcmp(afp->af_name, "ether")) {
638 					if (sdl == NULL ||
639 					    (sdl->sdl_type != IFT_ETHER &&
640 					    sdl->sdl_type != IFT_L2VLAN &&
641 					    sdl->sdl_type != IFT_BRIDGE) ||
642 					    sdl->sdl_alen != ETHER_ADDR_LEN)
643 						continue;
644 				} else {
645 					if (ifa->ifa_addr->sa_family
646 					    != afp->af_af)
647 						continue;
648 				}
649 			}
650 			namecp = cp;
651 			ifindex++;
652 			if (ifindex > 1)
653 				printf(" ");
654 			fputs(name, stdout);
655 			continue;
656 		}
657 		ifindex++;
658 
659 		if (argc > 0)
660 			ifconfig(argc, argv, 0, afp);
661 		else
662 			status(afp, sdl, ifa);
663 	}
664 	if (namesonly)
665 		printf("\n");
666 	freeifaddrs(ifap);
667 
668 done:
669 	freeformat();
670 	exit(exit_code);
671 }
672 
673 static struct afswtch *afs = NULL;
674 
675 void
676 af_register(struct afswtch *p)
677 {
678 	p->af_next = afs;
679 	afs = p;
680 }
681 
682 static struct afswtch *
683 af_getbyname(const char *name)
684 {
685 	struct afswtch *afp;
686 
687 	for (afp = afs; afp !=  NULL; afp = afp->af_next)
688 		if (strcmp(afp->af_name, name) == 0)
689 			return afp;
690 	return NULL;
691 }
692 
693 static struct afswtch *
694 af_getbyfamily(int af)
695 {
696 	struct afswtch *afp;
697 
698 	for (afp = afs; afp != NULL; afp = afp->af_next)
699 		if (afp->af_af == af)
700 			return afp;
701 	return NULL;
702 }
703 
704 static void
705 af_other_status(int s)
706 {
707 	struct afswtch *afp;
708 	uint8_t afmask[howmany(AF_MAX, NBBY)];
709 
710 	memset(afmask, 0, sizeof(afmask));
711 	for (afp = afs; afp != NULL; afp = afp->af_next) {
712 		if (afp->af_other_status == NULL)
713 			continue;
714 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
715 			continue;
716 		afp->af_other_status(s);
717 		setbit(afmask, afp->af_af);
718 	}
719 }
720 
721 static void
722 af_all_tunnel_status(int s)
723 {
724 	struct afswtch *afp;
725 	uint8_t afmask[howmany(AF_MAX, NBBY)];
726 
727 	memset(afmask, 0, sizeof(afmask));
728 	for (afp = afs; afp != NULL; afp = afp->af_next) {
729 		if (afp->af_status_tunnel == NULL)
730 			continue;
731 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
732 			continue;
733 		afp->af_status_tunnel(s);
734 		setbit(afmask, afp->af_af);
735 	}
736 }
737 
738 static struct cmd *cmds = NULL;
739 
740 void
741 cmd_register(struct cmd *p)
742 {
743 	p->c_next = cmds;
744 	cmds = p;
745 }
746 
747 static const struct cmd *
748 cmd_lookup(const char *name, int iscreate)
749 {
750 	const struct cmd *p;
751 
752 	for (p = cmds; p != NULL; p = p->c_next)
753 		if (strcmp(name, p->c_name) == 0) {
754 			if (iscreate) {
755 				if (p->c_iscloneop)
756 					return p;
757 			} else {
758 				if (!p->c_iscloneop)
759 					return p;
760 			}
761 		}
762 	return NULL;
763 }
764 
765 struct callback {
766 	callback_func *cb_func;
767 	void	*cb_arg;
768 	struct callback *cb_next;
769 };
770 static struct callback *callbacks = NULL;
771 
772 void
773 callback_register(callback_func *func, void *arg)
774 {
775 	struct callback *cb;
776 
777 	cb = malloc(sizeof(struct callback));
778 	if (cb == NULL)
779 		errx(1, "unable to allocate memory for callback");
780 	cb->cb_func = func;
781 	cb->cb_arg = arg;
782 	cb->cb_next = callbacks;
783 	callbacks = cb;
784 }
785 
786 /* specially-handled commands */
787 static void setifaddr(const char *, int, int, const struct afswtch *);
788 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
789 
790 static void setifdstaddr(const char *, int, int, const struct afswtch *);
791 static const struct cmd setifdstaddr_cmd =
792 	DEF_CMD("ifdstaddr", 0, setifdstaddr);
793 
794 static int
795 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
796 {
797 	const struct afswtch *afp, *nafp;
798 	const struct cmd *p;
799 	struct callback *cb;
800 	int s;
801 
802 	strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
803 	afp = NULL;
804 	if (uafp != NULL)
805 		afp = uafp;
806 	/*
807 	 * This is the historical "accident" allowing users to configure IPv4
808 	 * addresses without the "inet" keyword which while a nice feature has
809 	 * proven to complicate other things.  We cannot remove this but only
810 	 * make sure we will never have a similar implicit default for IPv6 or
811 	 * any other address familiy.  We need a fallback though for
812 	 * ifconfig IF up/down etc. to work without INET support as people
813 	 * never used ifconfig IF link up/down, etc. either.
814 	 */
815 #ifndef RESCUE
816 #ifdef INET
817 	if (afp == NULL && feature_present("inet"))
818 		afp = af_getbyname("inet");
819 #endif
820 #endif
821 	if (afp == NULL)
822 		afp = af_getbyname("link");
823 	if (afp == NULL) {
824 		warnx("Please specify an address_family.");
825 		usage();
826 	}
827 top:
828 	ifr.ifr_addr.sa_family =
829 		afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
830 		AF_LOCAL : afp->af_af;
831 
832 	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 &&
833 	    (uafp != NULL || errno != EAFNOSUPPORT ||
834 	     (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0))
835 		err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
836 
837 	while (argc > 0) {
838 		p = cmd_lookup(*argv, iscreate);
839 		if (iscreate && p == NULL) {
840 			/*
841 			 * Push the clone create callback so the new
842 			 * device is created and can be used for any
843 			 * remaining arguments.
844 			 */
845 			cb = callbacks;
846 			if (cb == NULL)
847 				errx(1, "internal error, no callback");
848 			callbacks = cb->cb_next;
849 			cb->cb_func(s, cb->cb_arg);
850 			iscreate = 0;
851 			/*
852 			 * Handle any address family spec that
853 			 * immediately follows and potentially
854 			 * recreate the socket.
855 			 */
856 			nafp = af_getbyname(*argv);
857 			if (nafp != NULL) {
858 				argc--, argv++;
859 				if (nafp != afp) {
860 					close(s);
861 					afp = nafp;
862 					goto top;
863 				}
864 			}
865 			/*
866 			 * Look for a normal parameter.
867 			 */
868 			continue;
869 		}
870 		if (p == NULL) {
871 			/*
872 			 * Not a recognized command, choose between setting
873 			 * the interface address and the dst address.
874 			 */
875 			p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
876 		}
877 		if (p->c_parameter == NEXTARG && p->c_u.c_func) {
878 			if (argv[1] == NULL)
879 				errx(1, "'%s' requires argument",
880 				    p->c_name);
881 			p->c_u.c_func(argv[1], 0, s, afp);
882 			argc--, argv++;
883 		} else if (p->c_parameter == OPTARG && p->c_u.c_func) {
884 			p->c_u.c_func(argv[1], 0, s, afp);
885 			if (argv[1] != NULL)
886 				argc--, argv++;
887 		} else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) {
888 			if (argc < 3)
889 				errx(1, "'%s' requires 2 arguments",
890 				    p->c_name);
891 			p->c_u.c_func2(argv[1], argv[2], s, afp);
892 			argc -= 2, argv += 2;
893 		} else if (p->c_u.c_func)
894 			p->c_u.c_func(*argv, p->c_parameter, s, afp);
895 		argc--, argv++;
896 	}
897 
898 	/*
899 	 * Do any post argument processing required by the address family.
900 	 */
901 	if (afp->af_postproc != NULL)
902 		afp->af_postproc(s, afp);
903 	/*
904 	 * Do deferred callbacks registered while processing
905 	 * command-line arguments.
906 	 */
907 	for (cb = callbacks; cb != NULL; cb = cb->cb_next)
908 		cb->cb_func(s, cb->cb_arg);
909 	/*
910 	 * Do deferred operations.
911 	 */
912 	if (clearaddr) {
913 		if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
914 			warnx("interface %s cannot change %s addresses!",
915 			      name, afp->af_name);
916 			clearaddr = 0;
917 		}
918 	}
919 	if (clearaddr) {
920 		int ret;
921 		strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name,
922 			sizeof ifr.ifr_name);
923 		ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
924 		if (ret < 0) {
925 			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
926 				/* means no previous address for interface */
927 			} else
928 				Perror("ioctl (SIOCDIFADDR)");
929 		}
930 	}
931 	if (newaddr) {
932 		if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
933 			warnx("interface %s cannot change %s addresses!",
934 			      name, afp->af_name);
935 			newaddr = 0;
936 		}
937 	}
938 	if (newaddr && (setaddr || setmask)) {
939 		strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name,
940 			sizeof ifr.ifr_name);
941 		if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
942 			Perror("ioctl (SIOCAIFADDR)");
943 	}
944 
945 	close(s);
946 	return(0);
947 }
948 
949 /*ARGSUSED*/
950 static void
951 setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
952 {
953 	if (afp->af_getaddr == NULL)
954 		return;
955 	/*
956 	 * Delay the ioctl to set the interface addr until flags are all set.
957 	 * The address interpretation may depend on the flags,
958 	 * and the flags may change when the address is set.
959 	 */
960 	setaddr++;
961 	if (doalias == 0 && afp->af_af != AF_LINK)
962 		clearaddr = 1;
963 	afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
964 }
965 
966 static void
967 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
968 {
969 	struct addrinfo *srcres, *dstres;
970 	int ecode;
971 
972 	if (afp->af_settunnel == NULL) {
973 		warn("address family %s does not support tunnel setup",
974 			afp->af_name);
975 		return;
976 	}
977 
978 	if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
979 		errx(1, "error in parsing address string: %s",
980 		    gai_strerror(ecode));
981 
982 	if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
983 		errx(1, "error in parsing address string: %s",
984 		    gai_strerror(ecode));
985 
986 	if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
987 		errx(1,
988 		    "source and destination address families do not match");
989 
990 	afp->af_settunnel(s, srcres, dstres);
991 
992 	freeaddrinfo(srcres);
993 	freeaddrinfo(dstres);
994 }
995 
996 /* ARGSUSED */
997 static void
998 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
999 {
1000 
1001 	if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
1002 		err(1, "SIOCDIFPHYADDR");
1003 }
1004 
1005 #ifdef JAIL
1006 static void
1007 setifvnet(const char *jname, int dummy __unused, int s,
1008     const struct afswtch *afp)
1009 {
1010 	struct ifreq my_ifr;
1011 
1012 	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
1013 	my_ifr.ifr_jid = jail_getid(jname);
1014 	if (my_ifr.ifr_jid < 0)
1015 		errx(1, "%s", jail_errmsg);
1016 	if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0)
1017 		err(1, "SIOCSIFVNET");
1018 }
1019 
1020 static void
1021 setifrvnet(const char *jname, int dummy __unused, int s,
1022     const struct afswtch *afp)
1023 {
1024 	struct ifreq my_ifr;
1025 
1026 	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
1027 	my_ifr.ifr_jid = jail_getid(jname);
1028 	if (my_ifr.ifr_jid < 0)
1029 		errx(1, "%s", jail_errmsg);
1030 	if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0)
1031 		err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
1032 }
1033 #endif
1034 
1035 static void
1036 setifnetmask(const char *addr, int dummy __unused, int s,
1037     const struct afswtch *afp)
1038 {
1039 	if (afp->af_getaddr != NULL) {
1040 		setmask++;
1041 		afp->af_getaddr(addr, MASK);
1042 	}
1043 }
1044 
1045 static void
1046 setifbroadaddr(const char *addr, int dummy __unused, int s,
1047     const struct afswtch *afp)
1048 {
1049 	if (afp->af_getaddr != NULL)
1050 		afp->af_getaddr(addr, DSTADDR);
1051 }
1052 
1053 static void
1054 notealias(const char *addr, int param, int s, const struct afswtch *afp)
1055 {
1056 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
1057 	if (setaddr && doalias == 0 && param < 0)
1058 		if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
1059 			bcopy((caddr_t)rqtosa(af_addreq),
1060 			      (caddr_t)rqtosa(af_ridreq),
1061 			      rqtosa(af_addreq)->sa_len);
1062 	doalias = param;
1063 	if (param < 0) {
1064 		clearaddr = 1;
1065 		newaddr = 0;
1066 	} else
1067 		clearaddr = 0;
1068 #undef rqtosa
1069 }
1070 
1071 /*ARGSUSED*/
1072 static void
1073 setifdstaddr(const char *addr, int param __unused, int s,
1074     const struct afswtch *afp)
1075 {
1076 	if (afp->af_getaddr != NULL)
1077 		afp->af_getaddr(addr, DSTADDR);
1078 }
1079 
1080 static int
1081 getifflags(const char *ifname, int us)
1082 {
1083 	struct ifreq my_ifr;
1084 	int s;
1085 
1086 	memset(&my_ifr, 0, sizeof(my_ifr));
1087 	(void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name));
1088 	if (us < 0) {
1089 		if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
1090 			err(1, "socket(family AF_LOCAL,SOCK_DGRAM");
1091 	} else
1092 		s = us;
1093  	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
1094  		Perror("ioctl (SIOCGIFFLAGS)");
1095  		exit(1);
1096  	}
1097 	if (us < 0)
1098 		close(s);
1099 	return ((my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16));
1100 }
1101 
1102 /*
1103  * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
1104  * of the ifreq structure, which may confuse other parts of ifconfig.
1105  * Make a private copy so we can avoid that.
1106  */
1107 static void
1108 setifflags(const char *vname, int value, int s, const struct afswtch *afp)
1109 {
1110 	struct ifreq		my_ifr;
1111 	int flags;
1112 
1113 	flags = getifflags(name, s);
1114 	if (value < 0) {
1115 		value = -value;
1116 		flags &= ~value;
1117 	} else
1118 		flags |= value;
1119 	memset(&my_ifr, 0, sizeof(my_ifr));
1120 	(void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name));
1121 	my_ifr.ifr_flags = flags & 0xffff;
1122 	my_ifr.ifr_flagshigh = flags >> 16;
1123 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
1124 		Perror(vname);
1125 }
1126 
1127 void
1128 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
1129 {
1130 	int flags;
1131 
1132  	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
1133  		Perror("ioctl (SIOCGIFCAP)");
1134  		exit(1);
1135  	}
1136 	flags = ifr.ifr_curcap;
1137 	if (value < 0) {
1138 		value = -value;
1139 		flags &= ~value;
1140 	} else
1141 		flags |= value;
1142 	flags &= ifr.ifr_reqcap;
1143 	ifr.ifr_reqcap = flags;
1144 	if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
1145 		Perror(vname);
1146 }
1147 
1148 static void
1149 setifmetric(const char *val, int dummy __unused, int s,
1150     const struct afswtch *afp)
1151 {
1152 	strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1153 	ifr.ifr_metric = atoi(val);
1154 	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
1155 		err(1, "ioctl SIOCSIFMETRIC (set metric)");
1156 }
1157 
1158 static void
1159 setifmtu(const char *val, int dummy __unused, int s,
1160     const struct afswtch *afp)
1161 {
1162 	strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1163 	ifr.ifr_mtu = atoi(val);
1164 	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
1165 		err(1, "ioctl SIOCSIFMTU (set mtu)");
1166 }
1167 
1168 static void
1169 setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp)
1170 {
1171 	u_long ul;
1172 	char *endp;
1173 
1174 	ul = strtoul(val, &endp, 0);
1175 	if (*endp != '\0')
1176 		errx(1, "invalid value for pcp");
1177 	if (ul > 7)
1178 		errx(1, "value for pcp out of range");
1179 	ifr.ifr_lan_pcp = ul;
1180 	if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
1181 		err(1, "SIOCSLANPCP");
1182 }
1183 
1184 static void
1185 disableifpcp(const char *val, int arg __unused, int s,
1186     const struct afswtch *afp)
1187 {
1188 
1189 	ifr.ifr_lan_pcp = IFNET_PCP_NONE;
1190 	if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
1191 		err(1, "SIOCSLANPCP");
1192 }
1193 
1194 static void
1195 setifname(const char *val, int dummy __unused, int s,
1196     const struct afswtch *afp)
1197 {
1198 	char *newname;
1199 
1200 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1201 
1202 	newname = strdup(val);
1203 	if (newname == NULL)
1204 		err(1, "no memory to set ifname");
1205 	ifr.ifr_data = newname;
1206 	if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
1207 		free(newname);
1208 		err(1, "ioctl SIOCSIFNAME (set name)");
1209 	}
1210 	printifname = 1;
1211 	strlcpy(name, newname, sizeof(name));
1212 	free(newname);
1213 }
1214 
1215 /* ARGSUSED */
1216 static void
1217 setifdescr(const char *val, int dummy __unused, int s,
1218     const struct afswtch *afp)
1219 {
1220 	char *newdescr;
1221 
1222 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1223 
1224 	ifr.ifr_buffer.length = strlen(val) + 1;
1225 	if (ifr.ifr_buffer.length == 1) {
1226 		ifr.ifr_buffer.buffer = newdescr = NULL;
1227 		ifr.ifr_buffer.length = 0;
1228 	} else {
1229 		newdescr = strdup(val);
1230 		ifr.ifr_buffer.buffer = newdescr;
1231 		if (newdescr == NULL) {
1232 			warn("no memory to set ifdescr");
1233 			return;
1234 		}
1235 	}
1236 
1237 	if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
1238 		err(1, "ioctl SIOCSIFDESCR (set descr)");
1239 
1240 	free(newdescr);
1241 }
1242 
1243 /* ARGSUSED */
1244 static void
1245 unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
1246 {
1247 
1248 	setifdescr("", 0, s, 0);
1249 }
1250 
1251 #define	IFFBITS \
1252 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
1253 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1254 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP"
1255 
1256 #define	IFCAPBITS \
1257 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
1258 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
1259 "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \
1260 "\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6"
1261 
1262 /*
1263  * Print the status of the interface.  If an address family was
1264  * specified, show only it; otherwise, show them all.
1265  */
1266 static void
1267 status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
1268 	struct ifaddrs *ifa)
1269 {
1270 	struct ifaddrs *ift;
1271 	int allfamilies, s;
1272 	struct ifstat ifs;
1273 
1274 	if (afp == NULL) {
1275 		allfamilies = 1;
1276 		ifr.ifr_addr.sa_family = AF_LOCAL;
1277 	} else {
1278 		allfamilies = 0;
1279 		ifr.ifr_addr.sa_family =
1280 		    afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af;
1281 	}
1282 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1283 
1284 	s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
1285 	if (s < 0)
1286 		err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
1287 
1288 	printf("%s: ", name);
1289 	printb("flags", ifa->ifa_flags, IFFBITS);
1290 	if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
1291 		printf(" metric %d", ifr.ifr_metric);
1292 	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
1293 		printf(" mtu %d", ifr.ifr_mtu);
1294 	putchar('\n');
1295 
1296 	for (;;) {
1297 		if ((descr = reallocf(descr, descrlen)) != NULL) {
1298 			ifr.ifr_buffer.buffer = descr;
1299 			ifr.ifr_buffer.length = descrlen;
1300 			if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
1301 				if (ifr.ifr_buffer.buffer == descr) {
1302 					if (strlen(descr) > 0)
1303 						printf("\tdescription: %s\n",
1304 						    descr);
1305 				} else if (ifr.ifr_buffer.length > descrlen) {
1306 					descrlen = ifr.ifr_buffer.length;
1307 					continue;
1308 				}
1309 			}
1310 		} else
1311 			warn("unable to allocate memory for interface"
1312 			    "description");
1313 		break;
1314 	}
1315 
1316 	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
1317 		if (ifr.ifr_curcap != 0) {
1318 			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
1319 			putchar('\n');
1320 		}
1321 		if (supmedia && ifr.ifr_reqcap != 0) {
1322 			printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
1323 			putchar('\n');
1324 		}
1325 	}
1326 
1327 	tunnel_status(s);
1328 
1329 	for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
1330 		if (ift->ifa_addr == NULL)
1331 			continue;
1332 		if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
1333 			continue;
1334 		if (allfamilies) {
1335 			const struct afswtch *p;
1336 			p = af_getbyfamily(ift->ifa_addr->sa_family);
1337 			if (p != NULL && p->af_status != NULL)
1338 				p->af_status(s, ift);
1339 		} else if (afp->af_af == ift->ifa_addr->sa_family)
1340 			afp->af_status(s, ift);
1341 	}
1342 #if 0
1343 	if (allfamilies || afp->af_af == AF_LINK) {
1344 		const struct afswtch *lafp;
1345 
1346 		/*
1347 		 * Hack; the link level address is received separately
1348 		 * from the routing information so any address is not
1349 		 * handled above.  Cobble together an entry and invoke
1350 		 * the status method specially.
1351 		 */
1352 		lafp = af_getbyname("lladdr");
1353 		if (lafp != NULL) {
1354 			info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
1355 			lafp->af_status(s, &info);
1356 		}
1357 	}
1358 #endif
1359 	if (allfamilies)
1360 		af_other_status(s);
1361 	else if (afp->af_other_status != NULL)
1362 		afp->af_other_status(s);
1363 
1364 	strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
1365 	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
1366 		printf("%s", ifs.ascii);
1367 
1368 	if (verbose > 0)
1369 		sfp_status(s, &ifr, verbose);
1370 
1371 	close(s);
1372 	return;
1373 }
1374 
1375 static void
1376 tunnel_status(int s)
1377 {
1378 	af_all_tunnel_status(s);
1379 }
1380 
1381 void
1382 Perror(const char *cmd)
1383 {
1384 	switch (errno) {
1385 
1386 	case ENXIO:
1387 		errx(1, "%s: no such interface", cmd);
1388 		break;
1389 
1390 	case EPERM:
1391 		errx(1, "%s: permission denied", cmd);
1392 		break;
1393 
1394 	default:
1395 		err(1, "%s", cmd);
1396 	}
1397 }
1398 
1399 /*
1400  * Print a value a la the %b format of the kernel's printf
1401  */
1402 void
1403 printb(const char *s, unsigned v, const char *bits)
1404 {
1405 	int i, any = 0;
1406 	char c;
1407 
1408 	if (bits && *bits == 8)
1409 		printf("%s=%o", s, v);
1410 	else
1411 		printf("%s=%x", s, v);
1412 	if (bits) {
1413 		bits++;
1414 		putchar('<');
1415 		while ((i = *bits++) != '\0') {
1416 			if (v & (1 << (i-1))) {
1417 				if (any)
1418 					putchar(',');
1419 				any = 1;
1420 				for (; (c = *bits) > 32; bits++)
1421 					putchar(c);
1422 			} else
1423 				for (; *bits > 32; bits++)
1424 					;
1425 		}
1426 		putchar('>');
1427 	}
1428 }
1429 
1430 void
1431 print_vhid(const struct ifaddrs *ifa, const char *s)
1432 {
1433 	struct if_data *ifd;
1434 
1435 	if (ifa->ifa_data == NULL)
1436 		return;
1437 
1438 	ifd = ifa->ifa_data;
1439 	if (ifd->ifi_vhid == 0)
1440 		return;
1441 
1442 	printf(" vhid %d", ifd->ifi_vhid);
1443 }
1444 
1445 void
1446 ifmaybeload(const char *name)
1447 {
1448 #define MOD_PREFIX_LEN		3	/* "if_" */
1449 	struct module_stat mstat;
1450 	int i, fileid, modid;
1451 	char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
1452 	const char *cp;
1453 	struct module_map_entry *mme;
1454 	bool found;
1455 
1456 	/* loading suppressed by the user */
1457 	if (noload)
1458 		return;
1459 
1460 	/* trim the interface number off the end */
1461 	strlcpy(ifname, name, sizeof(ifname));
1462 	for (dp = ifname; *dp != 0; dp++)
1463 		if (isdigit(*dp)) {
1464 			*dp = 0;
1465 			break;
1466 		}
1467 
1468 	/* Either derive it from the map or guess otherwise */
1469 	*ifkind = '\0';
1470 	found = false;
1471 	for (i = 0; i < nitems(module_map); ++i) {
1472 		mme = &module_map[i];
1473 		if (strcmp(mme->ifname, ifname) == 0) {
1474 			strlcpy(ifkind, mme->kldname, sizeof(ifkind));
1475 			found = true;
1476 			break;
1477 		}
1478 	}
1479 
1480 	/* We didn't have an alias for it... we'll guess. */
1481 	if (!found) {
1482 	    /* turn interface and unit into module name */
1483 	    strlcpy(ifkind, "if_", sizeof(ifkind));
1484 	    strlcat(ifkind, ifname, sizeof(ifkind));
1485 	}
1486 
1487 	/* scan files in kernel */
1488 	mstat.version = sizeof(struct module_stat);
1489 	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1490 		/* scan modules in file */
1491 		for (modid = kldfirstmod(fileid); modid > 0;
1492 		     modid = modfnext(modid)) {
1493 			if (modstat(modid, &mstat) < 0)
1494 				continue;
1495 			/* strip bus name if present */
1496 			if ((cp = strchr(mstat.name, '/')) != NULL) {
1497 				cp++;
1498 			} else {
1499 				cp = mstat.name;
1500 			}
1501 			/*
1502 			 * Is it already loaded?  Don't compare with ifname if
1503 			 * we were specifically told which kld to use.  Doing
1504 			 * so could lead to conflicts not trivially solved.
1505 			 */
1506 			if ((!found && strcmp(ifname, cp) == 0) ||
1507 			    strcmp(ifkind, cp) == 0)
1508 				return;
1509 		}
1510 	}
1511 
1512 	/*
1513 	 * Try to load the module.  But ignore failures, because ifconfig can't
1514 	 * infer the names of all drivers (eg mlx4en(4)).
1515 	 */
1516 	(void) kldload(ifkind);
1517 }
1518 
1519 static struct cmd basic_cmds[] = {
1520 	DEF_CMD("up",		IFF_UP,		setifflags),
1521 	DEF_CMD("down",		-IFF_UP,	setifflags),
1522 	DEF_CMD("arp",		-IFF_NOARP,	setifflags),
1523 	DEF_CMD("-arp",		IFF_NOARP,	setifflags),
1524 	DEF_CMD("debug",	IFF_DEBUG,	setifflags),
1525 	DEF_CMD("-debug",	-IFF_DEBUG,	setifflags),
1526 	DEF_CMD_ARG("description",		setifdescr),
1527 	DEF_CMD_ARG("descr",			setifdescr),
1528 	DEF_CMD("-description",	0,		unsetifdescr),
1529 	DEF_CMD("-descr",	0,		unsetifdescr),
1530 	DEF_CMD("promisc",	IFF_PPROMISC,	setifflags),
1531 	DEF_CMD("-promisc",	-IFF_PPROMISC,	setifflags),
1532 	DEF_CMD("add",		IFF_UP,		notealias),
1533 	DEF_CMD("alias",	IFF_UP,		notealias),
1534 	DEF_CMD("-alias",	-IFF_UP,	notealias),
1535 	DEF_CMD("delete",	-IFF_UP,	notealias),
1536 	DEF_CMD("remove",	-IFF_UP,	notealias),
1537 #ifdef notdef
1538 #define	EN_SWABIPS	0x1000
1539 	DEF_CMD("swabips",	EN_SWABIPS,	setifflags),
1540 	DEF_CMD("-swabips",	-EN_SWABIPS,	setifflags),
1541 #endif
1542 	DEF_CMD_ARG("netmask",			setifnetmask),
1543 	DEF_CMD_ARG("metric",			setifmetric),
1544 	DEF_CMD_ARG("broadcast",		setifbroadaddr),
1545 	DEF_CMD_ARG2("tunnel",			settunnel),
1546 	DEF_CMD("-tunnel", 0,			deletetunnel),
1547 	DEF_CMD("deletetunnel", 0,		deletetunnel),
1548 #ifdef JAIL
1549 	DEF_CMD_ARG("vnet",			setifvnet),
1550 	DEF_CMD_ARG("-vnet",			setifrvnet),
1551 #endif
1552 	DEF_CMD("link0",	IFF_LINK0,	setifflags),
1553 	DEF_CMD("-link0",	-IFF_LINK0,	setifflags),
1554 	DEF_CMD("link1",	IFF_LINK1,	setifflags),
1555 	DEF_CMD("-link1",	-IFF_LINK1,	setifflags),
1556 	DEF_CMD("link2",	IFF_LINK2,	setifflags),
1557 	DEF_CMD("-link2",	-IFF_LINK2,	setifflags),
1558 	DEF_CMD("monitor",	IFF_MONITOR,	setifflags),
1559 	DEF_CMD("-monitor",	-IFF_MONITOR,	setifflags),
1560 	DEF_CMD("nomap",	IFCAP_NOMAP,	setifcap),
1561 	DEF_CMD("-nomap",	-IFCAP_NOMAP,	setifcap),
1562 	DEF_CMD("staticarp",	IFF_STATICARP,	setifflags),
1563 	DEF_CMD("-staticarp",	-IFF_STATICARP,	setifflags),
1564 	DEF_CMD("rxcsum6",	IFCAP_RXCSUM_IPV6,	setifcap),
1565 	DEF_CMD("-rxcsum6",	-IFCAP_RXCSUM_IPV6,	setifcap),
1566 	DEF_CMD("txcsum6",	IFCAP_TXCSUM_IPV6,	setifcap),
1567 	DEF_CMD("-txcsum6",	-IFCAP_TXCSUM_IPV6,	setifcap),
1568 	DEF_CMD("rxcsum",	IFCAP_RXCSUM,	setifcap),
1569 	DEF_CMD("-rxcsum",	-IFCAP_RXCSUM,	setifcap),
1570 	DEF_CMD("txcsum",	IFCAP_TXCSUM,	setifcap),
1571 	DEF_CMD("-txcsum",	-IFCAP_TXCSUM,	setifcap),
1572 	DEF_CMD("netcons",	IFCAP_NETCONS,	setifcap),
1573 	DEF_CMD("-netcons",	-IFCAP_NETCONS,	setifcap),
1574 	DEF_CMD_ARG("pcp",			setifpcp),
1575 	DEF_CMD("-pcp", 0,			disableifpcp),
1576 	DEF_CMD("polling",	IFCAP_POLLING,	setifcap),
1577 	DEF_CMD("-polling",	-IFCAP_POLLING,	setifcap),
1578 	DEF_CMD("tso6",		IFCAP_TSO6,	setifcap),
1579 	DEF_CMD("-tso6",	-IFCAP_TSO6,	setifcap),
1580 	DEF_CMD("tso4",		IFCAP_TSO4,	setifcap),
1581 	DEF_CMD("-tso4",	-IFCAP_TSO4,	setifcap),
1582 	DEF_CMD("tso",		IFCAP_TSO,	setifcap),
1583 	DEF_CMD("-tso",		-IFCAP_TSO,	setifcap),
1584 	DEF_CMD("toe",		IFCAP_TOE,	setifcap),
1585 	DEF_CMD("-toe",		-IFCAP_TOE,	setifcap),
1586 	DEF_CMD("lro",		IFCAP_LRO,	setifcap),
1587 	DEF_CMD("-lro",		-IFCAP_LRO,	setifcap),
1588 	DEF_CMD("txtls",	IFCAP_TXTLS,	setifcap),
1589 	DEF_CMD("-txtls",	-IFCAP_TXTLS,	setifcap),
1590 	DEF_CMD("wol",		IFCAP_WOL,	setifcap),
1591 	DEF_CMD("-wol",		-IFCAP_WOL,	setifcap),
1592 	DEF_CMD("wol_ucast",	IFCAP_WOL_UCAST,	setifcap),
1593 	DEF_CMD("-wol_ucast",	-IFCAP_WOL_UCAST,	setifcap),
1594 	DEF_CMD("wol_mcast",	IFCAP_WOL_MCAST,	setifcap),
1595 	DEF_CMD("-wol_mcast",	-IFCAP_WOL_MCAST,	setifcap),
1596 	DEF_CMD("wol_magic",	IFCAP_WOL_MAGIC,	setifcap),
1597 	DEF_CMD("-wol_magic",	-IFCAP_WOL_MAGIC,	setifcap),
1598 	DEF_CMD("txrtlmt",	IFCAP_TXRTLMT,	setifcap),
1599 	DEF_CMD("-txrtlmt",	-IFCAP_TXRTLMT,	setifcap),
1600 	DEF_CMD("hwrxtstmp",	IFCAP_HWRXTSTMP,	setifcap),
1601 	DEF_CMD("-hwrxtstmp",	-IFCAP_HWRXTSTMP,	setifcap),
1602 	DEF_CMD("normal",	-IFF_LINK0,	setifflags),
1603 	DEF_CMD("compress",	IFF_LINK0,	setifflags),
1604 	DEF_CMD("noicmp",	IFF_LINK1,	setifflags),
1605 	DEF_CMD_ARG("mtu",			setifmtu),
1606 	DEF_CMD_ARG("name",			setifname),
1607 };
1608 
1609 static __constructor void
1610 ifconfig_ctor(void)
1611 {
1612 	size_t i;
1613 
1614 	for (i = 0; i < nitems(basic_cmds);  i++)
1615 		cmd_register(&basic_cmds[i]);
1616 }
1617