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