xref: /freebsd/sbin/ifconfig/ifconfig.c (revision 8e6b01171e30297084bb0b4457c4183c2746aacc)
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
35 static 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 static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
42 #endif /* not lint */
43 
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 
48 #include <net/if.h>
49 #include <net/if_dl.h>
50 #include <netinet/in.h>
51 #include <netinet/in_var.h>
52 #include <arpa/inet.h>
53 #include <netdb.h>
54 
55 #define	IPXIP
56 #define IPTUNNEL
57 #include <netipx/ipx.h>
58 #include <netipx/ipx_if.h>
59 
60 #define	NSIP
61 #include <netns/ns.h>
62 #include <netns/ns_if.h>
63 
64 #define EON
65 #include <netiso/iso.h>
66 #include <netiso/iso_var.h>
67 #include <sys/protosw.h>
68 
69 #include <ctype.h>
70 #include <err.h>
71 #include <errno.h>
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75 #include <unistd.h>
76 #include <nlist.h>
77 #include <kvm.h>
78 #include <fcntl.h>
79 
80 struct	ifreq		ifr, ridreq;
81 struct	ifaliasreq	addreq;
82 struct	iso_ifreq	iso_ridreq;
83 struct	iso_aliasreq	iso_addreq;
84 struct	sockaddr_in	netmask;
85 
86 char	name[30];
87 int	flags;
88 int	metric;
89 int	mtu;
90 int	nsellength = 1;
91 int	setaddr;
92 int	setipdst;
93 int	doalias;
94 int	clearaddr;
95 int	newaddr = 1;
96 int	s;
97 kvm_t	*kvmd;
98 extern	int errno;
99 
100 int	setifflags(), setifaddr(), setifdstaddr(), setifnetmask();
101 int	setifmetric(), setifmtu(), setifbroadaddr(), setifipdst();
102 int	notealias(), setsnpaoffset(), setnsellength(), notrailers();
103 
104 #define	NEXTARG		0xffffff
105 
106 struct	cmd {
107 	char	*c_name;
108 	int	c_parameter;		/* NEXTARG means next argv */
109 	int	(*c_func)();
110 } cmds[] = {
111 	{ "up",		IFF_UP,		setifflags } ,
112 	{ "down",	-IFF_UP,	setifflags },
113 	{ "trailers",	-1,		notrailers },
114 	{ "-trailers",	1,		notrailers },
115 	{ "arp",	-IFF_NOARP,	setifflags },
116 	{ "-arp",	IFF_NOARP,	setifflags },
117 	{ "debug",	IFF_DEBUG,	setifflags },
118 	{ "-debug",	-IFF_DEBUG,	setifflags },
119 	{ "alias",	IFF_UP,		notealias },
120 	{ "-alias",	-IFF_UP,	notealias },
121 	{ "delete",	-IFF_UP,	notealias },
122 #ifdef notdef
123 #define	EN_SWABIPS	0x1000
124 	{ "swabips",	EN_SWABIPS,	setifflags },
125 	{ "-swabips",	-EN_SWABIPS,	setifflags },
126 #endif
127 	{ "netmask",	NEXTARG,	setifnetmask },
128 	{ "metric",	NEXTARG,	setifmetric },
129 	{ "broadcast",	NEXTARG,	setifbroadaddr },
130 	{ "ipdst",	NEXTARG,	setifipdst },
131 	{ "snpaoffset",	NEXTARG,	setsnpaoffset },
132 	{ "nsellength",	NEXTARG,	setnsellength },
133 	{ "link0",	IFF_LINK0,	setifflags },
134 	{ "-link0",	-IFF_LINK0,	setifflags },
135 	{ "link1",	IFF_LINK1,	setifflags },
136 	{ "-link1",	-IFF_LINK1,	setifflags },
137 	{ "link2",	IFF_LINK2,	setifflags },
138 	{ "-link2",	-IFF_LINK2,	setifflags },
139 	{ "normal",	-IFF_LINK0,	setifflags },
140 	{ "compress",	IFF_LINK0,	setifflags },
141 	{ "noicmp",	IFF_LINK1,	setifflags },
142 	{ "mtu",	NEXTARG,	setifmtu },
143 	{ 0,		0,		setifaddr },
144 	{ 0,		0,		setifdstaddr },
145 };
146 
147 /*
148  * XNS support liberally adapted from code written at the University of
149  * Maryland principally by James O'Toole and Chris Torek.
150  */
151 int	in_status(), in_getaddr();
152 int	ipx_status(), ipx_getaddr();
153 int	xns_status(), xns_getaddr();
154 int	iso_status(), iso_getaddr();
155 int	ether_status();
156 
157 /* Known address families */
158 struct afswtch {
159 	char *af_name;
160 	short af_af;
161 	int (*af_status)();
162 	int (*af_getaddr)();
163 	int af_difaddr;
164 	int af_aifaddr;
165 	caddr_t af_ridreq;
166 	caddr_t af_addreq;
167 } afs[] = {
168 #define C(x) ((caddr_t) &x)
169 	{ "inet", AF_INET, in_status, in_getaddr,
170 	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
171 	{ "ipx", AF_IPX, ipx_status, ipx_getaddr,
172 	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
173 	{ "ns", AF_NS, xns_status, xns_getaddr,
174 	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
175 	{ "iso", AF_ISO, iso_status, iso_getaddr,
176 	     SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
177 	{ "ether", AF_INET, ether_status, NULL },
178 	{ 0,	0,	    0,		0 }
179 };
180 
181 struct afswtch *afp;	/*the address family being set or asked about*/
182 
183 main(argc, argv)
184 	int argc;
185 	char *argv[];
186 {
187 	int af = AF_INET;
188 	register struct afswtch *rafp;
189 
190 	if (argc < 2) {
191 		fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s",
192 		    "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]",
193 			    "[ netmask mask ] ]\n",
194 		    "\t[ metric n ]\n",
195 		    "\t[ mtu n ]\n",
196 		    "\t[ arp | -arp ]\n",
197 		    "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n");
198 		exit(1);
199 	}
200 	argc--, argv++;
201 	strncpy(name, *argv, sizeof(name));
202 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
203 	argc--, argv++;
204 	if (argc > 0) {
205 		for (afp = rafp = afs; rafp->af_name; rafp++)
206 			if (strcmp(rafp->af_name, *argv) == 0) {
207 				afp = rafp; argc--; argv++;
208 				break;
209 			}
210 		rafp = afp;
211 		af = ifr.ifr_addr.sa_family = rafp->af_af;
212 	}
213 	s = socket(af, SOCK_DGRAM, 0);
214 	if (s < 0) {
215 		perror("ifconfig: socket");
216 		exit(1);
217 	}
218 	if (strstr(name, "-a")) {
219 		struct ifconf ifc;
220 #define MAX_INTERFACES 50	/* Yeah right. */
221 		char buffer[MAX_INTERFACES * sizeof(struct ifreq)];
222 		struct ifreq *ifptr, *end;
223 		int ifflags, selectflag = -1;
224 
225 		if (strstr(name, "-au"))
226 			selectflag = 1;
227 		if (strstr(name, "-ad"))
228 			selectflag = 0;
229 		ifc.ifc_len = sizeof(buffer);
230 		ifc.ifc_buf = buffer;
231 		if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
232 			perror("ifconfig (SIOCGIFCONF)");
233 			exit (1);
234 		}
235 		ifflags = ifc.ifc_req->ifr_flags;
236 		end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
237 		ifptr = ifc.ifc_req;
238 		while (ifptr < end) {
239 			sprintf(ifr.ifr_name,"%s",ifptr->ifr_name);
240 			sprintf(name,"%s",ifptr->ifr_name);
241 			close(s);
242 			if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
243 				perror("ifconfig: socket");
244 				exit(1);
245 			}
246 			if (ifptr->ifr_flags == ifflags)
247 				ifconfig(argc,argv,af,rafp,selectflag);
248 			if(ifptr->ifr_addr.sa_len)	/* Dohw! */
249 				ifptr = (struct ifreq *) ((caddr_t) ifptr +
250 				ifptr->ifr_addr.sa_len -
251 				sizeof(struct sockaddr));
252 			ifptr++;
253 		}
254 	} else
255 		ifconfig(argc,argv,af,rafp, -1);
256 
257 	exit (0);
258 }
259 
260 
261 
262 ifconfig(argc,argv,af,rafp,flag)
263 	int argc;
264 	char *argv[];
265 	int af;
266 	struct afswtch *rafp;
267 	int flag;
268 {
269 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
270 		Perror("ioctl (SIOCGIFFLAGS)");
271 		exit(1);
272 	}
273 
274 	switch(flag) {
275 	case 0:
276 		if (ifr.ifr_flags & IFF_UP)
277 			return(0);
278 		break;
279 	case 1:
280 		if (!(ifr.ifr_flags & IFF_UP))
281 			return(0);
282 		break;
283 	case -1:
284 	default:
285 		break;
286 	}
287 
288 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
289 	flags = ifr.ifr_flags;
290 	if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
291 		perror("ioctl (SIOCGIFMETRIC)");
292 	else
293 		metric = ifr.ifr_metric;
294 	if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
295 		perror("ioctl (SIOCGIFMTU)");
296 	else
297 		mtu = ifr.ifr_mtu;
298 	if (argc == 0) {
299 		status();
300 		return(0);
301 	}
302 	while (argc > 0) {
303 		register struct cmd *p;
304 
305 		for (p = cmds; p->c_name; p++)
306 			if (strcmp(*argv, p->c_name) == 0)
307 				break;
308 		if (p->c_name == 0 && setaddr)
309 			p++;	/* got src, do dst */
310 		if (p->c_func) {
311 			if (p->c_parameter == NEXTARG) {
312 				if (argv[1] == NULL)
313 					errx(1, "'%s' requires argument",
314 					    p->c_name);
315 				(*p->c_func)(argv[1]);
316 				argc--, argv++;
317 			} else
318 				(*p->c_func)(*argv, p->c_parameter);
319 		}
320 		argc--, argv++;
321 	}
322 	if (af == AF_ISO)
323 		adjust_nsellength();
324 	if (setipdst && af==AF_IPX) {
325 		struct ipxip_req rq;
326 		int size = sizeof(rq);
327 
328 		rq.rq_ipx = addreq.ifra_addr;
329 		rq.rq_ip = addreq.ifra_dstaddr;
330 
331 		if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0)
332 			Perror("Encapsulation Routing");
333 	}
334 	if (setipdst && af==AF_NS) {
335 		struct nsip_req rq;
336 		int size = sizeof(rq);
337 
338 		rq.rq_ns = addreq.ifra_addr;
339 		rq.rq_ip = addreq.ifra_dstaddr;
340 
341 		if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
342 			Perror("Encapsulation Routing");
343 	}
344 	if (clearaddr) {
345 		int ret;
346 		strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name);
347 		if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) {
348 			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
349 				/* means no previous address for interface */
350 			} else
351 				Perror("ioctl (SIOCDIFADDR)");
352 		}
353 	}
354 	if (newaddr) {
355 		strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
356 		if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0)
357 			Perror("ioctl (SIOCAIFADDR)");
358 	}
359 	return(0);
360 }
361 #define RIDADDR 0
362 #define ADDR	1
363 #define MASK	2
364 #define DSTADDR	3
365 
366 /*ARGSUSED*/
367 setifaddr(addr, param)
368 	char *addr;
369 	short param;
370 {
371 	/*
372 	 * Delay the ioctl to set the interface addr until flags are all set.
373 	 * The address interpretation may depend on the flags,
374 	 * and the flags may change when the address is set.
375 	 */
376 	setaddr++;
377 	if (doalias == 0)
378 		clearaddr = 1;
379 	(*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
380 }
381 
382 setifnetmask(addr)
383 	char *addr;
384 {
385 	(*afp->af_getaddr)(addr, MASK);
386 }
387 
388 setifbroadaddr(addr)
389 	char *addr;
390 {
391 	(*afp->af_getaddr)(addr, DSTADDR);
392 }
393 
394 setifipdst(addr)
395 	char *addr;
396 {
397 	in_getaddr(addr, DSTADDR);
398 	setipdst++;
399 	clearaddr = 0;
400 	newaddr = 0;
401 }
402 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
403 /*ARGSUSED*/
404 notealias(addr, param)
405 	char *addr;
406 {
407 	if (setaddr && doalias == 0 && param < 0)
408 		bcopy((caddr_t)rqtosa(af_addreq),
409 		      (caddr_t)rqtosa(af_ridreq),
410 		      rqtosa(af_addreq)->sa_len);
411 	doalias = param;
412 	if (param < 0) {
413 		clearaddr = 1;
414 		newaddr = 0;
415 	} else
416 		clearaddr = 0;
417 }
418 
419 /*ARGSUSED*/
420 notrailers(vname, value)
421 	char *vname;
422 	int value;
423 {
424 	printf("Note: trailers are no longer sent, but always received\n");
425 }
426 
427 /*ARGSUSED*/
428 setifdstaddr(addr, param)
429 	char *addr;
430 	int param;
431 {
432 	(*afp->af_getaddr)(addr, DSTADDR);
433 }
434 
435 setifflags(vname, value)
436 	char *vname;
437 	short value;
438 {
439  	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
440  		Perror("ioctl (SIOCGIFFLAGS)");
441  		exit(1);
442  	}
443 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
444  	flags = ifr.ifr_flags;
445 
446 	if (value < 0) {
447 		value = -value;
448 		flags &= ~value;
449 	} else
450 		flags |= value;
451 	ifr.ifr_flags = flags;
452 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
453 		Perror(vname);
454 }
455 
456 setifmetric(val)
457 	char *val;
458 {
459 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
460 	ifr.ifr_metric = atoi(val);
461 	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
462 		perror("ioctl (set metric)");
463 }
464 
465 setifmtu(val)
466 	char *val;
467 {
468 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
469 	ifr.ifr_mtu = atoi(val);
470 	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
471 		perror("ioctl (set mtu)");
472 }
473 
474 setsnpaoffset(val)
475 	char *val;
476 {
477 	iso_addreq.ifra_snpaoffset = atoi(val);
478 }
479 
480 #define	IFFBITS \
481 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
482 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
483 
484 /*
485  * Print the status of the interface.  If an address family was
486  * specified, show it and it only; otherwise, show them all.
487  */
488 status()
489 {
490 	register struct afswtch *p = afp;
491 	short af = ifr.ifr_addr.sa_family;
492 
493 	printf("%s: ", name);
494 	printb("flags", flags, IFFBITS);
495 	if (metric)
496 		printf(" metric %d", metric);
497 	if (mtu)
498 		printf(" mtu %d", mtu);
499 	putchar('\n');
500 	if ((p = afp) != NULL) {
501 		(*p->af_status)(1);
502 	} else for (p = afs; p->af_name; p++) {
503 		ifr.ifr_addr.sa_family = p->af_af;
504 		(*p->af_status)(0);
505 	}
506 }
507 
508 in_status(force)
509 	int force;
510 {
511 	struct sockaddr_in *sin;
512 	char *inet_ntoa();
513 
514 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
515 	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
516 		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
517 			if (!force)
518 				return;
519 			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
520 		} else
521 			perror("ioctl (SIOCGIFADDR)");
522 	}
523 	sin = (struct sockaddr_in *)&ifr.ifr_addr;
524 	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
525 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
526 	if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
527 		if (errno != EADDRNOTAVAIL)
528 			perror("ioctl (SIOCGIFNETMASK)");
529 		bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
530 	} else
531 		netmask.sin_addr =
532 		    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
533 	if (flags & IFF_POINTOPOINT) {
534 		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
535 			if (errno == EADDRNOTAVAIL)
536 			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
537 			else
538 			    perror("ioctl (SIOCGIFDSTADDR)");
539 		}
540 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
541 		sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
542 		printf("--> %s ", inet_ntoa(sin->sin_addr));
543 	}
544 	printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
545 	if (flags & IFF_BROADCAST) {
546 		if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
547 			if (errno == EADDRNOTAVAIL)
548 			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
549 			else
550 			    perror("ioctl (SIOCGIFADDR)");
551 		}
552 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
553 		sin = (struct sockaddr_in *)&ifr.ifr_addr;
554 		if (sin->sin_addr.s_addr != 0)
555 			printf("broadcast %s", inet_ntoa(sin->sin_addr));
556 	}
557 	putchar('\n');
558 }
559 
560 ipx_status(force)
561 	int force;
562 {
563 	struct sockaddr_ipx *sipx;
564 
565 	close(s);
566 	s = socket(AF_IPX, SOCK_DGRAM, 0);
567 	if (s < 0) {
568 		if (errno == EPROTONOSUPPORT)
569 			return;
570 		perror("ifconfig: socket");
571 		exit(1);
572 	}
573 	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
574 		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
575 			if (!force)
576 				return;
577 			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
578 		} else
579 			perror("ioctl (SIOCGIFADDR)");
580 	}
581 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
582 	sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
583 	printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr));
584 	if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
585 		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
586 			if (errno == EADDRNOTAVAIL)
587 			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
588 			else
589 			    Perror("ioctl (SIOCGIFDSTADDR)");
590 		}
591 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
592 		sipx = (struct sockaddr_ipx *)&ifr.ifr_dstaddr;
593 		printf("--> %s ", ipx_ntoa(sipx->sipx_addr));
594 	}
595 	putchar('\n');
596 }
597 
598 xns_status(force)
599 	int force;
600 {
601 	struct sockaddr_ns *sns;
602 
603 	close(s);
604 	s = socket(AF_NS, SOCK_DGRAM, 0);
605 	if (s < 0) {
606 		if (errno == EPROTONOSUPPORT)
607 			return;
608 		perror("ifconfig: socket");
609 		exit(1);
610 	}
611 	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
612 		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
613 			if (!force)
614 				return;
615 			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
616 		} else
617 			perror("ioctl (SIOCGIFADDR)");
618 	}
619 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
620 	sns = (struct sockaddr_ns *)&ifr.ifr_addr;
621 	printf("\tns %s ", ns_ntoa(sns->sns_addr));
622 	if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
623 		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
624 			if (errno == EADDRNOTAVAIL)
625 			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
626 			else
627 			    Perror("ioctl (SIOCGIFDSTADDR)");
628 		}
629 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
630 		sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
631 		printf("--> %s ", ns_ntoa(sns->sns_addr));
632 	}
633 	putchar('\n');
634 }
635 
636 iso_status(force)
637 	int force;
638 {
639 	struct sockaddr_iso *siso;
640 	struct iso_ifreq ifr;
641 
642 	close(s);
643 	s = socket(AF_ISO, SOCK_DGRAM, 0);
644 	if (s < 0) {
645 		if (errno == EPROTONOSUPPORT)
646 			return;
647 		perror("ifconfig: socket");
648 		exit(1);
649 	}
650 	bzero((caddr_t)&ifr, sizeof(ifr));
651 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
652 	if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) {
653 		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
654 			if (!force)
655 				return;
656 			bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr));
657 		} else {
658 			perror("ioctl (SIOCGIFADDR_ISO)");
659 			exit(1);
660 		}
661 	}
662 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
663 	siso = &ifr.ifr_Addr;
664 	printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
665 	if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) {
666 		if (errno != EADDRNOTAVAIL)
667 			perror("ioctl (SIOCGIFNETMASK_ISO)");
668 	} else {
669 		printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
670 	}
671 	if (flags & IFF_POINTOPOINT) {
672 		if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) {
673 			if (errno == EADDRNOTAVAIL)
674 			    bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr));
675 			else
676 			    Perror("ioctl (SIOCGIFDSTADDR_ISO)");
677 		}
678 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
679 		siso = &ifr.ifr_Addr;
680 		printf("--> %s ", iso_ntoa(&siso->siso_addr));
681 	}
682 	putchar('\n');
683 }
684 
685 kread(addr, buf, size)
686         u_long addr;
687         char *buf;
688         int size;
689 {
690 
691         if (kvm_read(kvmd, addr, buf, size) != size)
692                 return (-1);
693         return (0);
694 }
695 
696 /* Unashamedly stolen from netstat -- maybe someday we can us sysctl() */
697 ether_status()
698 {
699 	struct nlist nl[] = { { "_ifnet" } , "" };
700 	u_long addr, addr2;
701 	struct ifnet ifnet;
702 	union {
703 		struct ifaddr ifa;
704 		struct in_ifaddr in;
705 		struct ns_ifaddr ns;
706 		struct iso_ifaddr iso;
707 	} ifaddr;
708 	char *cp;
709 	struct sockaddr *sa;
710 	struct sockaddr_dl *sdl;
711 	int n,m;
712 	char ifacename[IFNAMSIZ];
713 
714 	/*
715 	 * If we fail here it probably means we don't have permission to
716 	 * read /dev/kmem. Best to just silently bail out. If we have
717 	 * an error *after* we succeed in opening /dev/kmem, then we
718 	 * should report it.
719 	 */
720 	if ((kvmd = kvm_open(NULL,NULL,NULL,O_RDONLY,NULL)) == NULL)
721 		return;
722 	if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
723 		perror("ifconfig: kvm_nlist()");
724 		return;
725 	}
726 	if (kread(nl[0].n_value, (char *)&addr, sizeof(addr))) {
727 		perror("_ifnet");
728 		return;
729 	}
730 	addr2 = 0;
731 	while (addr || addr2) {
732 		if (addr2 == 0) {
733                         if (kread(addr, (char *)&ifnet, sizeof ifnet) ||
734                            kread((u_long)ifnet.if_name, ifacename, IFNAMSIZ)){
735 					perror("ifconfig: kvm_read()");
736 					return;
737 			}
738 			addr = (u_long)ifnet.if_next;
739 			addr2 = (u_long)ifnet.if_addrlist;
740 		}
741 		if (kread(addr2, (char *)&ifaddr, sizeof ifaddr)) {
742 			addr2 = 0;
743                         continue;
744                 }
745 		sprintf(ifacename,"%s%d",ifacename, ifnet.if_unit);
746 		if (!strncmp(name, ifacename, strlen(name))) {
747 #define CP(x) ((char *)(x))
748 			cp = (CP(ifaddr.ifa.ifa_addr) - CP(addr2)) +
749 				CP(&ifaddr); sa = (struct sockaddr *)cp;
750 			if (sa->sa_family == AF_LINK) {
751 				sdl = (struct sockaddr_dl *)sa;
752 				cp = (char *)LLADDR(sdl);
753 				if ((n = sdl->sdl_alen) > 0) {
754 					printf ("\tether ");
755                                		while (--n >= 0)
756 						m += printf("%02x%c",
757 							*cp++ & 0xff,
758 							n > 0 ? ':' : ' ');
759 					putchar('\n');
760 				}
761 				break;
762 			}
763 		}
764 		addr2 = (u_long)ifaddr.ifa.ifa_next;
765 	}
766 	kvm_close(kvmd);
767 }
768 
769 Perror(cmd)
770 	char *cmd;
771 {
772 	extern int errno;
773 
774 	switch (errno) {
775 
776 	case ENXIO:
777 		errx(1, "%s: no such interface", cmd);
778 		break;
779 
780 	case EPERM:
781 		errx(1, "%s: permission denied", cmd);
782 		break;
783 
784 	default:
785 		err(1, "%s", cmd);
786 	}
787 }
788 
789 struct	in_addr inet_makeaddr();
790 
791 #define SIN(x) ((struct sockaddr_in *) &(x))
792 struct sockaddr_in *sintab[] = {
793 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
794 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
795 
796 in_getaddr(s, which)
797 	char *s;
798 {
799 	register struct sockaddr_in *sin = sintab[which];
800 	struct hostent *hp;
801 	struct netent *np;
802 	int val;
803 
804 	sin->sin_len = sizeof(*sin);
805 	if (which != MASK)
806 		sin->sin_family = AF_INET;
807 
808 	if (inet_aton(s, &sin->sin_addr))
809 		;
810 	else if (hp = gethostbyname(s))
811 		bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
812 	else if (np = getnetbyname(s))
813 		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
814 	else
815 		errx(1, "%s: bad value", s);
816 }
817 
818 /*
819  * Print a value a la the %b format of the kernel's printf
820  */
821 printb(s, v, bits)
822 	char *s;
823 	register char *bits;
824 	register unsigned short v;
825 {
826 	register int i, any = 0;
827 	register char c;
828 
829 	if (bits && *bits == 8)
830 		printf("%s=%o", s, v);
831 	else
832 		printf("%s=%x", s, v);
833 	bits++;
834 	if (bits) {
835 		putchar('<');
836 		while (i = *bits++) {
837 			if (v & (1 << (i-1))) {
838 				if (any)
839 					putchar(',');
840 				any = 1;
841 				for (; (c = *bits) > 32; bits++)
842 					putchar(c);
843 			} else
844 				for (; *bits > 32; bits++)
845 					;
846 		}
847 		putchar('>');
848 	}
849 }
850 
851 #define SIPX(x) ((struct sockaddr_ipx *) &(x))
852 struct sockaddr_ipx *sipxtab[] = {
853 SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr),
854 SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)};
855 
856 ipx_getaddr(addr, which)
857 char *addr;
858 {
859 	struct sockaddr_ipx *sipx = sipxtab[which];
860 	struct ipx_addr ipx_addr();
861 
862 	sipx->sipx_family = AF_IPX;
863 	sipx->sipx_len = sizeof(*sipx);
864 	sipx->sipx_addr = ipx_addr(addr);
865 	if (which == MASK)
866 		printf("Attempt to set IPX netmask will be ineffectual\n");
867 }
868 
869 #define SNS(x) ((struct sockaddr_ns *) &(x))
870 struct sockaddr_ns *snstab[] = {
871 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
872 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
873 
874 xns_getaddr(addr, which)
875 char *addr;
876 {
877 	struct sockaddr_ns *sns = snstab[which];
878 	struct ns_addr ns_addr();
879 
880 	sns->sns_family = AF_NS;
881 	sns->sns_len = sizeof(*sns);
882 	sns->sns_addr = ns_addr(addr);
883 	if (which == MASK)
884 		printf("Attempt to set XNS netmask will be ineffectual\n");
885 }
886 
887 #define SISO(x) ((struct sockaddr_iso *) &(x))
888 struct sockaddr_iso *sisotab[] = {
889 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
890 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
891 
892 iso_getaddr(addr, which)
893 char *addr;
894 {
895 	register struct sockaddr_iso *siso = sisotab[which];
896 	struct iso_addr *iso_addr();
897 	siso->siso_addr = *iso_addr(addr);
898 
899 	if (which == MASK) {
900 		siso->siso_len = TSEL(siso) - (caddr_t)(siso);
901 		siso->siso_nlen = 0;
902 	} else {
903 		siso->siso_len = sizeof(*siso);
904 		siso->siso_family = AF_ISO;
905 	}
906 }
907 
908 setnsellength(val)
909 	char *val;
910 {
911 	nsellength = atoi(val);
912 	if (nsellength < 0)
913 		errx(1, "Negative NSEL length is absurd");
914 	if (afp == 0 || afp->af_af != AF_ISO)
915 		errx(1, "Setting NSEL length valid only for iso");
916 }
917 
918 fixnsel(s)
919 register struct sockaddr_iso *s;
920 {
921 	if (s->siso_family == 0)
922 		return;
923 	s->siso_tlen = nsellength;
924 }
925 
926 adjust_nsellength()
927 {
928 	fixnsel(sisotab[RIDADDR]);
929 	fixnsel(sisotab[ADDR]);
930 	fixnsel(sisotab[DSTADDR]);
931 }
932