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