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