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