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