ifconfig.c revision 92806
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. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1983, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
43#endif
44static const char rcsid[] =
45  "$FreeBSD: head/sbin/ifconfig/ifconfig.c 92806 2002-03-20 17:55:10Z obrien $";
46#endif /* not lint */
47
48#include <sys/param.h>
49#include <sys/ioctl.h>
50#include <sys/socket.h>
51#include <sys/sysctl.h>
52#include <sys/time.h>
53#include <sys/module.h>
54#include <sys/linker.h>
55
56#include <net/ethernet.h>
57#include <net/if.h>
58#include <net/if_var.h>
59#include <net/if_dl.h>
60#include <net/if_types.h>
61#include <net/route.h>
62
63/* IP */
64#include <netinet/in.h>
65#include <netinet/in_var.h>
66#include <arpa/inet.h>
67#include <netdb.h>
68
69#ifdef INET6
70#include <netinet6/nd6.h>	/* Define ND6_INFINITE_LIFETIME */
71#endif
72
73#ifndef NO_IPX
74/* IPX */
75#define	IPXIP
76#define IPTUNNEL
77#include <netipx/ipx.h>
78#include <netipx/ipx_if.h>
79#endif
80
81/* Appletalk */
82#include <netatalk/at.h>
83
84/* XNS */
85#ifdef NS
86#define	NSIP
87#include <netns/ns.h>
88#include <netns/ns_if.h>
89#endif
90
91/* OSI */
92
93#include <ctype.h>
94#include <err.h>
95#include <errno.h>
96#include <fcntl.h>
97#include <stdio.h>
98#include <stdlib.h>
99#include <string.h>
100#include <unistd.h>
101
102#include "ifconfig.h"
103
104/* wrapper for KAME-special getnameinfo() */
105#ifndef NI_WITHSCOPEID
106#define	NI_WITHSCOPEID	0
107#endif
108
109struct	ifreq		ifr, ridreq;
110struct	ifaliasreq	addreq;
111#ifdef INET6
112struct	in6_ifreq	in6_ridreq;
113struct	in6_aliasreq	in6_addreq =
114  { { 0 },
115    { 0 },
116    { 0 },
117    { 0 },
118    0,
119    { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } };
120#endif
121struct	sockaddr_in	netmask;
122struct	netrange	at_nr;		/* AppleTalk net range */
123
124char	name[32];
125int	flags;
126int	setaddr;
127int	setipdst;
128int	setmask;
129int	doalias;
130int	clearaddr;
131int	newaddr = 1;
132#ifdef INET6
133static	int ip6lifetime;
134#endif
135
136struct	afswtch;
137
138int supmedia = 0;
139int listcloners = 0;
140
141#ifdef INET6
142char	addr_buf[MAXHOSTNAMELEN *2 + 1];	/*for getnameinfo()*/
143#endif
144
145void	Perror __P((const char *cmd));
146void	checkatrange __P((struct sockaddr_at *));
147int	ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
148void	notealias __P((const char *, int, int, const struct afswtch *afp));
149void	list_cloners __P((void));
150void	printb __P((const char *s, unsigned value, const char *bits));
151void	rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
152void	status __P((const struct afswtch *afp, int addrcount,
153		    struct sockaddr_dl *sdl, struct if_msghdr *ifm,
154		    struct ifa_msghdr *ifam));
155void	tunnel_status __P((int s));
156void	usage __P((void));
157void	ifmaybeload __P((char *name));
158
159#ifdef INET6
160void	in6_fillscopeid __P((struct sockaddr_in6 *sin6));
161int	prefix __P((void *, int));
162static	char *sec2str __P((time_t));
163int	explicit_prefix = 0;
164#endif
165
166typedef	void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp));
167typedef	void c_func2 __P((const char *arg, const char *arg2, int s, const struct afswtch *afp));
168c_func	setatphase, setatrange;
169c_func	setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
170c_func2	settunnel;
171c_func	deletetunnel;
172#ifdef INET6
173c_func	setifprefixlen;
174c_func	setip6flags;
175c_func  setip6pltime;
176c_func  setip6vltime;
177c_func2	setip6lifetime;
178#endif
179c_func	setifipdst;
180c_func	setifflags, setifmetric, setifmtu, setiflladdr, setifcap;
181c_func	clone_destroy;
182
183
184void clone_create __P((void));
185
186
187#define	NEXTARG		0xffffff
188#define	NEXTARG2	0xfffffe
189
190const
191struct	cmd {
192	const	char *c_name;
193	int	c_parameter;		/* NEXTARG means next argv */
194	void	(*c_func) __P((const char *, int, int, const struct afswtch *afp));
195	void	(*c_func2) __P((const char *, const char *, int, const struct afswtch *afp));
196} cmds[] = {
197	{ "up",		IFF_UP,		setifflags } ,
198	{ "down",	-IFF_UP,	setifflags },
199	{ "arp",	-IFF_NOARP,	setifflags },
200	{ "-arp",	IFF_NOARP,	setifflags },
201	{ "debug",	IFF_DEBUG,	setifflags },
202	{ "-debug",	-IFF_DEBUG,	setifflags },
203	{ "add",	IFF_UP,		notealias },
204	{ "alias",	IFF_UP,		notealias },
205	{ "-alias",	-IFF_UP,	notealias },
206	{ "delete",	-IFF_UP,	notealias },
207	{ "remove",	-IFF_UP,	notealias },
208#ifdef notdef
209#define	EN_SWABIPS	0x1000
210	{ "swabips",	EN_SWABIPS,	setifflags },
211	{ "-swabips",	-EN_SWABIPS,	setifflags },
212#endif
213	{ "netmask",	NEXTARG,	setifnetmask },
214#ifdef INET6
215	{ "prefixlen",	NEXTARG,	setifprefixlen },
216	{ "anycast",	IN6_IFF_ANYCAST, setip6flags },
217	{ "tentative",	IN6_IFF_TENTATIVE, setip6flags },
218	{ "-tentative",	-IN6_IFF_TENTATIVE, setip6flags },
219	{ "deprecated",	IN6_IFF_DEPRECATED, setip6flags },
220	{ "-deprecated", -IN6_IFF_DEPRECATED, setip6flags },
221	{ "autoconf",	IN6_IFF_AUTOCONF, setip6flags },
222	{ "-autoconf",	-IN6_IFF_AUTOCONF, setip6flags },
223	{ "pltime",     NEXTARG,        setip6pltime },
224	{ "vltime",     NEXTARG,        setip6vltime },
225#endif
226	{ "range",	NEXTARG,	setatrange },
227	{ "phase",	NEXTARG,	setatphase },
228	{ "metric",	NEXTARG,	setifmetric },
229	{ "broadcast",	NEXTARG,	setifbroadaddr },
230	{ "ipdst",	NEXTARG,	setifipdst },
231	{ "tunnel",	NEXTARG2,	NULL,	settunnel },
232	{ "deletetunnel", 0,		deletetunnel },
233	{ "link0",	IFF_LINK0,	setifflags },
234	{ "-link0",	-IFF_LINK0,	setifflags },
235	{ "link1",	IFF_LINK1,	setifflags },
236	{ "-link1",	-IFF_LINK1,	setifflags },
237	{ "link2",	IFF_LINK2,	setifflags },
238	{ "-link2",	-IFF_LINK2,	setifflags },
239#ifdef USE_IF_MEDIA
240	{ "media",	NEXTARG,	setmedia },
241	{ "mediaopt",	NEXTARG,	setmediaopt },
242	{ "-mediaopt",	NEXTARG,	unsetmediaopt },
243#endif
244#ifdef USE_VLANS
245	{ "vlan",	NEXTARG,	setvlantag },
246	{ "vlandev",	NEXTARG,	setvlandev },
247	{ "-vlandev",	NEXTARG,	unsetvlandev },
248#endif
249#if 0
250	/* XXX `create' special-cased below */
251	{"create",	0,		clone_create },
252	{"plumb",	0,		clone_create },
253#endif
254	{"destroy",	0,		clone_destroy },
255	{"unplumb",	0,		clone_destroy },
256#ifdef USE_IEEE80211
257	{ "ssid",	NEXTARG,	set80211ssid },
258	{ "nwid",	NEXTARG,	set80211ssid },
259	{ "stationname", NEXTARG,	set80211stationname },
260	{ "station",	NEXTARG,	set80211stationname },	/* BSD/OS */
261	{ "channel",	NEXTARG,	set80211channel },
262	{ "authmode",	NEXTARG,	set80211authmode },
263	{ "powersavemode", NEXTARG,	set80211powersavemode },
264	{ "powersave",	1,		set80211powersave },
265	{ "-powersave",	0,		set80211powersave },
266	{ "powersavesleep", NEXTARG,	set80211powersavesleep },
267	{ "wepmode",	NEXTARG,	set80211wepmode },
268	{ "wep",	1,		set80211wep },
269	{ "-wep",	0,		set80211wep },
270	{ "weptxkey",	NEXTARG,	set80211weptxkey },
271	{ "wepkey",	NEXTARG,	set80211wepkey },
272	{ "nwkey",	NEXTARG,	set80211nwkey },	/* NetBSD */
273	{ "-nwkey",	0,		set80211wep },		/* NetBSD */
274#endif
275	{ "rxcsum",	IFCAP_RXCSUM,	setifcap },
276	{ "-rxcsum",	-IFCAP_RXCSUM,	setifcap },
277	{ "txcsum",	IFCAP_TXCSUM,	setifcap },
278	{ "-txcsum",	-IFCAP_TXCSUM,	setifcap },
279	{ "netcons",	IFCAP_NETCONS,	setifcap },
280	{ "-netcons",	-IFCAP_NETCONS,	setifcap },
281	{ "normal",	-IFF_LINK0,	setifflags },
282	{ "compress",	IFF_LINK0,	setifflags },
283	{ "noicmp",	IFF_LINK1,	setifflags },
284	{ "mtu",	NEXTARG,	setifmtu },
285	{ "lladdr",	NEXTARG,	setiflladdr },
286	{ 0,		0,		setifaddr },
287	{ 0,		0,		setifdstaddr },
288};
289
290/*
291 * XNS support liberally adapted from code written at the University of
292 * Maryland principally by James O'Toole and Chris Torek.
293 */
294typedef	void af_status __P((int, struct rt_addrinfo *));
295typedef	void af_getaddr __P((const char *, int));
296typedef void af_getprefix __P((const char *, int));
297
298af_status	in_status, at_status, ether_status;
299af_getaddr	in_getaddr, at_getaddr, ether_getaddr;
300
301#ifndef NO_IPX
302af_status	ipx_status;
303af_getaddr	ipx_getaddr;
304#endif
305
306#ifdef INET6
307af_status	in6_status;
308af_getaddr	in6_getaddr;
309af_getprefix	in6_getprefix;
310#endif /*INET6*/
311#ifdef NS
312af_status	xns_status;
313af_getaddr	xns_getaddr;
314#endif
315
316/* Known address families */
317const
318struct	afswtch {
319	const char *af_name;
320	short af_af;
321	af_status *af_status;
322	af_getaddr *af_getaddr;
323	af_getprefix *af_getprefix;
324	u_long af_difaddr;
325	u_long af_aifaddr;
326	caddr_t af_ridreq;
327	caddr_t af_addreq;
328} afs[] = {
329#define C(x) ((caddr_t) &x)
330	{ "inet", AF_INET, in_status, in_getaddr, NULL,
331	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
332#ifdef INET6
333	{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
334	     SIOCDIFADDR_IN6, SIOCAIFADDR_IN6,
335	     C(in6_ridreq), C(in6_addreq) },
336#endif /*INET6*/
337#ifndef NO_IPX
338	{ "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL,
339	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
340#endif
341	{ "atalk", AF_APPLETALK, at_status, at_getaddr, NULL,
342	     SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
343#ifdef NS
344	{ "ns", AF_NS, xns_status, xns_getaddr, NULL,
345	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
346#endif
347	{ "ether", AF_LINK, ether_status, ether_getaddr, NULL,
348	     0, SIOCSIFLLADDR, NULL, C(ridreq) },
349#if 0	/* XXX conflicts with the media command */
350#ifdef USE_IF_MEDIA
351	{ "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */
352#endif
353#ifdef USE_VLANS
354	{ "vlan", AF_UNSPEC, vlan_status, NULL, NULL, },  /* XXX not real!! */
355#endif
356#ifdef USE_IEEE80211
357	{ "ieee80211", AF_UNSPEC, ieee80211_status, NULL, NULL, },  /* XXX not real!! */
358#endif
359#endif
360	{ 0,	0,	    0,		0 }
361};
362
363/*
364 * Expand the compacted form of addresses as returned via the
365 * configuration read via sysctl().
366 */
367
368#define ROUNDUP(a) \
369	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
370#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
371
372void
373rt_xaddrs(cp, cplim, rtinfo)
374	caddr_t cp, cplim;
375	struct rt_addrinfo *rtinfo;
376{
377	struct sockaddr *sa;
378	int i;
379
380	memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
381	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
382		if ((rtinfo->rti_addrs & (1 << i)) == 0)
383			continue;
384		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
385		ADVANCE(cp, sa);
386	}
387}
388
389
390void
391usage()
392{
393#ifndef INET6
394	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
395	"usage: ifconfig interface address_family [address [dest_address]]",
396	"                [parameters]",
397	"       ifconfig -C",
398	"       ifconfig interface create",
399	"       ifconfig -a [-d] [-m] [-u] [address_family]",
400	"       ifconfig -l [-d] [-u] [address_family]",
401	"       ifconfig [-d] [-m] [-u]");
402#else
403	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
404	"usage: ifconfig [-L] interface address_family [address [dest_address]]",
405	"                [parameters]",
406	"       ifconfig -C",
407	"       ifconfig interface create",
408	"       ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
409	"       ifconfig -l [-d] [-u] [address_family]",
410	"       ifconfig [-L] [-d] [-m] [-u]");
411#endif
412	exit(1);
413}
414
415int
416main(argc, argv)
417	int argc;
418	char *const *argv;
419{
420	int c;
421	int all, namesonly, downonly, uponly;
422	int need_nl = 0;
423	const struct afswtch *afp = 0;
424	int addrcount, ifindex;
425	struct	if_msghdr *ifm, *nextifm;
426	struct	ifa_msghdr *ifam;
427	struct	sockaddr_dl *sdl;
428	char	*buf, *lim, *next;
429	size_t needed;
430	int mib[6];
431
432	/* Parse leading line options */
433	all = downonly = uponly = namesonly = 0;
434	while ((c = getopt(argc, argv, "adlmuC"
435#ifdef INET6
436					"L"
437#endif
438			)) != -1) {
439		switch (c) {
440		case 'a':	/* scan all interfaces */
441			all++;
442			break;
443		case 'd':	/* restrict scan to "down" interfaces */
444			downonly++;
445			break;
446		case 'l':	/* scan interface names only */
447			namesonly++;
448			break;
449		case 'm':	/* show media choices in status */
450			supmedia = 1;
451			break;
452		case 'u':	/* restrict scan to "up" interfaces */
453			uponly++;
454			break;
455		case 'C':
456			listcloners = 1;
457			break;
458#ifdef INET6
459		case 'L':
460			ip6lifetime++;	/* print IPv6 address lifetime */
461			break;
462#endif
463		default:
464			usage();
465			break;
466		}
467	}
468	argc -= optind;
469	argv += optind;
470
471	if (listcloners) {
472		/* -C must be solitary */
473		if (all || supmedia || uponly || downonly || namesonly ||
474		    argc > 0)
475			usage();
476
477		list_cloners();
478		exit(0);
479	}
480
481	/* -l cannot be used with -a or -m */
482	if (namesonly && (all || supmedia))
483		usage();
484
485	/* nonsense.. */
486	if (uponly && downonly)
487		usage();
488
489	/* no arguments is equivalent to '-a' */
490	if (!namesonly && argc < 1)
491		all = 1;
492
493	/* -a and -l allow an address family arg to limit the output */
494	if (all || namesonly) {
495		if (argc > 1)
496			usage();
497
498		ifindex = 0;
499		if (argc == 1) {
500			for (afp = afs; afp->af_name; afp++)
501				if (strcmp(afp->af_name, *argv) == 0) {
502					argc--, argv++;
503					break;
504				}
505			if (afp->af_name == NULL)
506				usage();
507			/* leave with afp non-zero */
508		}
509	} else {
510		/* not listing, need an argument */
511		if (argc < 1)
512			usage();
513
514		strncpy(name, *argv, sizeof(name));
515		argc--, argv++;
516
517		/* check and maybe load support for this interface */
518		ifmaybeload(name);
519
520		/*
521		 * NOTE:  We must special-case the `create' command right
522		 * here as we would otherwise fail when trying to find
523		 * the interface.
524		 */
525		if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
526		    strcmp(argv[0], "plumb") == 0)) {
527			clone_create();
528			argc--, argv++;
529			if (argc == 0)
530				exit(0);
531		}
532		ifindex = if_nametoindex(name);
533		if (ifindex == 0)
534			errx(1, "interface %s does not exist", name);
535	}
536
537	/* Check for address family */
538	if (argc > 0) {
539		for (afp = afs; afp->af_name; afp++)
540			if (strcmp(afp->af_name, *argv) == 0) {
541				argc--, argv++;
542				break;
543			}
544		if (afp->af_name == NULL)
545			afp = NULL;	/* not a family, NULL */
546	}
547
548	mib[0] = CTL_NET;
549	mib[1] = PF_ROUTE;
550	mib[2] = 0;
551	mib[3] = 0;			/* address family */
552	mib[4] = NET_RT_IFLIST;
553	mib[5] = ifindex;		/* interface index */
554
555	/* if particular family specified, only ask about it */
556	if (afp)
557		mib[3] = afp->af_af;
558
559	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
560		errx(1, "iflist-sysctl-estimate");
561	if ((buf = malloc(needed)) == NULL)
562		errx(1, "malloc");
563	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
564		errx(1, "actual retrieval of interface table");
565	lim = buf + needed;
566
567	next = buf;
568	while (next < lim) {
569
570		ifm = (struct if_msghdr *)next;
571
572		if (ifm->ifm_type == RTM_IFINFO) {
573			sdl = (struct sockaddr_dl *)(ifm + 1);
574			flags = ifm->ifm_flags;
575		} else {
576			fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
577			fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
578				ifm->ifm_type);
579			fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
580			fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
581				lim);
582			exit (1);
583		}
584
585		next += ifm->ifm_msglen;
586		ifam = NULL;
587		addrcount = 0;
588		while (next < lim) {
589
590			nextifm = (struct if_msghdr *)next;
591
592			if (nextifm->ifm_type != RTM_NEWADDR)
593				break;
594
595			if (ifam == NULL)
596				ifam = (struct ifa_msghdr *)nextifm;
597
598			addrcount++;
599			next += nextifm->ifm_msglen;
600		}
601		strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
602		name[sdl->sdl_nlen] = '\0';
603
604		if (all || namesonly) {
605			if (uponly)
606				if ((flags & IFF_UP) == 0)
607					continue; /* not up */
608			if (downonly)
609				if (flags & IFF_UP)
610					continue; /* not down */
611			if (namesonly) {
612				if (afp == NULL ||
613					afp->af_status != ether_status ||
614					sdl->sdl_type == IFT_ETHER) {
615					if (need_nl)
616						putchar(' ');
617					fputs(name, stdout);
618					need_nl++;
619				}
620				continue;
621			}
622		}
623
624		if (argc > 0)
625			ifconfig(argc, argv, afp);
626		else
627			status(afp, addrcount, sdl, ifm, ifam);
628	}
629	free(buf);
630
631	if (namesonly && need_nl > 0)
632		putchar('\n');
633
634	exit (0);
635}
636
637int
638ifconfig(argc, argv, afp)
639	int argc;
640	char *const *argv;
641	const struct afswtch *afp;
642{
643	int s;
644
645	if (afp == NULL)
646		afp = &afs[0];
647	ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
648	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
649
650	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
651		err(1, "socket");
652
653	while (argc > 0) {
654		const struct cmd *p;
655
656		for (p = cmds; p->c_name; p++)
657			if (strcmp(*argv, p->c_name) == 0)
658				break;
659		if (p->c_name == 0 && setaddr)
660			p++;	/* got src, do dst */
661		if (p->c_func || p->c_func2) {
662			if (p->c_parameter == NEXTARG) {
663				if (argv[1] == NULL)
664					errx(1, "'%s' requires argument",
665					    p->c_name);
666				(*p->c_func)(argv[1], 0, s, afp);
667				argc--, argv++;
668			} else if (p->c_parameter == NEXTARG2) {
669				if (argc < 3)
670					errx(1, "'%s' requires 2 arguments",
671					    p->c_name);
672				(*p->c_func2)(argv[1], argv[2], s, afp);
673				argc -= 2, argv += 2;
674			} else
675				(*p->c_func)(*argv, p->c_parameter, s, afp);
676		}
677		argc--, argv++;
678	}
679#ifdef INET6
680	if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) {
681		/* Aggregatable address architecture defines all prefixes
682		   are 64. So, it is convenient to set prefixlen to 64 if
683		   it is not specified. */
684		setifprefixlen("64", 0, s, afp);
685		/* in6_getprefix("64", MASK) if MASK is available here... */
686	}
687#endif
688#ifndef NO_IPX
689	if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) {
690		struct ipxip_req rq;
691		int size = sizeof(rq);
692
693		rq.rq_ipx = addreq.ifra_addr;
694		rq.rq_ip = addreq.ifra_dstaddr;
695
696		if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0)
697			Perror("Encapsulation Routing");
698	}
699#endif
700	if (ifr.ifr_addr.sa_family == AF_APPLETALK)
701		checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
702#ifdef NS
703	if (setipdst && ifr.ifr_addr.sa_family == AF_NS) {
704		struct nsip_req rq;
705		int size = sizeof(rq);
706
707		rq.rq_ns = addreq.ifra_addr;
708		rq.rq_ip = addreq.ifra_dstaddr;
709
710		if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
711			Perror("Encapsulation Routing");
712	}
713#endif
714	if (clearaddr) {
715		if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
716			warnx("interface %s cannot change %s addresses!",
717			      name, afp->af_name);
718			clearaddr = NULL;
719		}
720	}
721	if (clearaddr) {
722		int ret;
723		strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
724		if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) {
725			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
726				/* means no previous address for interface */
727			} else
728				Perror("ioctl (SIOCDIFADDR)");
729		}
730	}
731	if (newaddr) {
732		if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
733			warnx("interface %s cannot change %s addresses!",
734			      name, afp->af_name);
735			newaddr = 0;
736		}
737	}
738	if (newaddr && (setaddr || setmask)) {
739		strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
740		if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
741			Perror("ioctl (SIOCAIFADDR)");
742	}
743	close(s);
744	return(0);
745}
746#define RIDADDR 0
747#define ADDR	1
748#define MASK	2
749#define DSTADDR	3
750
751/*ARGSUSED*/
752void
753setifaddr(addr, param, s, afp)
754	const char *addr;
755	int param;
756	int s;
757	const struct afswtch *afp;
758{
759	if (*afp->af_getaddr == NULL)
760		return;
761	/*
762	 * Delay the ioctl to set the interface addr until flags are all set.
763	 * The address interpretation may depend on the flags,
764	 * and the flags may change when the address is set.
765	 */
766	setaddr++;
767	if (doalias == 0 && afp->af_af != AF_LINK)
768		clearaddr = 1;
769	(*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
770}
771
772void
773settunnel(src, dst, s, afp)
774	const char *src, *dst;
775	int s;
776	const struct afswtch *afp;
777{
778	struct addrinfo hints, *srcres, *dstres;
779	struct ifaliasreq addreq;
780	int ecode;
781#ifdef INET6
782	struct in6_aliasreq in6_addreq;
783#endif
784
785	memset(&hints, 0, sizeof(hints));
786	hints.ai_family = afp->af_af;
787
788	if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
789		errx(1, "error in parsing address string: %s",
790		    gai_strerror(ecode));
791
792	if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
793		errx(1, "error in parsing address string: %s",
794		    gai_strerror(ecode));
795
796	if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
797		errx(1,
798		    "source and destination address families do not match");
799
800	switch (srcres->ai_addr->sa_family) {
801	case AF_INET:
802		memset(&addreq, 0, sizeof(addreq));
803		strncpy(addreq.ifra_name, name, IFNAMSIZ);
804		memcpy(&addreq.ifra_addr, srcres->ai_addr,
805		    srcres->ai_addr->sa_len);
806		memcpy(&addreq.ifra_dstaddr, dstres->ai_addr,
807		    dstres->ai_addr->sa_len);
808
809		if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
810			warn("SIOCSIFPHYADDR");
811		break;
812
813#ifdef INET6
814	case AF_INET6:
815		memset(&in6_addreq, 0, sizeof(in6_addreq));
816		strncpy(in6_addreq.ifra_name, name, IFNAMSIZ);
817		memcpy(&in6_addreq.ifra_addr, srcres->ai_addr,
818		    srcres->ai_addr->sa_len);
819		memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
820		    dstres->ai_addr->sa_len);
821
822		if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0)
823			warn("SIOCSIFPHYADDR_IN6");
824		break;
825#endif /* INET6 */
826
827	default:
828		warn("address family not supported");
829	}
830
831	freeaddrinfo(srcres);
832	freeaddrinfo(dstres);
833}
834
835/* ARGSUSED */
836void
837deletetunnel(vname, param, s, afp)
838	const char *vname;
839	int param;
840	int s;
841	const struct afswtch *afp;
842{
843
844	if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
845		err(1, "SIOCDIFPHYADDR");
846}
847
848void
849setifnetmask(addr, dummy, s, afp)
850	const char *addr;
851	int dummy __unused;
852	int s;
853	const struct afswtch *afp;
854{
855	if (*afp->af_getaddr == NULL)
856		return;
857	setmask++;
858	(*afp->af_getaddr)(addr, MASK);
859}
860
861#ifdef INET6
862void
863setifprefixlen(addr, dummy, s, afp)
864        const char *addr;
865	int dummy __unused;
866	int s;
867	const struct afswtch *afp;
868{
869        if (*afp->af_getprefix)
870                (*afp->af_getprefix)(addr, MASK);
871	explicit_prefix = 1;
872}
873
874void
875setip6flags(dummyaddr, flag, dummysoc, afp)
876	const char *dummyaddr __unused;
877	int flag;
878	int dummysoc __unused;
879	const struct afswtch *afp;
880{
881	if (afp->af_af != AF_INET6)
882		err(1, "address flags can be set only for inet6 addresses");
883
884	if (flag < 0)
885		in6_addreq.ifra_flags &= ~(-flag);
886	else
887		in6_addreq.ifra_flags |= flag;
888}
889
890void
891setip6pltime(seconds, dummy, s, afp)
892    	const char *seconds;
893	int dummy __unused;
894	int s;
895	const struct afswtch *afp;
896{
897	setip6lifetime("pltime", seconds, s, afp);
898}
899
900void
901setip6vltime(seconds, dummy, s, afp)
902    	const char *seconds;
903	int dummy __unused;
904	int s;
905	const struct afswtch *afp;
906{
907	setip6lifetime("vltime", seconds, s, afp);
908}
909
910void
911setip6lifetime(cmd, val, s, afp)
912	const char *cmd;
913	const char *val;
914	int s;
915	const struct afswtch *afp;
916{
917	time_t newval, t;
918	char *ep;
919
920	t = time(NULL);
921	newval = (time_t)strtoul(val, &ep, 0);
922	if (val == ep)
923		errx(1, "invalid %s", cmd);
924	if (afp->af_af != AF_INET6)
925		errx(1, "%s not allowed for the AF", cmd);
926	if (strcmp(cmd, "vltime") == 0) {
927		in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
928		in6_addreq.ifra_lifetime.ia6t_vltime = newval;
929	} else if (strcmp(cmd, "pltime") == 0) {
930		in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
931		in6_addreq.ifra_lifetime.ia6t_pltime = newval;
932	}
933}
934#endif
935
936void
937setifbroadaddr(addr, dummy, s, afp)
938	const char *addr;
939	int dummy __unused;
940	int s;
941	const struct afswtch *afp;
942{
943	if (*afp->af_getaddr == NULL)
944		return;
945	(*afp->af_getaddr)(addr, DSTADDR);
946}
947
948void
949setifipdst(addr, dummy, s, afp)
950	const char *addr;
951	int dummy __unused;
952	int s;
953	const struct afswtch *afp;
954{
955	in_getaddr(addr, DSTADDR);
956	setipdst++;
957	clearaddr = 0;
958	newaddr = 0;
959}
960#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
961
962void
963notealias(addr, param, s, afp)
964	const char *addr;
965	int param;
966	int s;
967	const struct afswtch *afp;
968{
969	if (setaddr && doalias == 0 && param < 0)
970		bcopy((caddr_t)rqtosa(af_addreq),
971		      (caddr_t)rqtosa(af_ridreq),
972		      rqtosa(af_addreq)->sa_len);
973	doalias = param;
974	if (param < 0) {
975		clearaddr = 1;
976		newaddr = 0;
977	} else
978		clearaddr = 0;
979}
980
981/*ARGSUSED*/
982void
983setifdstaddr(addr, param, s, afp)
984	const char *addr;
985	int param __unused;
986	int s;
987	const struct afswtch *afp;
988{
989	if (*afp->af_getaddr == NULL)
990		return;
991	(*afp->af_getaddr)(addr, DSTADDR);
992}
993
994/*
995 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
996 * of the ifreq structure, which may confuse other parts of ifconfig.
997 * Make a private copy so we can avoid that.
998 */
999void
1000setifflags(vname, value, s, afp)
1001	const char *vname;
1002	int value;
1003	int s;
1004	const struct afswtch *afp;
1005{
1006	struct ifreq		my_ifr;
1007
1008	bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
1009
1010 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
1011 		Perror("ioctl (SIOCGIFFLAGS)");
1012 		exit(1);
1013 	}
1014	strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name));
1015 	flags = my_ifr.ifr_flags;
1016
1017	if (value < 0) {
1018		value = -value;
1019		flags &= ~value;
1020	} else
1021		flags |= value;
1022	my_ifr.ifr_flags = flags;
1023	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
1024		Perror(vname);
1025}
1026
1027void
1028setifcap(vname, value, s, afp)
1029	const char *vname;
1030	int value;
1031	int s;
1032	const struct afswtch *afp;
1033{
1034
1035 	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
1036 		Perror("ioctl (SIOCGIFCAP)");
1037 		exit(1);
1038 	}
1039	flags = ifr.ifr_curcap;
1040	if (value < 0) {
1041		value = -value;
1042		flags &= ~value;
1043	} else
1044		flags |= value;
1045	ifr.ifr_reqcap = flags;
1046	if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
1047		Perror(vname);
1048}
1049
1050void
1051setifmetric(val, dummy, s, afp)
1052	const char *val;
1053	int dummy __unused;
1054	int s;
1055	const struct afswtch *afp;
1056{
1057	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1058	ifr.ifr_metric = atoi(val);
1059	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
1060		warn("ioctl (set metric)");
1061}
1062
1063void
1064setifmtu(val, dummy, s, afp)
1065	const char *val;
1066	int dummy __unused;
1067	int s;
1068	const struct afswtch *afp;
1069{
1070	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1071	ifr.ifr_mtu = atoi(val);
1072	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
1073		warn("ioctl (set mtu)");
1074}
1075
1076void
1077setiflladdr(val, dummy, s, afp)
1078	const char *val;
1079	int dummy __unused;
1080	int s;
1081	const struct afswtch *afp;
1082{
1083	struct ether_addr	*ea;
1084
1085	ea = ether_aton(val);
1086	if (ea == NULL) {
1087		warn("malformed link-level address");
1088		return;
1089	}
1090	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1091	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
1092	ifr.ifr_addr.sa_family = AF_LINK;
1093	bcopy(ea, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
1094	if (ioctl(s, SIOCSIFLLADDR, (caddr_t)&ifr) < 0)
1095		warn("ioctl (set lladdr)");
1096
1097	return;
1098}
1099
1100#define	IFFBITS \
1101"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
1102"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1103"\20MULTICAST"
1104
1105#define	IFCAPBITS \
1106"\003\1rxcsum\2txcsum\3netcons"
1107
1108/*
1109 * Print the status of the interface.  If an address family was
1110 * specified, show it and it only; otherwise, show them all.
1111 */
1112void
1113status(afp, addrcount, sdl, ifm, ifam)
1114	const struct afswtch *afp;
1115	int addrcount;
1116	struct	sockaddr_dl *sdl;
1117	struct if_msghdr *ifm;
1118	struct ifa_msghdr *ifam;
1119{
1120	const struct afswtch *p = NULL;
1121	struct	rt_addrinfo info;
1122	int allfamilies, s;
1123	struct ifstat ifs;
1124
1125	if (afp == NULL) {
1126		allfamilies = 1;
1127		afp = &afs[0];
1128	} else
1129		allfamilies = 0;
1130
1131	ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
1132	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1133
1134	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
1135		err(1, "socket");
1136
1137	printf("%s: ", name);
1138	printb("flags", flags, IFFBITS);
1139	if (ifm->ifm_data.ifi_metric)
1140		printf(" metric %ld", ifm->ifm_data.ifi_metric);
1141	if (ifm->ifm_data.ifi_mtu)
1142		printf(" mtu %ld", ifm->ifm_data.ifi_mtu);
1143	putchar('\n');
1144
1145	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
1146		if (ifr.ifr_curcap != 0) {
1147			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
1148			putchar('\n');
1149		}
1150		if (supmedia && ifr.ifr_reqcap != 0) {
1151			printf("\tcapability list:\n");
1152			printb("\t\t", ifr.ifr_reqcap, IFCAPBITS);
1153			putchar('\n');
1154		}
1155	}
1156
1157	tunnel_status(s);
1158
1159	while (addrcount > 0) {
1160
1161		info.rti_addrs = ifam->ifam_addrs;
1162
1163		/* Expand the compacted addresses */
1164		rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
1165			  &info);
1166
1167		if (!allfamilies) {
1168			if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) {
1169				p = afp;
1170				(*p->af_status)(s, &info);
1171			}
1172		} else for (p = afs; p->af_name; p++) {
1173			if (p->af_af == info.rti_info[RTAX_IFA]->sa_family)
1174				(*p->af_status)(s, &info);
1175		}
1176		addrcount--;
1177		ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
1178	}
1179	if (allfamilies || afp->af_status == ether_status)
1180		ether_status(s, (struct rt_addrinfo *)sdl);
1181#ifdef USE_IF_MEDIA
1182	if (allfamilies || afp->af_status == media_status)
1183		media_status(s, NULL);
1184#endif
1185#ifdef USE_VLANS
1186	if (allfamilies || afp->af_status == vlan_status)
1187		vlan_status(s, NULL);
1188#endif
1189#ifdef USE_IEEE80211
1190	if (allfamilies || afp->af_status == ieee80211_status)
1191		ieee80211_status(s, NULL);
1192#endif
1193	strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
1194	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
1195		printf("%s", ifs.ascii);
1196
1197	if (!allfamilies && !p && afp->af_status != media_status &&
1198	    afp->af_status != ether_status
1199#ifdef USE_VLANS
1200	    && afp->af_status != vlan_status
1201#endif
1202		)
1203		warnx("%s has no %s interface address!", name, afp->af_name);
1204
1205	close(s);
1206	return;
1207}
1208
1209void
1210tunnel_status(s)
1211	int s;
1212{
1213	char psrcaddr[NI_MAXHOST];
1214	char pdstaddr[NI_MAXHOST];
1215	u_long srccmd, dstcmd;
1216	struct ifreq *ifrp;
1217	const char *ver = "";
1218#ifdef NI_WITHSCOPEID
1219	const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID;
1220#else
1221	const int niflag = NI_NUMERICHOST;
1222#endif
1223#ifdef INET6
1224	struct in6_ifreq in6_ifr;
1225	int s6;
1226#endif /* INET6 */
1227
1228	psrcaddr[0] = pdstaddr[0] = '\0';
1229
1230#ifdef INET6
1231	memset(&in6_ifr, 0, sizeof(in6_ifr));
1232	strncpy(in6_ifr.ifr_name, name, IFNAMSIZ);
1233	s6 = socket(AF_INET6, SOCK_DGRAM, 0);
1234	if (s6 < 0) {
1235		srccmd = SIOCGIFPSRCADDR;
1236		dstcmd = SIOCGIFPDSTADDR;
1237		ifrp = &ifr;
1238	} else {
1239		close(s6);
1240		srccmd = SIOCGIFPSRCADDR_IN6;
1241		dstcmd = SIOCGIFPDSTADDR_IN6;
1242		ifrp = (struct ifreq *)&in6_ifr;
1243	}
1244#else /* INET6 */
1245	srccmd = SIOCGIFPSRCADDR;
1246	dstcmd = SIOCGIFPDSTADDR;
1247	ifrp = &ifr;
1248#endif /* INET6 */
1249
1250	if (ioctl(s, srccmd, (caddr_t)ifrp) < 0)
1251		return;
1252#ifdef INET6
1253	if (ifrp->ifr_addr.sa_family == AF_INET6)
1254		in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr);
1255#endif
1256	getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
1257	    psrcaddr, sizeof(psrcaddr), 0, 0, niflag);
1258#ifdef INET6
1259	if (ifrp->ifr_addr.sa_family == AF_INET6)
1260		ver = "6";
1261#endif
1262
1263	if (ioctl(s, dstcmd, (caddr_t)ifrp) < 0)
1264		return;
1265#ifdef INET6
1266	if (ifrp->ifr_addr.sa_family == AF_INET6)
1267		in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr);
1268#endif
1269	getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
1270	    pdstaddr, sizeof(pdstaddr), 0, 0, niflag);
1271
1272	printf("\ttunnel inet%s %s --> %s\n", ver,
1273	    psrcaddr, pdstaddr);
1274}
1275
1276void
1277in_status(s, info)
1278	int s __unused;
1279	struct rt_addrinfo * info;
1280{
1281	struct sockaddr_in *sin, null_sin;
1282
1283	memset(&null_sin, 0, sizeof(null_sin));
1284
1285	sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA];
1286	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
1287
1288	if (flags & IFF_POINTOPOINT) {
1289		/* note RTAX_BRD overlap with IFF_BROADCAST */
1290		sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
1291		if (!sin)
1292			sin = &null_sin;
1293		printf("--> %s ", inet_ntoa(sin->sin_addr));
1294	}
1295
1296	sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK];
1297	if (!sin)
1298		sin = &null_sin;
1299	printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
1300
1301	if (flags & IFF_BROADCAST) {
1302		/* note RTAX_BRD overlap with IFF_POINTOPOINT */
1303		sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD];
1304		if (sin && sin->sin_addr.s_addr != 0)
1305			printf("broadcast %s", inet_ntoa(sin->sin_addr));
1306	}
1307	putchar('\n');
1308}
1309
1310#ifdef INET6
1311void
1312in6_fillscopeid(sin6)
1313	struct sockaddr_in6 *sin6;
1314{
1315#if defined(__KAME__) && defined(KAME_SCOPEID)
1316	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1317		sin6->sin6_scope_id =
1318			ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
1319		sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
1320	}
1321#endif
1322}
1323
1324void
1325in6_status(s, info)
1326	int s __unused;
1327	struct rt_addrinfo * info;
1328{
1329	struct sockaddr_in6 *sin, null_sin;
1330	struct in6_ifreq ifr6;
1331	int s6;
1332	u_int32_t flags6;
1333	struct in6_addrlifetime lifetime;
1334	time_t t = time(NULL);
1335	int error;
1336	u_int32_t scopeid;
1337
1338	memset(&null_sin, 0, sizeof(null_sin));
1339
1340	sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA];
1341	strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
1342	if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1343		perror("ifconfig: socket");
1344		return;
1345	}
1346	ifr6.ifr_addr = *sin;
1347	if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
1348		perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)");
1349		close(s6);
1350		return;
1351	}
1352	flags6 = ifr6.ifr_ifru.ifru_flags6;
1353	memset(&lifetime, 0, sizeof(lifetime));
1354	ifr6.ifr_addr = *sin;
1355	if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
1356		perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)");
1357		close(s6);
1358		return;
1359	}
1360	lifetime = ifr6.ifr_ifru.ifru_lifetime;
1361	close(s6);
1362
1363	/* XXX: embedded link local addr check */
1364	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
1365	    *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) {
1366		u_short index;
1367
1368		index = *(u_short *)&sin->sin6_addr.s6_addr[2];
1369		*(u_short *)&sin->sin6_addr.s6_addr[2] = 0;
1370		if (sin->sin6_scope_id == 0)
1371			sin->sin6_scope_id = ntohs(index);
1372	}
1373	scopeid = sin->sin6_scope_id;
1374
1375	error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf,
1376			    sizeof(addr_buf), NULL, 0,
1377			    NI_NUMERICHOST|NI_WITHSCOPEID);
1378	if (error != 0)
1379		inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
1380			  sizeof(addr_buf));
1381	printf("\tinet6 %s ", addr_buf);
1382
1383	if (flags & IFF_POINTOPOINT) {
1384		/* note RTAX_BRD overlap with IFF_BROADCAST */
1385		sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD];
1386		/*
1387		 * some of the interfaces do not have valid destination
1388		 * address.
1389		 */
1390		if (sin && sin->sin6_family == AF_INET6) {
1391			int error;
1392
1393			/* XXX: embedded link local addr check */
1394			if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
1395			    *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) {
1396				u_short index;
1397
1398				index = *(u_short *)&sin->sin6_addr.s6_addr[2];
1399				*(u_short *)&sin->sin6_addr.s6_addr[2] = 0;
1400				if (sin->sin6_scope_id == 0)
1401					sin->sin6_scope_id = ntohs(index);
1402			}
1403
1404			error = getnameinfo((struct sockaddr *)sin,
1405					    sin->sin6_len, addr_buf,
1406					    sizeof(addr_buf), NULL, 0,
1407					    NI_NUMERICHOST|NI_WITHSCOPEID);
1408			if (error != 0)
1409				inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
1410					  sizeof(addr_buf));
1411			printf("--> %s ", addr_buf);
1412		}
1413	}
1414
1415	sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK];
1416	if (!sin)
1417		sin = &null_sin;
1418	printf("prefixlen %d ", prefix(&sin->sin6_addr,
1419		sizeof(struct in6_addr)));
1420
1421	if ((flags6 & IN6_IFF_ANYCAST) != 0)
1422		printf("anycast ");
1423	if ((flags6 & IN6_IFF_TENTATIVE) != 0)
1424		printf("tentative ");
1425	if ((flags6 & IN6_IFF_DUPLICATED) != 0)
1426		printf("duplicated ");
1427	if ((flags6 & IN6_IFF_DETACHED) != 0)
1428		printf("detached ");
1429	if ((flags6 & IN6_IFF_DEPRECATED) != 0)
1430		printf("deprecated ");
1431	if ((flags6 & IN6_IFF_AUTOCONF) != 0)
1432		printf("autoconf ");
1433	if ((flags6 & IN6_IFF_TEMPORARY) != 0)
1434		printf("temporary ");
1435
1436        if (scopeid)
1437		printf("scopeid 0x%x ", scopeid);
1438
1439	if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
1440		printf("pltime ");
1441		if (lifetime.ia6t_preferred) {
1442			printf("%s ", lifetime.ia6t_preferred < t
1443				? "0" : sec2str(lifetime.ia6t_preferred - t));
1444		} else
1445			printf("infty ");
1446
1447		printf("vltime ");
1448		if (lifetime.ia6t_expire) {
1449			printf("%s ", lifetime.ia6t_expire < t
1450				? "0" : sec2str(lifetime.ia6t_expire - t));
1451		} else
1452			printf("infty ");
1453	}
1454
1455	putchar('\n');
1456}
1457#endif /*INET6*/
1458
1459#ifndef NO_IPX
1460void
1461ipx_status(s, info)
1462	int s __unused;
1463	struct rt_addrinfo * info;
1464{
1465	struct sockaddr_ipx *sipx, null_sipx;
1466
1467	memset(&null_sipx, 0, sizeof(null_sipx));
1468
1469	sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA];
1470	printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr));
1471
1472	if (flags & IFF_POINTOPOINT) {
1473		sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD];
1474		if (!sipx)
1475			sipx = &null_sipx;
1476		printf("--> %s ", ipx_ntoa(sipx->sipx_addr));
1477	}
1478	putchar('\n');
1479}
1480#endif
1481
1482void
1483at_status(s, info)
1484	int s __unused;
1485	struct rt_addrinfo * info;
1486{
1487	struct sockaddr_at *sat, null_sat;
1488	struct netrange *nr;
1489
1490	memset(&null_sat, 0, sizeof(null_sat));
1491
1492	sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA];
1493	nr = &sat->sat_range.r_netrange;
1494	printf("\tatalk %d.%d range %d-%d phase %d",
1495		ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1496		ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
1497	if (flags & IFF_POINTOPOINT) {
1498		/* note RTAX_BRD overlap with IFF_BROADCAST */
1499		sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
1500		if (!sat)
1501			sat = &null_sat;
1502		printf("--> %d.%d",
1503			ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
1504	}
1505	if (flags & IFF_BROADCAST) {
1506		/* note RTAX_BRD overlap with IFF_POINTOPOINT */
1507		sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
1508		if (sat)
1509			printf(" broadcast %d.%d",
1510				ntohs(sat->sat_addr.s_net),
1511				sat->sat_addr.s_node);
1512	}
1513
1514	putchar('\n');
1515}
1516
1517#ifdef NS
1518void
1519xns_status(s, info)
1520	int s __unused;
1521	struct rt_addrinfo * info;
1522{
1523	struct sockaddr_ns *sns, null_sns;
1524
1525	memset(&null_sns, 0, sizeof(null_sns));
1526
1527	sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA];
1528	printf("\tns %s ", ns_ntoa(sns->sns_addr));
1529
1530	if (flags & IFF_POINTOPOINT) {
1531		sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD];
1532		if (!sns)
1533			sns = &null_sns;
1534		printf("--> %s ", ns_ntoa(sns->sns_addr));
1535	}
1536
1537	putchar('\n');
1538	close(s);
1539}
1540#endif
1541
1542
1543void
1544ether_status(s, info)
1545	int s __unused;
1546	struct rt_addrinfo *info;
1547{
1548	char *cp;
1549	int n;
1550	struct sockaddr_dl *sdl = (struct sockaddr_dl *)info;
1551
1552	cp = (char *)LLADDR(sdl);
1553	if ((n = sdl->sdl_alen) > 0) {
1554		if (sdl->sdl_type == IFT_ETHER)
1555			printf ("\tether ");
1556		else
1557			printf ("\tlladdr ");
1558             	while (--n >= 0)
1559			printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
1560		putchar('\n');
1561	}
1562}
1563
1564void
1565Perror(cmd)
1566	const char *cmd;
1567{
1568	switch (errno) {
1569
1570	case ENXIO:
1571		errx(1, "%s: no such interface", cmd);
1572		break;
1573
1574	case EPERM:
1575		errx(1, "%s: permission denied", cmd);
1576		break;
1577
1578	default:
1579		err(1, "%s", cmd);
1580	}
1581}
1582
1583#define SIN(x) ((struct sockaddr_in *) &(x))
1584struct sockaddr_in *sintab[] = {
1585SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
1586SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
1587
1588void
1589in_getaddr(s, which)
1590	const char *s;
1591	int which;
1592{
1593	struct sockaddr_in *sin = sintab[which];
1594	struct hostent *hp;
1595	struct netent *np;
1596
1597	sin->sin_len = sizeof(*sin);
1598	if (which != MASK)
1599		sin->sin_family = AF_INET;
1600
1601	if (which == ADDR) {
1602		char *p = NULL;
1603
1604		if((p = strrchr(s, '/')) != NULL) {
1605			/* address is `name/masklen' */
1606			int masklen;
1607			int ret;
1608			struct sockaddr_in *min = sintab[MASK];
1609			*p = '\0';
1610			ret = sscanf(p+1, "%u", &masklen);
1611			if(ret != 1 || (masklen < 0 || masklen > 32)) {
1612				*p = '/';
1613				errx(1, "%s: bad value", s);
1614			}
1615			min->sin_len = sizeof(*min);
1616			min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
1617				              0xffffffff);
1618		}
1619	}
1620
1621	if (inet_aton(s, &sin->sin_addr))
1622		return;
1623	if ((hp = gethostbyname(s)) != 0)
1624		bcopy(hp->h_addr, (char *)&sin->sin_addr,
1625		    MIN(hp->h_length, sizeof(sin->sin_addr)));
1626	else if ((np = getnetbyname(s)) != 0)
1627		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
1628	else
1629		errx(1, "%s: bad value", s);
1630}
1631
1632#ifdef INET6
1633#define	SIN6(x) ((struct sockaddr_in6 *) &(x))
1634struct	sockaddr_in6 *sin6tab[] = {
1635SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
1636SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)};
1637
1638void
1639in6_getaddr(s, which)
1640	const char *s;
1641	int which;
1642{
1643	struct sockaddr_in6 *sin = sin6tab[which];
1644	struct addrinfo hints, *res;
1645	int error = -1;
1646
1647	newaddr &= 1;
1648
1649	sin->sin6_len = sizeof(*sin);
1650	if (which != MASK)
1651		sin->sin6_family = AF_INET6;
1652
1653	if (which == ADDR) {
1654		char *p = NULL;
1655		if((p = strrchr(s, '/')) != NULL) {
1656			*p = '\0';
1657			in6_getprefix(p + 1, MASK);
1658			explicit_prefix = 1;
1659		}
1660	}
1661
1662	if (sin->sin6_family == AF_INET6) {
1663		bzero(&hints, sizeof(struct addrinfo));
1664		hints.ai_family = AF_INET6;
1665		error = getaddrinfo(s, NULL, &hints, &res);
1666	}
1667	if (error != 0) {
1668		if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
1669			errx(1, "%s: bad value", s);
1670	} else
1671		bcopy(res->ai_addr, sin, res->ai_addrlen);
1672}
1673
1674void
1675in6_getprefix(plen, which)
1676	const char *plen;
1677	int which;
1678{
1679	struct sockaddr_in6 *sin = sin6tab[which];
1680	u_char *cp;
1681	int len = atoi(plen);
1682
1683	if ((len < 0) || (len > 128))
1684		errx(1, "%s: bad value", plen);
1685	sin->sin6_len = sizeof(*sin);
1686	if (which != MASK)
1687		sin->sin6_family = AF_INET6;
1688	if ((len == 0) || (len == 128)) {
1689		memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr));
1690		return;
1691	}
1692	memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr));
1693	for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
1694		*cp++ = 0xff;
1695	*cp = 0xff << (8 - len);
1696}
1697#endif
1698
1699/*
1700 * Print a value a la the %b format of the kernel's printf
1701 */
1702void
1703printb(s, v, bits)
1704	const char *s;
1705	unsigned v;
1706	const char *bits;
1707{
1708	int i, any = 0;
1709	char c;
1710
1711	if (bits && *bits == 8)
1712		printf("%s=%o", s, v);
1713	else
1714		printf("%s=%x", s, v);
1715	bits++;
1716	if (bits) {
1717		putchar('<');
1718		while ((i = *bits++) != '\0') {
1719			if (v & (1 << (i-1))) {
1720				if (any)
1721					putchar(',');
1722				any = 1;
1723				for (; (c = *bits) > 32; bits++)
1724					putchar(c);
1725			} else
1726				for (; *bits > 32; bits++)
1727					;
1728		}
1729		putchar('>');
1730	}
1731}
1732
1733#ifndef NO_IPX
1734#define SIPX(x) ((struct sockaddr_ipx *) &(x))
1735struct sockaddr_ipx *sipxtab[] = {
1736SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr),
1737SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)};
1738
1739void
1740ipx_getaddr(addr, which)
1741	const char *addr;
1742	int which;
1743{
1744	struct sockaddr_ipx *sipx = sipxtab[which];
1745
1746	sipx->sipx_family = AF_IPX;
1747	sipx->sipx_len = sizeof(*sipx);
1748	sipx->sipx_addr = ipx_addr(addr);
1749	if (which == MASK)
1750		printf("Attempt to set IPX netmask will be ineffectual\n");
1751}
1752#endif
1753
1754void
1755at_getaddr(addr, which)
1756	const char *addr;
1757	int which;
1758{
1759	struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
1760	u_int net, node;
1761
1762	sat->sat_family = AF_APPLETALK;
1763	sat->sat_len = sizeof(*sat);
1764	if (which == MASK)
1765		errx(1, "AppleTalk does not use netmasks");
1766	if (sscanf(addr, "%u.%u", &net, &node) != 2
1767	    || net > 0xffff || node > 0xfe)
1768		errx(1, "%s: illegal address", addr);
1769	sat->sat_addr.s_net = htons(net);
1770	sat->sat_addr.s_node = node;
1771}
1772
1773void
1774ether_getaddr(addr, which)
1775	const char *addr;
1776	int which;
1777{
1778	struct ether_addr *ea;
1779	struct sockaddr *sea = &ridreq.ifr_addr;
1780
1781	ea = ether_aton(addr);
1782	if (ea == NULL)
1783		errx(1, "malformed ether address");
1784	if (which == MASK)
1785		errx(1, "Ethernet does not use netmasks");
1786	sea->sa_family = AF_LINK;
1787	sea->sa_len = ETHER_ADDR_LEN;
1788	bcopy(ea, sea->sa_data, ETHER_ADDR_LEN);
1789}
1790
1791/* XXX  FIXME -- should use strtoul for better parsing. */
1792void
1793setatrange(range, dummy, s, afp)
1794	const char *range;
1795	int dummy __unused;
1796	int s;
1797	const struct afswtch *afp;
1798{
1799	u_short	first = 123, last = 123;
1800
1801	if (sscanf(range, "%hu-%hu", &first, &last) != 2
1802	    || first == 0 || first > 0xffff
1803	    || last == 0 || last > 0xffff || first > last)
1804		errx(1, "%s: illegal net range: %u-%u", range, first, last);
1805	at_nr.nr_firstnet = htons(first);
1806	at_nr.nr_lastnet = htons(last);
1807}
1808
1809void
1810setatphase(phase, dummy, s, afp)
1811	const char *phase;
1812	int dummy __unused;
1813	int s;
1814	const struct afswtch *afp;
1815{
1816	if (!strcmp(phase, "1"))
1817		at_nr.nr_phase = 1;
1818	else if (!strcmp(phase, "2"))
1819		at_nr.nr_phase = 2;
1820	else
1821		errx(1, "%s: illegal phase", phase);
1822}
1823
1824void
1825checkatrange(struct sockaddr_at *sat)
1826{
1827	if (at_nr.nr_phase == 0)
1828		at_nr.nr_phase = 2;	/* Default phase 2 */
1829	if (at_nr.nr_firstnet == 0)
1830		at_nr.nr_firstnet =	/* Default range of one */
1831		at_nr.nr_lastnet = sat->sat_addr.s_net;
1832printf("\tatalk %d.%d range %d-%d phase %d\n",
1833	ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1834	ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
1835	if ((u_short) ntohs(at_nr.nr_firstnet) >
1836			(u_short) ntohs(sat->sat_addr.s_net)
1837		    || (u_short) ntohs(at_nr.nr_lastnet) <
1838			(u_short) ntohs(sat->sat_addr.s_net))
1839		errx(1, "AppleTalk address is not in range");
1840	sat->sat_range.r_netrange = at_nr;
1841}
1842
1843#ifdef NS
1844#define SNS(x) ((struct sockaddr_ns *) &(x))
1845struct sockaddr_ns *snstab[] = {
1846SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
1847SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
1848
1849void
1850xns_getaddr(addr, which)
1851	const char *addr;
1852	int which;
1853{
1854	struct sockaddr_ns *sns = snstab[which];
1855
1856	sns->sns_family = AF_NS;
1857	sns->sns_len = sizeof(*sns);
1858	sns->sns_addr = ns_addr(addr);
1859	if (which == MASK)
1860		printf("Attempt to set XNS netmask will be ineffectual\n");
1861}
1862#endif
1863
1864#ifdef INET6
1865int
1866prefix(val, size)
1867        void *val;
1868        int size;
1869{
1870        u_char *name = (u_char *)val;
1871        int byte, bit, plen = 0;
1872
1873        for (byte = 0; byte < size; byte++, plen += 8)
1874                if (name[byte] != 0xff)
1875                        break;
1876	if (byte == size)
1877		return (plen);
1878	for (bit = 7; bit != 0; bit--, plen++)
1879                if (!(name[byte] & (1 << bit)))
1880                        break;
1881        for (; bit != 0; bit--)
1882                if (name[byte] & (1 << bit))
1883                        return(0);
1884        byte++;
1885        for (; byte < size; byte++)
1886                if (name[byte])
1887                        return(0);
1888        return (plen);
1889}
1890
1891static char *
1892sec2str(total)
1893	time_t total;
1894{
1895	static char result[256];
1896	int days, hours, mins, secs;
1897	int first = 1;
1898	char *p = result;
1899
1900	if (0) {
1901		days = total / 3600 / 24;
1902		hours = (total / 3600) % 24;
1903		mins = (total / 60) % 60;
1904		secs = total % 60;
1905
1906		if (days) {
1907			first = 0;
1908			p += sprintf(p, "%dd", days);
1909		}
1910		if (!first || hours) {
1911			first = 0;
1912			p += sprintf(p, "%dh", hours);
1913		}
1914		if (!first || mins) {
1915			first = 0;
1916			p += sprintf(p, "%dm", mins);
1917		}
1918		sprintf(p, "%ds", secs);
1919	} else
1920		sprintf(result, "%lu", (unsigned long)total);
1921
1922	return(result);
1923}
1924#endif /*INET6*/
1925
1926void
1927ifmaybeload(name)
1928	char *name;
1929{
1930	struct module_stat mstat;
1931	int fileid, modid;
1932	char ifkind[35], *cp, *dp;
1933
1934	/* turn interface and unit into module name */
1935	strcpy(ifkind, "if_");
1936	for (cp = name, dp = ifkind + 3;
1937	    (*cp != 0) && !isdigit(*cp); cp++, dp++)
1938		*dp = *cp;
1939	*dp = 0;
1940
1941	/* scan files in kernel */
1942	mstat.version = sizeof(struct module_stat);
1943	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1944		/* scan modules in file */
1945		for (modid = kldfirstmod(fileid); modid > 0;
1946		     modid = modfnext(modid)) {
1947			if (modstat(modid, &mstat) < 0)
1948				continue;
1949			/* strip bus name if present */
1950			if ((cp = strchr(mstat.name, '/')) != NULL) {
1951				cp++;
1952			} else {
1953				cp = mstat.name;
1954			}
1955			/* already loaded? */
1956			if (!strcmp(ifkind, cp))
1957				return;
1958		}
1959	}
1960
1961	/* not present, we should try to load it */
1962	kldload(ifkind);
1963}
1964
1965void
1966list_cloners(void)
1967{
1968	struct if_clonereq ifcr;
1969	char *cp, *buf;
1970	int idx;
1971	int s;
1972
1973	s = socket(AF_INET, SOCK_DGRAM, 0);
1974	if (s == -1)
1975		err(1, "socket");
1976
1977	memset(&ifcr, 0, sizeof(ifcr));
1978
1979	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
1980		err(1, "SIOCIFGCLONERS for count");
1981
1982	buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
1983	if (buf == NULL)
1984		err(1, "unable to allocate cloner name buffer");
1985
1986	ifcr.ifcr_count = ifcr.ifcr_total;
1987	ifcr.ifcr_buffer = buf;
1988
1989	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
1990		err(1, "SIOCIFGCLONERS for names");
1991
1992	/*
1993	 * In case some disappeared in the mean time, clamp it down.
1994	 */
1995	if (ifcr.ifcr_count > ifcr.ifcr_total)
1996		ifcr.ifcr_count = ifcr.ifcr_total;
1997
1998	for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
1999		if (idx > 0)
2000			putchar(' ');
2001		printf("%s", cp);
2002	}
2003
2004	putchar('\n');
2005	free(buf);
2006}
2007
2008void
2009clone_create()
2010{
2011	int s;
2012
2013	s = socket(AF_INET, SOCK_DGRAM, 0);
2014	if (s == -1)
2015		err(1, "socket");
2016
2017	memset(&ifr, 0, sizeof(ifr));
2018	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2019	if (ioctl(s, SIOCIFCREATE, &ifr) < 0)
2020		err(1, "SIOCIFCREATE");
2021
2022	if (strcmp(name, ifr.ifr_name) != 0) {
2023		printf("%s\n", ifr.ifr_name);
2024		strlcpy(name, ifr.ifr_name, sizeof(name));
2025	}
2026
2027	close(s);
2028}
2029
2030void
2031clone_destroy(val, d, s, rafp)
2032	const char *val;
2033	int d;
2034	int s;
2035	const struct afswtch *rafp;
2036{
2037
2038	(void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2039	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
2040		err(1, "SIOCIFDESTROY");
2041}
2042