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