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