ifconfig.c revision 1.22
1/*	$NetBSD: ifconfig.c,v 1.22 1996/01/04 20:11:20 pk Exp $	*/
2
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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37static char copyright[] =
38"@(#) Copyright (c) 1983, 1993\n\
39	The Regents of the University of California.  All rights reserved.\n";
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
45#else
46static char rcsid[] = "$NetBSD: ifconfig.c,v 1.22 1996/01/04 20:11:20 pk Exp $";
47#endif
48#endif /* not lint */
49
50#include <sys/param.h>
51#include <sys/socket.h>
52#include <sys/ioctl.h>
53
54#include <net/if.h>
55#include <netinet/in.h>
56#include <arpa/inet.h>
57
58#define	NSIP
59#include <netns/ns.h>
60#include <netns/ns_if.h>
61#include <netdb.h>
62
63#define EON
64#include <netiso/iso.h>
65#include <netiso/iso_var.h>
66#include <sys/protosw.h>
67
68#include <ctype.h>
69#include <err.h>
70#include <errno.h>
71#include <stdio.h>
72#include <stdlib.h>
73#include <string.h>
74#include <unistd.h>
75
76struct	ifreq		ifr, ridreq;
77struct	ifaliasreq	addreq;
78struct	iso_ifreq	iso_ridreq;
79struct	iso_aliasreq	iso_addreq;
80struct	sockaddr_in	netmask;
81char	name[30];
82int	flags, metric, setaddr, setipdst, doalias;
83int	clearaddr, s;
84int	newaddr = 1;
85int	nsellength = 1;
86int	af = AF_INET;
87
88void 	notealias __P((char *, int));
89void 	notrailers __P((char *, int));
90void 	setifaddr __P((char *, int));
91void 	setifdstaddr __P((char *, int));
92void 	setifflags __P((char *, int));
93void 	setifbroadaddr __P((char *));
94void 	setifipdst __P((char *));
95void 	setifmetric __P((char *));
96void 	setifnetmask __P((char *));
97void 	setnsellength __P((char *));
98void 	setsnpaoffset __P((char *));
99
100#define	NEXTARG		0xffffff
101
102struct	cmd {
103	char	*c_name;
104	int	c_parameter;		/* NEXTARG means next argv */
105	void	(*c_func)();
106} cmds[] = {
107	{ "up",		IFF_UP,		setifflags } ,
108	{ "down",	-IFF_UP,	setifflags },
109	{ "trailers",	-1,		notrailers },
110	{ "-trailers",	1,		notrailers },
111	{ "arp",	-IFF_NOARP,	setifflags },
112	{ "-arp",	IFF_NOARP,	setifflags },
113	{ "debug",	IFF_DEBUG,	setifflags },
114	{ "-debug",	-IFF_DEBUG,	setifflags },
115	{ "alias",	IFF_UP,		notealias },
116	{ "-alias",	-IFF_UP,	notealias },
117	{ "delete",	-IFF_UP,	notealias },
118#ifdef notdef
119#define	EN_SWABIPS	0x1000
120	{ "swabips",	EN_SWABIPS,	setifflags },
121	{ "-swabips",	-EN_SWABIPS,	setifflags },
122#endif
123	{ "netmask",	NEXTARG,	setifnetmask },
124	{ "metric",	NEXTARG,	setifmetric },
125	{ "broadcast",	NEXTARG,	setifbroadaddr },
126	{ "ipdst",	NEXTARG,	setifipdst },
127#ifndef INET_ONLY
128	{ "snpaoffset",	NEXTARG,	setsnpaoffset },
129	{ "nsellength",	NEXTARG,	setnsellength },
130#endif	/* INET_ONLY */
131	{ "link0",	IFF_LINK0,	setifflags } ,
132	{ "-link0",	-IFF_LINK0,	setifflags } ,
133	{ "link1",	IFF_LINK1,	setifflags } ,
134	{ "-link1",	-IFF_LINK1,	setifflags } ,
135	{ "link2",	IFF_LINK2,	setifflags } ,
136	{ "-link2",	-IFF_LINK2,	setifflags } ,
137	{ 0,		0,		setifaddr },
138	{ 0,		0,		setifdstaddr },
139};
140
141void 	adjust_nsellength();
142int	getinfo __P((struct ifreq *));
143void	getsock __P((int));
144void	printall __P((void));
145void 	printb __P((char *, unsigned short, char *));
146void 	status();
147void 	usage();
148
149/*
150 * XNS support liberally adapted from code written at the University of
151 * Maryland principally by James O'Toole and Chris Torek.
152 */
153void	in_status __P((int));
154void 	in_getaddr __P((char *, int));
155void 	xns_status __P((int));
156void 	xns_getaddr __P((char *, int));
157void 	iso_status __P((int));
158void 	iso_getaddr __P((char *, int));
159
160/* Known address families */
161struct afswtch {
162	char *af_name;
163	short af_af;
164	void (*af_status)();
165	void (*af_getaddr)();
166	u_long af_difaddr;
167	u_long af_aifaddr;
168	caddr_t af_ridreq;
169	caddr_t af_addreq;
170} afs[] = {
171#define C(x) ((caddr_t) &x)
172	{ "inet", AF_INET, in_status, in_getaddr,
173	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
174#ifndef INET_ONLY	/* small version, for boot media */
175	{ "ns", AF_NS, xns_status, xns_getaddr,
176	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
177	{ "iso", AF_ISO, iso_status, iso_getaddr,
178	     SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
179#endif	/* INET_ONLY */
180	{ 0,	0,	    0,		0 }
181};
182
183struct afswtch *afp;	/*the address family being set or asked about*/
184
185int
186main(argc, argv)
187	int argc;
188	char *argv[];
189{
190	register struct afswtch *rafp;
191	int aflag = 0;
192
193	if (argc < 2)
194		usage();
195	argc--, argv++;
196	if (!strcmp(*argv, "-a"))
197		aflag = 1;
198	else
199		strncpy(name, *argv, sizeof(name));
200	argc--, argv++;
201	if (argc > 0) {
202		for (afp = rafp = afs; rafp->af_name; rafp++)
203			if (strcmp(rafp->af_name, *argv) == 0) {
204				afp = rafp; argc--; argv++;
205				break;
206			}
207		rafp = afp;
208		af = ifr.ifr_addr.sa_family = rafp->af_af;
209	}
210	if (aflag) {
211		if (argc > 0)
212			usage();
213		printall();
214		exit(0);
215	}
216	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
217	if (getinfo(&ifr) < 0)
218		exit(1);
219	if (argc == 0) {
220		status();
221		exit(0);
222	}
223	while (argc > 0) {
224		register struct cmd *p;
225
226		for (p = cmds; p->c_name; p++)
227			if (strcmp(*argv, p->c_name) == 0)
228				break;
229		if (p->c_name == 0 && setaddr)
230			p++;	/* got src, do dst */
231		if (p->c_func) {
232			if (p->c_parameter == NEXTARG) {
233				if (argv[1] == NULL)
234					errx(1, "'%s' requires argument",
235					    p->c_name);
236				(*p->c_func)(argv[1]);
237				argc--, argv++;
238			} else
239				(*p->c_func)(*argv, p->c_parameter);
240		}
241		argc--, argv++;
242	}
243
244#ifndef INET_ONLY
245
246	if (af == AF_ISO)
247		adjust_nsellength();
248	if (setipdst && af==AF_NS) {
249		struct nsip_req rq;
250		int size = sizeof(rq);
251
252		rq.rq_ns = addreq.ifra_addr;
253		rq.rq_ip = addreq.ifra_dstaddr;
254
255		if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
256			warn("encapsulation routing");
257	}
258
259#endif	/* INET_ONLY */
260
261	if (clearaddr) {
262		int ret;
263		strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name);
264		if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) {
265			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
266				/* means no previous address for interface */
267			} else
268				warn("SIOCDIFADDR");
269		}
270	}
271	if (newaddr) {
272		strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
273		if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0)
274			warn("SIOCAIFADDR");
275	}
276	exit(0);
277}
278
279void
280getsock(naf)
281	int naf;
282{
283	static int oaf = -1;
284
285	if (oaf == naf)
286		return;
287	if (oaf != -1)
288		close(s);
289	s = socket(naf, SOCK_DGRAM, 0);
290	if (s < 0)
291		oaf = -1;
292	else
293		oaf = naf;
294}
295
296int
297getinfo(ifr)
298	struct ifreq *ifr;
299{
300
301	getsock(af);
302	if (s < 0)
303		err(1, "socket");
304	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
305		warn("SIOCGIFFLAGS");
306		return (-1);
307	}
308	flags = ifr->ifr_flags;
309	if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) {
310		warn("SIOCGIFMETRIC");
311		metric = 0;
312	} else
313		metric = ifr->ifr_metric;
314	return (0);
315}
316
317void
318printall()
319{
320	char inbuf[8192];
321	struct ifconf ifc;
322	struct ifreq ifreq, *ifr;
323	int i;
324
325	ifc.ifc_len = sizeof(inbuf);
326	ifc.ifc_buf = inbuf;
327	getsock(af);
328	if (s < 0)
329		err(1, "socket");
330	if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
331		err(1, "SIOCGIFCONF");
332	ifr = ifc.ifc_req;
333	ifreq.ifr_name[0] = '\0';
334	for (i = 0; i < ifc.ifc_len; ) {
335		ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
336		i += sizeof(ifr->ifr_name) +
337			(ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
338				? ifr->ifr_addr.sa_len
339				: sizeof(struct sockaddr));
340		if (!strncmp(ifreq.ifr_name, ifr->ifr_name,
341			     sizeof(ifr->ifr_name)))
342			continue;
343		strncpy(name, ifr->ifr_name, sizeof(ifr->ifr_name));
344		ifreq = *ifr;
345		if (getinfo(&ifreq) < 0)
346			continue;
347		status();
348	}
349}
350
351#define RIDADDR 0
352#define ADDR	1
353#define MASK	2
354#define DSTADDR	3
355
356/*ARGSUSED*/
357void
358setifaddr(addr, param)
359	char *addr;
360	int param;
361{
362	/*
363	 * Delay the ioctl to set the interface addr until flags are all set.
364	 * The address interpretation may depend on the flags,
365	 * and the flags may change when the address is set.
366	 */
367	setaddr++;
368	if (doalias == 0)
369		clearaddr = 1;
370	(*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
371}
372
373void
374setifnetmask(addr)
375	char *addr;
376{
377	(*afp->af_getaddr)(addr, MASK);
378}
379
380void
381setifbroadaddr(addr)
382	char *addr;
383{
384	(*afp->af_getaddr)(addr, DSTADDR);
385}
386
387void
388setifipdst(addr)
389	char *addr;
390{
391	in_getaddr(addr, DSTADDR);
392	setipdst++;
393	clearaddr = 0;
394	newaddr = 0;
395}
396
397#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
398/*ARGSUSED*/
399void
400notealias(addr, param)
401	char *addr;
402	int param;
403{
404	if (setaddr && doalias == 0 && param < 0)
405		memcpy(rqtosa(af_ridreq),
406		       rqtosa(af_addreq),
407		       rqtosa(af_addreq)->sa_len);
408	doalias = param;
409	if (param < 0) {
410		clearaddr = 1;
411		newaddr = 0;
412	} else
413		clearaddr = 0;
414}
415
416/*ARGSUSED*/
417void
418notrailers(vname, value)
419	char *vname;
420	int value;
421{
422	printf("Note: trailers are no longer sent, but always received\n");
423}
424
425/*ARGSUSED*/
426void
427setifdstaddr(addr, param)
428	char *addr;
429	int param;
430{
431	(*afp->af_getaddr)(addr, DSTADDR);
432}
433
434void
435setifflags(vname, value)
436	char *vname;
437	int value;
438{
439 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
440		err(1, "SIOCGIFFLAGS");
441	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
442 	flags = ifr.ifr_flags;
443
444	if (value < 0) {
445		value = -value;
446		flags &= ~value;
447	} else
448		flags |= value;
449	ifr.ifr_flags = flags;
450	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
451		err(1, "SIOCSIFFLAGS");
452}
453
454void
455setifmetric(val)
456	char *val;
457{
458	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
459	ifr.ifr_metric = atoi(val);
460	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
461		warn("SIOCSIFMETRIC");
462}
463
464#define	IFFBITS \
465"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
466\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
467
468/*
469 * Print the status of the interface.  If an address family was
470 * specified, show it and it only; otherwise, show them all.
471 */
472void
473status()
474{
475	register struct afswtch *p = afp;
476
477	printf("%s: ", name);
478	printb("flags", flags, IFFBITS);
479	if (metric)
480		printf(" metric %d", metric);
481	putchar('\n');
482	if ((p = afp) != NULL) {
483		(*p->af_status)(1);
484	} else for (p = afs; p->af_name; p++) {
485		ifr.ifr_addr.sa_family = p->af_af;
486		(*p->af_status)(0);
487	}
488}
489
490void
491in_status(force)
492	int force;
493{
494	struct sockaddr_in *sin;
495	char *inet_ntoa();
496
497	getsock(AF_INET);
498	if (s < 0) {
499		if (errno == EPROTONOSUPPORT)
500			return;
501		err(1, "socket");
502	}
503	memset(&ifr, 0, sizeof(ifr));
504	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
505	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
506		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
507			if (!force)
508				return;
509			memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
510		} else
511			warn("SIOCGIFADDR");
512	}
513	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
514	sin = (struct sockaddr_in *)&ifr.ifr_addr;
515	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
516	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
517	if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
518		if (errno != EADDRNOTAVAIL)
519			warn("SIOCGIFNETMASK");
520		memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
521	} else
522		netmask.sin_addr =
523		    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
524	if (flags & IFF_POINTOPOINT) {
525		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
526			if (errno == EADDRNOTAVAIL)
527			    memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
528			else
529			    warn("SIOCGIFDSTADDR");
530		}
531		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
532		sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
533		printf("--> %s ", inet_ntoa(sin->sin_addr));
534	}
535	printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
536	if (flags & IFF_BROADCAST) {
537		if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
538			if (errno == EADDRNOTAVAIL)
539			    memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
540			else
541			    warn("SIOCGIFBRDADDR");
542		}
543		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
544		sin = (struct sockaddr_in *)&ifr.ifr_addr;
545		if (sin->sin_addr.s_addr != 0)
546			printf("broadcast %s", inet_ntoa(sin->sin_addr));
547	}
548	putchar('\n');
549}
550
551#ifndef INET_ONLY
552
553void
554xns_status(force)
555	int force;
556{
557	struct sockaddr_ns *sns;
558
559	getsock(AF_NS);
560	if (s < 0) {
561		if (errno == EPROTONOSUPPORT)
562			return;
563		err(1, "socket");
564	}
565	memset(&ifr, 0, sizeof(ifr));
566	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
567	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
568		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
569			if (!force)
570				return;
571			memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
572		} else
573			warn("SIOCGIFADDR");
574	}
575	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
576	sns = (struct sockaddr_ns *)&ifr.ifr_addr;
577	printf("\tns %s ", ns_ntoa(sns->sns_addr));
578	if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
579		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
580			if (errno == EADDRNOTAVAIL)
581			    memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
582			else
583			    warn("SIOCGIFDSTADDR");
584		}
585		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
586		sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
587		printf("--> %s ", ns_ntoa(sns->sns_addr));
588	}
589	putchar('\n');
590}
591
592void
593iso_status(force)
594	int force;
595{
596	struct sockaddr_iso *siso;
597	struct iso_ifreq ifr;
598
599	getsock(AF_ISO);
600	if (s < 0) {
601		if (errno == EPROTONOSUPPORT)
602			return;
603		err(1, "socket");
604	}
605	memset(&ifr, 0, sizeof(ifr));
606	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
607	if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) {
608		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
609			if (!force)
610				return;
611			memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
612		} else
613			warn("SIOCGIFADDR_ISO");
614	}
615	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
616	siso = &ifr.ifr_Addr;
617	printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
618	if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) {
619		if (errno == EADDRNOTAVAIL)
620			memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
621		else
622			warn("SIOCGIFNETMASK_ISO");
623	} else {
624		printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
625	}
626	if (flags & IFF_POINTOPOINT) {
627		if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) {
628			if (errno == EADDRNOTAVAIL)
629			    memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
630			else
631			    warn("SIOCGIFDSTADDR_ISO");
632		}
633		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
634		siso = &ifr.ifr_Addr;
635		printf("--> %s ", iso_ntoa(&siso->siso_addr));
636	}
637	putchar('\n');
638}
639
640#endif	/* INET_ONLY */
641
642struct	in_addr inet_makeaddr();
643
644#define SIN(x) ((struct sockaddr_in *) &(x))
645struct sockaddr_in *sintab[] = {
646SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
647SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
648
649void
650in_getaddr(s, which)
651	char *s;
652	int which;
653{
654	register struct sockaddr_in *sin = sintab[which];
655	struct hostent *hp;
656	struct netent *np;
657
658	sin->sin_len = sizeof(*sin);
659	if (which != MASK)
660		sin->sin_family = AF_INET;
661
662	if (inet_aton(s, &sin->sin_addr) == 0) {
663		if (hp = gethostbyname(s))
664			memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
665		else if (np = getnetbyname(s))
666			sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
667		else
668			errx(1, "%s: bad value", s);
669	}
670}
671
672/*
673 * Print a value a la the %b format of the kernel's printf
674 */
675void
676printb(s, v, bits)
677	char *s;
678	register char *bits;
679	register unsigned short v;
680{
681	register int i, any = 0;
682	register char c;
683
684	if (bits && *bits == 8)
685		printf("%s=%o", s, v);
686	else
687		printf("%s=%x", s, v);
688	bits++;
689	if (bits) {
690		putchar('<');
691		while (i = *bits++) {
692			if (v & (1 << (i-1))) {
693				if (any)
694					putchar(',');
695				any = 1;
696				for (; (c = *bits) > 32; bits++)
697					putchar(c);
698			} else
699				for (; *bits > 32; bits++)
700					;
701		}
702		putchar('>');
703	}
704}
705
706#ifndef INET_ONLY
707
708#define SNS(x) ((struct sockaddr_ns *) &(x))
709struct sockaddr_ns *snstab[] = {
710SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
711SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
712
713void
714xns_getaddr(addr, which)
715	char *addr;
716	int which;
717{
718	struct sockaddr_ns *sns = snstab[which];
719	struct ns_addr ns_addr();
720
721	sns->sns_family = AF_NS;
722	sns->sns_len = sizeof(*sns);
723	sns->sns_addr = ns_addr(addr);
724	if (which == MASK)
725		printf("Attempt to set XNS netmask will be ineffectual\n");
726}
727
728#define SISO(x) ((struct sockaddr_iso *) &(x))
729struct sockaddr_iso *sisotab[] = {
730SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
731SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
732
733void
734iso_getaddr(addr, which)
735	char *addr;
736	int which;
737{
738	register struct sockaddr_iso *siso = sisotab[which];
739	struct iso_addr *iso_addr();
740	siso->siso_addr = *iso_addr(addr);
741
742	if (which == MASK) {
743		siso->siso_len = TSEL(siso) - (caddr_t)(siso);
744		siso->siso_nlen = 0;
745	} else {
746		siso->siso_len = sizeof(*siso);
747		siso->siso_family = AF_ISO;
748	}
749}
750
751void
752setsnpaoffset(val)
753	char *val;
754{
755	iso_addreq.ifra_snpaoffset = atoi(val);
756}
757
758void
759setnsellength(val)
760	char *val;
761{
762	nsellength = atoi(val);
763	if (nsellength < 0)
764		errx(1, "Negative NSEL length is absurd");
765	if (afp == 0 || afp->af_af != AF_ISO)
766		errx(1, "Setting NSEL length valid only for iso");
767}
768
769void
770fixnsel(s)
771	register struct sockaddr_iso *s;
772{
773	if (s->siso_family == 0)
774		return;
775	s->siso_tlen = nsellength;
776}
777
778void
779adjust_nsellength()
780{
781	fixnsel(sisotab[RIDADDR]);
782	fixnsel(sisotab[ADDR]);
783	fixnsel(sisotab[DSTADDR]);
784}
785
786#endif	/* INET_ONLY */
787
788void
789usage()
790{
791	fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s",
792		"\t[ af [ address [ dest_addr ] ] [ up ] [ down ] ",
793		"[ netmask mask ] ]\n",
794		"\t[ metric n ]\n",
795		"\t[ arp | -arp ]\n",
796		"\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n",
797		"       ifconfig -a [ af ]\n");
798	exit(1);
799}
800