xref: /freebsd/sbin/ifconfig/ifconfig.c (revision 721351876cd4d3a8a700f62d2061331fa951a488)
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  * 4. 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 
30 #ifndef lint
31 static const char copyright[] =
32 "@(#) Copyright (c) 1983, 1993\n\
33 	The Regents of the University of California.  All rights reserved.\n";
34 #endif /* not lint */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
39 #endif
40 static const char rcsid[] =
41   "$FreeBSD$";
42 #endif /* not lint */
43 
44 #include <sys/param.h>
45 #include <sys/ioctl.h>
46 #include <sys/socket.h>
47 #include <sys/sysctl.h>
48 #include <sys/time.h>
49 #include <sys/module.h>
50 #include <sys/linker.h>
51 
52 #include <net/ethernet.h>
53 #include <net/if.h>
54 #include <net/if_gre.h>
55 #include <net/if_var.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 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <unistd.h>
75 
76 #include "ifconfig.h"
77 
78 /*
79  * Since "struct ifreq" is composed of various union members, callers
80  * should pay special attention to interprete the value.
81  * (.e.g. little/big endian difference in the structure.)
82  */
83 struct	ifreq ifr;
84 
85 char	name[IFNAMSIZ];
86 int	setaddr;
87 int	setmask;
88 int	doalias;
89 int	clearaddr;
90 int	newaddr = 1;
91 int	verbose;
92 int	noload;
93 
94 int	supmedia = 0;
95 int	printkeys = 0;		/* Print keying material for interfaces. */
96 
97 static	int ifconfig(int argc, char *const *argv, int iscreate,
98 		const struct afswtch *afp);
99 static	void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
100 		struct ifaddrs *ifa);
101 static	void tunnel_status(int s);
102 static	void usage(void);
103 
104 static struct afswtch *af_getbyname(const char *name);
105 static struct afswtch *af_getbyfamily(int af);
106 static void af_other_status(int);
107 
108 static struct option *opts = NULL;
109 
110 void
111 opt_register(struct option *p)
112 {
113 	p->next = opts;
114 	opts = p;
115 }
116 
117 static void
118 usage(void)
119 {
120 	char options[1024];
121 	struct option *p;
122 
123 	/* XXX not right but close enough for now */
124 	options[0] = '\0';
125 	for (p = opts; p != NULL; p = p->next) {
126 		strlcat(options, p->opt_usage, sizeof(options));
127 		strlcat(options, " ", sizeof(options));
128 	}
129 
130 	fprintf(stderr,
131 	"usage: ifconfig %sinterface address_family [address [dest_address]]\n"
132 	"                [parameters]\n"
133 	"       ifconfig interface create\n"
134 	"       ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
135 	"       ifconfig -l [-d] [-u] [address_family]\n"
136 	"       ifconfig %s[-d] [-m] [-u] [-v]\n",
137 		options, options, options);
138 	exit(1);
139 }
140 
141 int
142 main(int argc, char *argv[])
143 {
144 	int c, all, namesonly, downonly, uponly;
145 	const struct afswtch *afp = NULL;
146 	int ifindex;
147 	struct ifaddrs *ifap, *ifa;
148 	struct ifreq paifr;
149 	const struct sockaddr_dl *sdl;
150 	char options[1024], *cp;
151 	const char *ifname;
152 	struct option *p;
153 	size_t iflen;
154 
155 	all = downonly = uponly = namesonly = noload = verbose = 0;
156 
157 	/* Parse leading line options */
158 	strlcpy(options, "adklmnuv", sizeof(options));
159 	for (p = opts; p != NULL; p = p->next)
160 		strlcat(options, p->opt, sizeof(options));
161 	while ((c = getopt(argc, argv, options)) != -1) {
162 		switch (c) {
163 		case 'a':	/* scan all interfaces */
164 			all++;
165 			break;
166 		case 'd':	/* restrict scan to "down" interfaces */
167 			downonly++;
168 			break;
169 		case 'k':
170 			printkeys++;
171 			break;
172 		case 'l':	/* scan interface names only */
173 			namesonly++;
174 			break;
175 		case 'm':	/* show media choices in status */
176 			supmedia = 1;
177 			break;
178 		case 'n':	/* suppress module loading */
179 			noload++;
180 			break;
181 		case 'u':	/* restrict scan to "up" interfaces */
182 			uponly++;
183 			break;
184 		case 'v':
185 			verbose++;
186 			break;
187 		default:
188 			for (p = opts; p != NULL; p = p->next)
189 				if (p->opt[0] == c) {
190 					p->cb(optarg);
191 					break;
192 				}
193 			if (p == NULL)
194 				usage();
195 			break;
196 		}
197 	}
198 	argc -= optind;
199 	argv += optind;
200 
201 	/* -l cannot be used with -a or -m */
202 	if (namesonly && (all || supmedia))
203 		usage();
204 
205 	/* nonsense.. */
206 	if (uponly && downonly)
207 		usage();
208 
209 	/* no arguments is equivalent to '-a' */
210 	if (!namesonly && argc < 1)
211 		all = 1;
212 
213 	/* -a and -l allow an address family arg to limit the output */
214 	if (all || namesonly) {
215 		if (argc > 1)
216 			usage();
217 
218 		ifname = NULL;
219 		ifindex = 0;
220 		if (argc == 1) {
221 			afp = af_getbyname(*argv);
222 			if (afp == NULL)
223 				usage();
224 			if (afp->af_name != NULL)
225 				argc--, argv++;
226 			/* leave with afp non-zero */
227 		}
228 	} else {
229 		/* not listing, need an argument */
230 		if (argc < 1)
231 			usage();
232 
233 		ifname = *argv;
234 		argc--, argv++;
235 
236 		/* check and maybe load support for this interface */
237 		ifmaybeload(ifname);
238 
239 		ifindex = if_nametoindex(ifname);
240 		if (ifindex == 0) {
241 			/*
242 			 * NOTE:  We must special-case the `create' command
243 			 * right here as we would otherwise fail when trying
244 			 * to find the interface.
245 			 */
246 			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
247 			    strcmp(argv[0], "plumb") == 0)) {
248 				iflen = strlcpy(name, ifname, sizeof(name));
249 				if (iflen >= sizeof(name))
250 					errx(1, "%s: cloning name too long",
251 					    ifname);
252 				ifconfig(argc, argv, 1, NULL);
253 				exit(0);
254 			}
255 			errx(1, "interface %s does not exist", ifname);
256 		}
257 	}
258 
259 	/* Check for address family */
260 	if (argc > 0) {
261 		afp = af_getbyname(*argv);
262 		if (afp != NULL)
263 			argc--, argv++;
264 	}
265 
266 	if (getifaddrs(&ifap) != 0)
267 		err(EXIT_FAILURE, "getifaddrs");
268 	cp = NULL;
269 	ifindex = 0;
270 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
271 		memset(&paifr, 0, sizeof(paifr));
272 		strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
273 		if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
274 			memcpy(&paifr.ifr_addr, ifa->ifa_addr,
275 			    ifa->ifa_addr->sa_len);
276 		}
277 
278 		if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
279 			continue;
280 		if (ifa->ifa_addr->sa_family == AF_LINK)
281 			sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
282 		else
283 			sdl = NULL;
284 		if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0)
285 			continue;
286 		iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
287 		if (iflen >= sizeof(name)) {
288 			warnx("%s: interface name too long, skipping",
289 			    ifa->ifa_name);
290 			continue;
291 		}
292 		cp = ifa->ifa_name;
293 
294 		if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
295 			continue;
296 		if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
297 			continue;
298 		ifindex++;
299 		/*
300 		 * Are we just listing the interfaces?
301 		 */
302 		if (namesonly) {
303 			if (ifindex > 1)
304 				printf(" ");
305 			fputs(name, stdout);
306 			continue;
307 		}
308 
309 		if (argc > 0)
310 			ifconfig(argc, argv, 0, afp);
311 		else
312 			status(afp, sdl, ifa);
313 	}
314 	if (namesonly)
315 		printf("\n");
316 	freeifaddrs(ifap);
317 
318 	exit(0);
319 }
320 
321 static struct afswtch *afs = NULL;
322 
323 void
324 af_register(struct afswtch *p)
325 {
326 	p->af_next = afs;
327 	afs = p;
328 }
329 
330 static struct afswtch *
331 af_getbyname(const char *name)
332 {
333 	struct afswtch *afp;
334 
335 	for (afp = afs; afp !=  NULL; afp = afp->af_next)
336 		if (strcmp(afp->af_name, name) == 0)
337 			return afp;
338 	return NULL;
339 }
340 
341 static struct afswtch *
342 af_getbyfamily(int af)
343 {
344 	struct afswtch *afp;
345 
346 	for (afp = afs; afp != NULL; afp = afp->af_next)
347 		if (afp->af_af == af)
348 			return afp;
349 	return NULL;
350 }
351 
352 static void
353 af_other_status(int s)
354 {
355 	struct afswtch *afp;
356 	uint8_t afmask[howmany(AF_MAX, NBBY)];
357 
358 	memset(afmask, 0, sizeof(afmask));
359 	for (afp = afs; afp != NULL; afp = afp->af_next) {
360 		if (afp->af_other_status == NULL)
361 			continue;
362 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
363 			continue;
364 		afp->af_other_status(s);
365 		setbit(afmask, afp->af_af);
366 	}
367 }
368 
369 static void
370 af_all_tunnel_status(int s)
371 {
372 	struct afswtch *afp;
373 	uint8_t afmask[howmany(AF_MAX, NBBY)];
374 
375 	memset(afmask, 0, sizeof(afmask));
376 	for (afp = afs; afp != NULL; afp = afp->af_next) {
377 		if (afp->af_status_tunnel == NULL)
378 			continue;
379 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
380 			continue;
381 		afp->af_status_tunnel(s);
382 		setbit(afmask, afp->af_af);
383 	}
384 }
385 
386 static struct cmd *cmds = NULL;
387 
388 void
389 cmd_register(struct cmd *p)
390 {
391 	p->c_next = cmds;
392 	cmds = p;
393 }
394 
395 static const struct cmd *
396 cmd_lookup(const char *name)
397 {
398 #define	N(a)	(sizeof(a)/sizeof(a[0]))
399 	const struct cmd *p;
400 
401 	for (p = cmds; p != NULL; p = p->c_next)
402 		if (strcmp(name, p->c_name) == 0)
403 			return p;
404 	return NULL;
405 #undef N
406 }
407 
408 struct callback {
409 	callback_func *cb_func;
410 	void	*cb_arg;
411 	struct callback *cb_next;
412 };
413 static struct callback *callbacks = NULL;
414 
415 void
416 callback_register(callback_func *func, void *arg)
417 {
418 	struct callback *cb;
419 
420 	cb = malloc(sizeof(struct callback));
421 	if (cb == NULL)
422 		errx(1, "unable to allocate memory for callback");
423 	cb->cb_func = func;
424 	cb->cb_arg = arg;
425 	cb->cb_next = callbacks;
426 	callbacks = cb;
427 }
428 
429 /* specially-handled commands */
430 static void setifaddr(const char *, int, int, const struct afswtch *);
431 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
432 
433 static void setifdstaddr(const char *, int, int, const struct afswtch *);
434 static const struct cmd setifdstaddr_cmd =
435 	DEF_CMD("ifdstaddr", 0, setifdstaddr);
436 
437 static int
438 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp)
439 {
440 	const struct afswtch *nafp;
441 	struct callback *cb;
442 	int s;
443 
444 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
445 top:
446 	if (afp == NULL)
447 		afp = af_getbyname("inet");
448 	ifr.ifr_addr.sa_family =
449 		afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
450 		AF_INET : afp->af_af;
451 
452 	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
453 		err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family);
454 
455 	while (argc > 0) {
456 		const struct cmd *p;
457 
458 		p = cmd_lookup(*argv);
459 		if (p == NULL) {
460 			/*
461 			 * Not a recognized command, choose between setting
462 			 * the interface address and the dst address.
463 			 */
464 			p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
465 		}
466 		if (p->c_u.c_func || p->c_u.c_func2) {
467 			if (iscreate && !p->c_iscloneop) {
468 				/*
469 				 * Push the clone create callback so the new
470 				 * device is created and can be used for any
471 				 * remaining arguments.
472 				 */
473 				cb = callbacks;
474 				if (cb == NULL)
475 					errx(1, "internal error, no callback");
476 				callbacks = cb->cb_next;
477 				cb->cb_func(s, cb->cb_arg);
478 				iscreate = 0;
479 				/*
480 				 * Handle any address family spec that
481 				 * immediately follows and potentially
482 				 * recreate the socket.
483 				 */
484 				nafp = af_getbyname(*argv);
485 				if (nafp != NULL) {
486 					argc--, argv++;
487 					if (nafp != afp) {
488 						close(s);
489 						afp = nafp;
490 						goto top;
491 					}
492 				}
493 			}
494 			if (p->c_parameter == NEXTARG) {
495 				if (argv[1] == NULL)
496 					errx(1, "'%s' requires argument",
497 					    p->c_name);
498 				p->c_u.c_func(argv[1], 0, s, afp);
499 				argc--, argv++;
500 			} else if (p->c_parameter == OPTARG) {
501 				p->c_u.c_func(argv[1], 0, s, afp);
502 				if (argv[1] != NULL)
503 					argc--, argv++;
504 			} else if (p->c_parameter == NEXTARG2) {
505 				if (argc < 3)
506 					errx(1, "'%s' requires 2 arguments",
507 					    p->c_name);
508 				p->c_u.c_func2(argv[1], argv[2], s, afp);
509 				argc -= 2, argv += 2;
510 			} else
511 				p->c_u.c_func(*argv, p->c_parameter, s, afp);
512 		}
513 		argc--, argv++;
514 	}
515 
516 	/*
517 	 * Do any post argument processing required by the address family.
518 	 */
519 	if (afp->af_postproc != NULL)
520 		afp->af_postproc(s, afp);
521 	/*
522 	 * Do deferred callbacks registered while processing
523 	 * command-line arguments.
524 	 */
525 	for (cb = callbacks; cb != NULL; cb = cb->cb_next)
526 		cb->cb_func(s, cb->cb_arg);
527 	/*
528 	 * Do deferred operations.
529 	 */
530 	if (clearaddr) {
531 		if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
532 			warnx("interface %s cannot change %s addresses!",
533 			      name, afp->af_name);
534 			clearaddr = 0;
535 		}
536 	}
537 	if (clearaddr) {
538 		int ret;
539 		strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
540 		ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
541 		if (ret < 0) {
542 			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
543 				/* means no previous address for interface */
544 			} else
545 				Perror("ioctl (SIOCDIFADDR)");
546 		}
547 	}
548 	if (newaddr) {
549 		if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
550 			warnx("interface %s cannot change %s addresses!",
551 			      name, afp->af_name);
552 			newaddr = 0;
553 		}
554 	}
555 	if (newaddr && (setaddr || setmask)) {
556 		strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
557 		if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
558 			Perror("ioctl (SIOCAIFADDR)");
559 	}
560 
561 	close(s);
562 	return(0);
563 }
564 
565 /*ARGSUSED*/
566 static void
567 setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
568 {
569 	if (afp->af_getaddr == NULL)
570 		return;
571 	/*
572 	 * Delay the ioctl to set the interface addr until flags are all set.
573 	 * The address interpretation may depend on the flags,
574 	 * and the flags may change when the address is set.
575 	 */
576 	setaddr++;
577 	if (doalias == 0 && afp->af_af != AF_LINK)
578 		clearaddr = 1;
579 	afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
580 }
581 
582 static void
583 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
584 {
585 	struct addrinfo *srcres, *dstres;
586 	int ecode;
587 
588 	if (afp->af_settunnel == NULL) {
589 		warn("address family %s does not support tunnel setup",
590 			afp->af_name);
591 		return;
592 	}
593 
594 	if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
595 		errx(1, "error in parsing address string: %s",
596 		    gai_strerror(ecode));
597 
598 	if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
599 		errx(1, "error in parsing address string: %s",
600 		    gai_strerror(ecode));
601 
602 	if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
603 		errx(1,
604 		    "source and destination address families do not match");
605 
606 	afp->af_settunnel(s, srcres, dstres);
607 
608 	freeaddrinfo(srcres);
609 	freeaddrinfo(dstres);
610 }
611 
612 /* ARGSUSED */
613 static void
614 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
615 {
616 
617 	if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
618 		err(1, "SIOCDIFPHYADDR");
619 }
620 
621 static void
622 setifnetmask(const char *addr, int dummy __unused, int s,
623     const struct afswtch *afp)
624 {
625 	if (afp->af_getaddr != NULL) {
626 		setmask++;
627 		afp->af_getaddr(addr, MASK);
628 	}
629 }
630 
631 static void
632 setifbroadaddr(const char *addr, int dummy __unused, int s,
633     const struct afswtch *afp)
634 {
635 	if (afp->af_getaddr != NULL)
636 		afp->af_getaddr(addr, DSTADDR);
637 }
638 
639 static void
640 setifipdst(const char *addr, int dummy __unused, int s,
641     const struct afswtch *afp)
642 {
643 	const struct afswtch *inet;
644 
645 	inet = af_getbyname("inet");
646 	if (inet == NULL)
647 		return;
648 	inet->af_getaddr(addr, DSTADDR);
649 	clearaddr = 0;
650 	newaddr = 0;
651 }
652 
653 static void
654 notealias(const char *addr, int param, int s, const struct afswtch *afp)
655 {
656 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
657 	if (setaddr && doalias == 0 && param < 0)
658 		if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
659 			bcopy((caddr_t)rqtosa(af_addreq),
660 			      (caddr_t)rqtosa(af_ridreq),
661 			      rqtosa(af_addreq)->sa_len);
662 	doalias = param;
663 	if (param < 0) {
664 		clearaddr = 1;
665 		newaddr = 0;
666 	} else
667 		clearaddr = 0;
668 #undef rqtosa
669 }
670 
671 /*ARGSUSED*/
672 static void
673 setifdstaddr(const char *addr, int param __unused, int s,
674     const struct afswtch *afp)
675 {
676 	if (afp->af_getaddr != NULL)
677 		afp->af_getaddr(addr, DSTADDR);
678 }
679 
680 /*
681  * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
682  * of the ifreq structure, which may confuse other parts of ifconfig.
683  * Make a private copy so we can avoid that.
684  */
685 static void
686 setifflags(const char *vname, int value, int s, const struct afswtch *afp)
687 {
688 	struct ifreq		my_ifr;
689 	int flags;
690 
691 	bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
692 
693  	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
694  		Perror("ioctl (SIOCGIFFLAGS)");
695  		exit(1);
696  	}
697 	strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name));
698 	flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16);
699 
700 	if (value < 0) {
701 		value = -value;
702 		flags &= ~value;
703 	} else
704 		flags |= value;
705 	my_ifr.ifr_flags = flags & 0xffff;
706 	my_ifr.ifr_flagshigh = flags >> 16;
707 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
708 		Perror(vname);
709 }
710 
711 void
712 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
713 {
714 	int flags;
715 
716  	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
717  		Perror("ioctl (SIOCGIFCAP)");
718  		exit(1);
719  	}
720 	flags = ifr.ifr_curcap;
721 	if (value < 0) {
722 		value = -value;
723 		flags &= ~value;
724 	} else
725 		flags |= value;
726 	flags &= ifr.ifr_reqcap;
727 	ifr.ifr_reqcap = flags;
728 	if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
729 		Perror(vname);
730 }
731 
732 static void
733 setifmetric(const char *val, int dummy __unused, int s,
734     const struct afswtch *afp)
735 {
736 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
737 	ifr.ifr_metric = atoi(val);
738 	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
739 		warn("ioctl (set metric)");
740 }
741 
742 static void
743 setifmtu(const char *val, int dummy __unused, int s,
744     const struct afswtch *afp)
745 {
746 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
747 	ifr.ifr_mtu = atoi(val);
748 	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
749 		warn("ioctl (set mtu)");
750 }
751 
752 static void
753 setifgrekey(const char *val, int dummy __unused, int s,
754     const struct afswtch *afp)
755 {
756 	uint32_t grekey = atol(val);
757 
758 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
759 	ifr.ifr_data = (caddr_t)&grekey;
760 	if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0)
761 		warn("ioctl (set grekey)");
762 }
763 
764 static void
765 setifname(const char *val, int dummy __unused, int s,
766     const struct afswtch *afp)
767 {
768 	char *newname;
769 
770 	newname = strdup(val);
771 	if (newname == NULL) {
772 		warn("no memory to set ifname");
773 		return;
774 	}
775 	ifr.ifr_data = newname;
776 	if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
777 		warn("ioctl (set name)");
778 		free(newname);
779 		return;
780 	}
781 	strlcpy(name, newname, sizeof(name));
782 	free(newname);
783 }
784 
785 #define	IFFBITS \
786 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
787 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
788 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT"
789 
790 #define	IFCAPBITS \
791 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
792 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC"
793 
794 /*
795  * Print the status of the interface.  If an address family was
796  * specified, show only it; otherwise, show them all.
797  */
798 static void
799 status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
800 	struct ifaddrs *ifa)
801 {
802 	struct ifaddrs *ift;
803 	int allfamilies, s;
804 	struct ifstat ifs;
805 
806 	if (afp == NULL) {
807 		allfamilies = 1;
808 		afp = af_getbyname("inet");
809 	} else
810 		allfamilies = 0;
811 
812 	ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
813 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
814 
815 	s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
816 	if (s < 0)
817 		err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
818 
819 	printf("%s: ", name);
820 	printb("flags", ifa->ifa_flags, IFFBITS);
821 	if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
822 		printf(" metric %d", ifr.ifr_metric);
823 	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
824 		printf(" mtu %d", ifr.ifr_mtu);
825 	putchar('\n');
826 
827 	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
828 		if (ifr.ifr_curcap != 0) {
829 			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
830 			putchar('\n');
831 		}
832 		if (supmedia && ifr.ifr_reqcap != 0) {
833 			printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
834 			putchar('\n');
835 		}
836 	}
837 
838 	tunnel_status(s);
839 
840 	for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
841 		if (ift->ifa_addr == NULL)
842 			continue;
843 		if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
844 			continue;
845 		if (allfamilies) {
846 			const struct afswtch *p;
847 			p = af_getbyfamily(ift->ifa_addr->sa_family);
848 			if (p != NULL && p->af_status != NULL)
849 				p->af_status(s, ift);
850 		} else if (afp->af_af == ift->ifa_addr->sa_family)
851 			afp->af_status(s, ift);
852 	}
853 #if 0
854 	if (allfamilies || afp->af_af == AF_LINK) {
855 		const struct afswtch *lafp;
856 
857 		/*
858 		 * Hack; the link level address is received separately
859 		 * from the routing information so any address is not
860 		 * handled above.  Cobble together an entry and invoke
861 		 * the status method specially.
862 		 */
863 		lafp = af_getbyname("lladdr");
864 		if (lafp != NULL) {
865 			info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
866 			lafp->af_status(s, &info);
867 		}
868 	}
869 #endif
870 	if (allfamilies)
871 		af_other_status(s);
872 	else if (afp->af_other_status != NULL)
873 		afp->af_other_status(s);
874 
875 	strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
876 	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
877 		printf("%s", ifs.ascii);
878 
879 	int grekey = 0;
880 	ifr.ifr_data = (caddr_t)&grekey;
881 	if (ioctl(s, GREGKEY, &ifr) == 0)
882 		if (grekey != 0)
883 			printf("\tgrekey: %d\n", grekey);
884 
885 	close(s);
886 	return;
887 }
888 
889 static void
890 tunnel_status(int s)
891 {
892 	af_all_tunnel_status(s);
893 }
894 
895 void
896 Perror(const char *cmd)
897 {
898 	switch (errno) {
899 
900 	case ENXIO:
901 		errx(1, "%s: no such interface", cmd);
902 		break;
903 
904 	case EPERM:
905 		errx(1, "%s: permission denied", cmd);
906 		break;
907 
908 	default:
909 		err(1, "%s", cmd);
910 	}
911 }
912 
913 /*
914  * Print a value a la the %b format of the kernel's printf
915  */
916 void
917 printb(const char *s, unsigned v, const char *bits)
918 {
919 	int i, any = 0;
920 	char c;
921 
922 	if (bits && *bits == 8)
923 		printf("%s=%o", s, v);
924 	else
925 		printf("%s=%x", s, v);
926 	bits++;
927 	if (bits) {
928 		putchar('<');
929 		while ((i = *bits++) != '\0') {
930 			if (v & (1 << (i-1))) {
931 				if (any)
932 					putchar(',');
933 				any = 1;
934 				for (; (c = *bits) > 32; bits++)
935 					putchar(c);
936 			} else
937 				for (; *bits > 32; bits++)
938 					;
939 		}
940 		putchar('>');
941 	}
942 }
943 
944 void
945 ifmaybeload(const char *name)
946 {
947 #define MOD_PREFIX_LEN		3	/* "if_" */
948 	struct module_stat mstat;
949 	int fileid, modid;
950 	char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
951 	const char *cp;
952 
953 	/* loading suppressed by the user */
954 	if (noload)
955 		return;
956 
957 	/* trim the interface number off the end */
958 	strlcpy(ifname, name, sizeof(ifname));
959 	for (dp = ifname; *dp != 0; dp++)
960 		if (isdigit(*dp)) {
961 			*dp = 0;
962 			break;
963 		}
964 
965 	/* turn interface and unit into module name */
966 	strcpy(ifkind, "if_");
967 	strlcpy(ifkind + MOD_PREFIX_LEN, ifname,
968 	    sizeof(ifkind) - MOD_PREFIX_LEN);
969 
970 	/* scan files in kernel */
971 	mstat.version = sizeof(struct module_stat);
972 	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
973 		/* scan modules in file */
974 		for (modid = kldfirstmod(fileid); modid > 0;
975 		     modid = modfnext(modid)) {
976 			if (modstat(modid, &mstat) < 0)
977 				continue;
978 			/* strip bus name if present */
979 			if ((cp = strchr(mstat.name, '/')) != NULL) {
980 				cp++;
981 			} else {
982 				cp = mstat.name;
983 			}
984 			/* already loaded? */
985 			if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 ||
986 			    strncmp(ifkind, cp, strlen(ifkind) + 1) == 0)
987 				return;
988 		}
989 	}
990 
991 	/* not present, we should try to load it */
992 	kldload(ifkind);
993 }
994 
995 static struct cmd basic_cmds[] = {
996 	DEF_CMD("up",		IFF_UP,		setifflags),
997 	DEF_CMD("down",		-IFF_UP,	setifflags),
998 	DEF_CMD("arp",		-IFF_NOARP,	setifflags),
999 	DEF_CMD("-arp",		IFF_NOARP,	setifflags),
1000 	DEF_CMD("debug",	IFF_DEBUG,	setifflags),
1001 	DEF_CMD("-debug",	-IFF_DEBUG,	setifflags),
1002 	DEF_CMD("promisc",	IFF_PPROMISC,	setifflags),
1003 	DEF_CMD("-promisc",	-IFF_PPROMISC,	setifflags),
1004 	DEF_CMD("add",		IFF_UP,		notealias),
1005 	DEF_CMD("alias",	IFF_UP,		notealias),
1006 	DEF_CMD("-alias",	-IFF_UP,	notealias),
1007 	DEF_CMD("delete",	-IFF_UP,	notealias),
1008 	DEF_CMD("remove",	-IFF_UP,	notealias),
1009 #ifdef notdef
1010 #define	EN_SWABIPS	0x1000
1011 	DEF_CMD("swabips",	EN_SWABIPS,	setifflags),
1012 	DEF_CMD("-swabips",	-EN_SWABIPS,	setifflags),
1013 #endif
1014 	DEF_CMD_ARG("netmask",			setifnetmask),
1015 	DEF_CMD_ARG("metric",			setifmetric),
1016 	DEF_CMD_ARG("broadcast",		setifbroadaddr),
1017 	DEF_CMD_ARG("ipdst",			setifipdst),
1018 	DEF_CMD_ARG2("tunnel",			settunnel),
1019 	DEF_CMD("-tunnel", 0,			deletetunnel),
1020 	DEF_CMD("deletetunnel", 0,		deletetunnel),
1021 	DEF_CMD("link0",	IFF_LINK0,	setifflags),
1022 	DEF_CMD("-link0",	-IFF_LINK0,	setifflags),
1023 	DEF_CMD("link1",	IFF_LINK1,	setifflags),
1024 	DEF_CMD("-link1",	-IFF_LINK1,	setifflags),
1025 	DEF_CMD("link2",	IFF_LINK2,	setifflags),
1026 	DEF_CMD("-link2",	-IFF_LINK2,	setifflags),
1027 	DEF_CMD("monitor",	IFF_MONITOR,	setifflags),
1028 	DEF_CMD("-monitor",	-IFF_MONITOR,	setifflags),
1029 	DEF_CMD("staticarp",	IFF_STATICARP,	setifflags),
1030 	DEF_CMD("-staticarp",	-IFF_STATICARP,	setifflags),
1031 	DEF_CMD("rxcsum",	IFCAP_RXCSUM,	setifcap),
1032 	DEF_CMD("-rxcsum",	-IFCAP_RXCSUM,	setifcap),
1033 	DEF_CMD("txcsum",	IFCAP_TXCSUM,	setifcap),
1034 	DEF_CMD("-txcsum",	-IFCAP_TXCSUM,	setifcap),
1035 	DEF_CMD("netcons",	IFCAP_NETCONS,	setifcap),
1036 	DEF_CMD("-netcons",	-IFCAP_NETCONS,	setifcap),
1037 	DEF_CMD("polling",	IFCAP_POLLING,	setifcap),
1038 	DEF_CMD("-polling",	-IFCAP_POLLING,	setifcap),
1039 	DEF_CMD("tso",		IFCAP_TSO,	setifcap),
1040 	DEF_CMD("-tso",		-IFCAP_TSO,	setifcap),
1041 	DEF_CMD("lro",		IFCAP_LRO,	setifcap),
1042 	DEF_CMD("-lro",		-IFCAP_LRO,	setifcap),
1043 	DEF_CMD("wol",		IFCAP_WOL,	setifcap),
1044 	DEF_CMD("-wol",		-IFCAP_WOL,	setifcap),
1045 	DEF_CMD("wol_ucast",	IFCAP_WOL_UCAST,	setifcap),
1046 	DEF_CMD("-wol_ucast",	-IFCAP_WOL_UCAST,	setifcap),
1047 	DEF_CMD("wol_mcast",	IFCAP_WOL_MCAST,	setifcap),
1048 	DEF_CMD("-wol_mcast",	-IFCAP_WOL_MCAST,	setifcap),
1049 	DEF_CMD("wol_magic",	IFCAP_WOL_MAGIC,	setifcap),
1050 	DEF_CMD("-wol_magic",	-IFCAP_WOL_MAGIC,	setifcap),
1051 	DEF_CMD("normal",	-IFF_LINK0,	setifflags),
1052 	DEF_CMD("compress",	IFF_LINK0,	setifflags),
1053 	DEF_CMD("noicmp",	IFF_LINK1,	setifflags),
1054 	DEF_CMD_ARG("mtu",			setifmtu),
1055 	DEF_CMD_ARG("name",			setifname),
1056 	DEF_CMD_ARG("grekey",			setifgrekey),
1057 };
1058 
1059 static __constructor void
1060 ifconfig_ctor(void)
1061 {
1062 #define	N(a)	(sizeof(a) / sizeof(a[0]))
1063 	int i;
1064 
1065 	for (i = 0; i < N(basic_cmds);  i++)
1066 		cmd_register(&basic_cmds[i]);
1067 #undef N
1068 }
1069