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 /* 35 * 951109 - Andrew@pubnix.net - Changed to iterative buffer growing mechanism 36 * for ifconfig -a so all interfaces are queried. 37 * 38 * 960101 - peter@freebsd.org - Blow away the SIOCGIFCONF code and use 39 * sysctl() to get the structured interface conf 40 * and parse the messages in there. REALLY UGLY! 41 */ 42 #ifndef lint 43 static char copyright[] = 44 "@(#) Copyright (c) 1983, 1993\n\ 45 The Regents of the University of California. All rights reserved.\n"; 46 #endif /* not lint */ 47 48 #ifndef lint 49 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 50 #endif /* not lint */ 51 52 #include <sys/param.h> 53 #include <sys/socket.h> 54 #include <sys/ioctl.h> 55 #include <sys/sysctl.h> 56 57 #include <net/if.h> 58 #include <net/if_dl.h> 59 #include <net/if_types.h> 60 #include <net/route.h> 61 #include <netinet/in.h> 62 #include <netinet/in_var.h> 63 #include <arpa/inet.h> 64 #include <netdb.h> 65 66 #define IPXIP 67 #define IPTUNNEL 68 #include <netipx/ipx.h> 69 #include <netipx/ipx_if.h> 70 71 #ifdef NS 72 #define NSIP 73 #include <netns/ns.h> 74 #include <netns/ns_if.h> 75 #endif 76 77 #ifdef ISO 78 #define EON 79 #include <netiso/iso.h> 80 #include <netiso/iso_var.h> 81 #endif 82 #include <sys/protosw.h> 83 84 #include <ctype.h> 85 #include <err.h> 86 #include <errno.h> 87 #include <stdio.h> 88 #include <stdlib.h> 89 #include <string.h> 90 #include <unistd.h> 91 #include <nlist.h> 92 #include <kvm.h> 93 #include <fcntl.h> 94 95 struct ifreq ifr, ridreq; 96 struct ifaliasreq addreq; 97 #ifdef ISO 98 struct iso_ifreq iso_ridreq; 99 struct iso_aliasreq iso_addreq; 100 #endif 101 struct sockaddr_in netmask; 102 103 char name[32]; 104 int flags; 105 int metric; 106 int mtu; 107 #ifdef ISO 108 int nsellength = 1; 109 #endif 110 int setaddr; 111 int setipdst; 112 int doalias; 113 int clearaddr; 114 int newaddr = 1; 115 int s; 116 kvm_t *kvmd; 117 extern int errno; 118 119 int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 120 int setifmetric(), setifmtu(), setifbroadaddr(), setifipdst(); 121 int notealias(); 122 #ifdef ISO 123 int setsnpaoffset(), setnsellength(); 124 #endif 125 int notrailers(); 126 127 #define NEXTARG 0xffffff 128 129 struct cmd { 130 char *c_name; 131 int c_parameter; /* NEXTARG means next argv */ 132 int (*c_func)(); 133 } cmds[] = { 134 { "up", IFF_UP, setifflags } , 135 { "down", -IFF_UP, setifflags }, 136 { "trailers", -1, notrailers }, 137 { "-trailers", 1, notrailers }, 138 { "arp", -IFF_NOARP, setifflags }, 139 { "-arp", IFF_NOARP, setifflags }, 140 { "debug", IFF_DEBUG, setifflags }, 141 { "-debug", -IFF_DEBUG, setifflags }, 142 { "alias", IFF_UP, notealias }, 143 { "-alias", -IFF_UP, notealias }, 144 { "delete", -IFF_UP, notealias }, 145 #ifdef notdef 146 #define EN_SWABIPS 0x1000 147 { "swabips", EN_SWABIPS, setifflags }, 148 { "-swabips", -EN_SWABIPS, setifflags }, 149 #endif 150 { "netmask", NEXTARG, setifnetmask }, 151 { "metric", NEXTARG, setifmetric }, 152 { "broadcast", NEXTARG, setifbroadaddr }, 153 { "ipdst", NEXTARG, setifipdst }, 154 #ifdef ISO 155 { "snpaoffset", NEXTARG, setsnpaoffset }, 156 { "nsellength", NEXTARG, setnsellength }, 157 #endif 158 { "link0", IFF_LINK0, setifflags }, 159 { "-link0", -IFF_LINK0, setifflags }, 160 { "link1", IFF_LINK1, setifflags }, 161 { "-link1", -IFF_LINK1, setifflags }, 162 { "link2", IFF_LINK2, setifflags }, 163 { "-link2", -IFF_LINK2, setifflags }, 164 { "normal", -IFF_LINK0, setifflags }, 165 { "compress", IFF_LINK0, setifflags }, 166 { "noicmp", IFF_LINK1, setifflags }, 167 { "mtu", NEXTARG, setifmtu }, 168 { 0, 0, setifaddr }, 169 { 0, 0, setifdstaddr }, 170 }; 171 172 /* 173 * XNS support liberally adapted from code written at the University of 174 * Maryland principally by James O'Toole and Chris Torek. 175 */ 176 int in_status(), in_getaddr(); 177 int ipx_status(), ipx_getaddr(); 178 #ifdef NS 179 int xns_status(), xns_getaddr(); 180 #endif 181 #ifdef ISO 182 int iso_status(), iso_getaddr(); 183 #endif 184 int ether_status(); 185 186 /* Known address families */ 187 struct afswtch { 188 char *af_name; 189 short af_af; 190 int (*af_status)(); 191 int (*af_getaddr)(); 192 int af_difaddr; 193 int af_aifaddr; 194 caddr_t af_ridreq; 195 caddr_t af_addreq; 196 } afs[] = { 197 #define C(x) ((caddr_t) &x) 198 { "inet", AF_INET, in_status, in_getaddr, 199 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 200 { "ipx", AF_IPX, ipx_status, ipx_getaddr, 201 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 202 #ifdef NS 203 { "ns", AF_NS, xns_status, xns_getaddr, 204 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 205 #endif 206 #ifdef ISO 207 { "iso", AF_ISO, iso_status, iso_getaddr, 208 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) }, 209 #endif 210 { "ether", AF_INET, ether_status, NULL }, /* XXX not real!! */ 211 { 0, 0, 0, 0 } 212 }; 213 214 struct afswtch *afp; /*the address family being set or asked about*/ 215 216 void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 217 int ifconfig __P((int argc, char *argv[], int af, struct afswtch *rafp)); 218 219 220 /* 221 * Expand the compacted form of addresses as returned via the 222 * configuration read via sysctl(). 223 */ 224 225 #define ROUNDUP(a) \ 226 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 227 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 228 229 void 230 rt_xaddrs(cp, cplim, rtinfo) 231 caddr_t cp, cplim; 232 struct rt_addrinfo *rtinfo; 233 { 234 struct sockaddr *sa; 235 int i; 236 237 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 238 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 239 if ((rtinfo->rti_addrs & (1 << i)) == 0) 240 continue; 241 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 242 ADVANCE(cp, sa); 243 } 244 } 245 246 247 /* 248 * Grunge for new-style sysctl() decoding.. :-( 249 * Apologies to the world for committing gross things like this in 1996.. 250 */ 251 struct if_msghdr *ifm; 252 struct ifa_msghdr *ifam; 253 struct sockaddr_dl *sdl; 254 struct rt_addrinfo info; 255 char *buf, *lim, *next; 256 257 258 259 main(argc, argv) 260 int argc; 261 char *argv[]; 262 { 263 int af = AF_INET; 264 struct afswtch *rafp; 265 266 size_t needed; 267 int mib[6], len; 268 int all; 269 270 if (argc < 2) { 271 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s%s", 272 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 273 "[ netmask mask ] ]\n", 274 "\t[ metric n ]\n", 275 "\t[ mtu n ]\n", 276 "\t[ arp | -arp ]\n", 277 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n", 278 "\t[ -a ] [ -ad ] [ -au ]\n"); 279 exit(1); 280 } 281 argc--, argv++; 282 strncpy(name, *argv, sizeof(name)); 283 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 284 argc--, argv++; 285 if (argc > 0) { 286 for (afp = rafp = afs; rafp->af_name; rafp++) 287 if (strcmp(rafp->af_name, *argv) == 0) { 288 afp = rafp; argc--; argv++; 289 break; 290 } 291 rafp = afp; 292 af = ifr.ifr_addr.sa_family = rafp->af_af; 293 } 294 295 mib[0] = CTL_NET; 296 mib[1] = PF_ROUTE; 297 mib[2] = 0; 298 mib[3] = 0; /* address family */ 299 mib[4] = NET_RT_IFLIST; 300 mib[5] = 0; 301 302 /* if particular family specified, only ask about it */ 303 if (afp) { 304 mib[3] = afp->af_af; 305 } 306 307 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 308 errx(1, "iflist-sysctl-estimate"); 309 if ((buf = malloc(needed)) == NULL) 310 errx(1, "malloc"); 311 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 312 errx(1, "actual retrieval of interface table"); 313 lim = buf + needed; 314 315 all = 0; 316 if (strcmp(name, "-a") == 0) 317 all = 1; /* All interfaces */ 318 else if (strcmp(name, "-au") == 0) 319 all = 2; /* All IFF_UPinterfaces */ 320 else if (strcmp(name, "-ad") == 0) 321 all = 3; /* All !IFF_UP interfaces */ 322 323 for (next = buf; next < lim; next += ifm->ifm_msglen) { 324 325 ifm = (struct if_msghdr *)next; 326 327 /* XXX: Swallow up leftover NEWADDR messages */ 328 if (ifm->ifm_type == RTM_NEWADDR) 329 continue; 330 331 if (ifm->ifm_type == RTM_IFINFO) { 332 sdl = (struct sockaddr_dl *)(ifm + 1); 333 flags = ifm->ifm_flags; 334 } else { 335 errx(1, "out of sync parsing NET_RT_IFLIST"); 336 } 337 338 switch(all) { 339 case -1: 340 case 0: 341 if (strlen(name) != sdl->sdl_nlen) 342 continue; /* not same len */ 343 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 344 continue; /* not same name */ 345 break; 346 case 1: 347 break; /* always do it */ 348 case 2: 349 if ((flags & IFF_UP) == 0) 350 continue; /* not up */ 351 break; 352 case 3: 353 if (flags & IFF_UP) 354 continue; /* not down */ 355 break; 356 } 357 358 if (all > 0) { 359 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 360 name[sdl->sdl_nlen] = '\0'; 361 } 362 363 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) { 364 perror("ifconfig: socket"); 365 exit(1); 366 } 367 368 ifconfig(argc,argv,af,rafp); 369 370 close(s); 371 372 if (all == 0) { 373 all = -1; /* flag it as 'done' */ 374 break; 375 } 376 } 377 free(buf); 378 379 if (all == 0) 380 errx(1, "interface %s does not exist..", name); 381 382 383 exit (0); 384 } 385 386 387 388 int 389 ifconfig(argc,argv,af,rafp) 390 int argc; 391 char *argv[]; 392 int af; 393 struct afswtch *rafp; 394 { 395 396 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 397 398 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 399 perror("ioctl (SIOCGIFMETRIC)"); 400 else 401 metric = ifr.ifr_metric; 402 403 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 404 perror("ioctl (SIOCGIFMTU)"); 405 else 406 mtu = ifr.ifr_mtu; 407 408 if (argc == 0) { 409 status(); 410 return(0); 411 } 412 413 while (argc > 0) { 414 register struct cmd *p; 415 416 for (p = cmds; p->c_name; p++) 417 if (strcmp(*argv, p->c_name) == 0) 418 break; 419 if (p->c_name == 0 && setaddr) 420 p++; /* got src, do dst */ 421 if (p->c_func) { 422 if (p->c_parameter == NEXTARG) { 423 if (argv[1] == NULL) 424 errx(1, "'%s' requires argument", 425 p->c_name); 426 (*p->c_func)(argv[1]); 427 argc--, argv++; 428 } else 429 (*p->c_func)(*argv, p->c_parameter); 430 } 431 argc--, argv++; 432 } 433 #ifdef ISO 434 if (af == AF_ISO) 435 adjust_nsellength(); 436 #endif 437 if (setipdst && af==AF_IPX) { 438 struct ipxip_req rq; 439 int size = sizeof(rq); 440 441 rq.rq_ipx = addreq.ifra_addr; 442 rq.rq_ip = addreq.ifra_dstaddr; 443 444 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 445 Perror("Encapsulation Routing"); 446 } 447 #ifdef NS 448 if (setipdst && af==AF_NS) { 449 struct nsip_req rq; 450 int size = sizeof(rq); 451 452 rq.rq_ns = addreq.ifra_addr; 453 rq.rq_ip = addreq.ifra_dstaddr; 454 455 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 456 Perror("Encapsulation Routing"); 457 } 458 #endif 459 if (clearaddr) { 460 if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) { 461 warnx("interface %s cannot change %s addresses!", 462 name, rafp->af_name); 463 clearaddr = NULL; 464 } 465 } 466 if (clearaddr) { 467 int ret; 468 strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name); 469 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 470 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 471 /* means no previous address for interface */ 472 } else 473 Perror("ioctl (SIOCDIFADDR)"); 474 } 475 } 476 if (newaddr) { 477 if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) { 478 warnx("interface %s cannot change %s addresses!", 479 name, rafp->af_name); 480 newaddr = NULL; 481 } 482 } 483 if (newaddr) { 484 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 485 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 486 Perror("ioctl (SIOCAIFADDR)"); 487 } 488 return(0); 489 } 490 #define RIDADDR 0 491 #define ADDR 1 492 #define MASK 2 493 #define DSTADDR 3 494 495 /*ARGSUSED*/ 496 setifaddr(addr, param) 497 char *addr; 498 short param; 499 { 500 /* 501 * Delay the ioctl to set the interface addr until flags are all set. 502 * The address interpretation may depend on the flags, 503 * and the flags may change when the address is set. 504 */ 505 setaddr++; 506 if (doalias == 0) 507 clearaddr = 1; 508 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 509 } 510 511 setifnetmask(addr) 512 char *addr; 513 { 514 (*afp->af_getaddr)(addr, MASK); 515 } 516 517 setifbroadaddr(addr) 518 char *addr; 519 { 520 (*afp->af_getaddr)(addr, DSTADDR); 521 } 522 523 setifipdst(addr) 524 char *addr; 525 { 526 in_getaddr(addr, DSTADDR); 527 setipdst++; 528 clearaddr = 0; 529 newaddr = 0; 530 } 531 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 532 /*ARGSUSED*/ 533 notealias(addr, param) 534 char *addr; 535 { 536 if (setaddr && doalias == 0 && param < 0) 537 bcopy((caddr_t)rqtosa(af_addreq), 538 (caddr_t)rqtosa(af_ridreq), 539 rqtosa(af_addreq)->sa_len); 540 doalias = param; 541 if (param < 0) { 542 clearaddr = 1; 543 newaddr = 0; 544 } else 545 clearaddr = 0; 546 } 547 548 /*ARGSUSED*/ 549 notrailers(vname, value) 550 char *vname; 551 int value; 552 { 553 printf("Note: trailers are no longer sent, but always received\n"); 554 } 555 556 /*ARGSUSED*/ 557 setifdstaddr(addr, param) 558 char *addr; 559 int param; 560 { 561 (*afp->af_getaddr)(addr, DSTADDR); 562 } 563 564 setifflags(vname, value) 565 char *vname; 566 short value; 567 { 568 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 569 Perror("ioctl (SIOCGIFFLAGS)"); 570 exit(1); 571 } 572 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 573 flags = ifr.ifr_flags; 574 575 if (value < 0) { 576 value = -value; 577 flags &= ~value; 578 } else 579 flags |= value; 580 ifr.ifr_flags = flags; 581 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 582 Perror(vname); 583 } 584 585 setifmetric(val) 586 char *val; 587 { 588 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 589 ifr.ifr_metric = atoi(val); 590 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 591 perror("ioctl (set metric)"); 592 } 593 594 setifmtu(val) 595 char *val; 596 { 597 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 598 ifr.ifr_mtu = atoi(val); 599 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 600 perror("ioctl (set mtu)"); 601 } 602 603 #ifdef ISO 604 setsnpaoffset(val) 605 char *val; 606 { 607 iso_addreq.ifra_snpaoffset = atoi(val); 608 } 609 #endif 610 611 #define IFFBITS \ 612 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 613 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 614 615 /* 616 * Print the status of the interface. If an address family was 617 * specified, show it and it only; otherwise, show them all. 618 */ 619 status() 620 { 621 struct afswtch *p = NULL; 622 short af = ifr.ifr_addr.sa_family; 623 char *mynext; 624 struct if_msghdr *myifm; 625 626 printf("%s: ", name); 627 printb("flags", flags, IFFBITS); 628 if (metric) 629 printf(" metric %d", metric); 630 if (mtu) 631 printf(" mtu %d", mtu); 632 putchar('\n'); 633 634 /* 635 * XXX: Sigh. This is bad, I know. At this point, we may have 636 * *zero* RTM_NEWADDR's, so we have to "feel the water" before 637 * incrementing the loop. One day, I might feel inspired enough 638 * to get the top level loop to pass a count down here so we 639 * dont have to mess with this. -Peter 640 */ 641 myifm = ifm; 642 643 while (1) { 644 645 mynext = next + ifm->ifm_msglen; 646 647 if (mynext >= lim) 648 break; 649 650 myifm = (struct if_msghdr *)mynext; 651 652 if (myifm->ifm_type != RTM_NEWADDR) 653 break; 654 655 next = mynext; 656 657 ifm = (struct if_msghdr *)next; 658 659 ifam = (struct ifa_msghdr *)myifm; 660 info.rti_addrs = ifam->ifam_addrs; 661 662 /* Expand the compacted addresses */ 663 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 664 &info); 665 666 if (afp) { 667 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family && 668 afp->af_status != ether_status) { 669 p = afp; 670 if (p->af_status != ether_status) 671 (*p->af_status)(1); 672 } 673 } else for (p = afs; p->af_name; p++) { 674 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family && 675 p->af_status != ether_status) 676 (*p->af_status)(0); 677 } 678 } 679 if (afp == NULL || afp->af_status == ether_status) 680 ether_status(); 681 else if (afp && !p) { 682 warnx("%s has no %s IFA address!", name, afp->af_name); 683 } 684 } 685 686 in_status(force) 687 int force; 688 { 689 struct sockaddr_in *sin, null_sin; 690 char *inet_ntoa(); 691 692 693 memset(&null_sin, 0, sizeof(null_sin)); 694 695 sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; 696 if (!sin || sin->sin_family != AF_INET) { 697 if (!force) 698 return; 699 /* warnx("%s has no AF_INET IFA address!", name); */ 700 sin = &null_sin; 701 } 702 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 703 704 if (flags & IFF_POINTOPOINT) { 705 /* note RTAX_BRD overlap with IFF_BROADCAST */ 706 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 707 if (!sin) 708 sin = &null_sin; 709 printf("--> %s ", inet_ntoa(sin->sin_addr)); 710 } 711 712 sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK]; 713 if (!sin) 714 sin = &null_sin; 715 printf("netmask 0x%x ", ntohl(sin->sin_addr.s_addr)); 716 717 if (flags & IFF_BROADCAST) { 718 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 719 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 720 if (sin && sin->sin_addr.s_addr != 0) 721 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 722 } 723 putchar('\n'); 724 } 725 726 ipx_status(force) 727 int force; 728 { 729 struct sockaddr_ipx *sipx, null_sipx; 730 731 close(s); 732 s = socket(AF_IPX, SOCK_DGRAM, 0); 733 if (s < 0) { 734 if (errno == EPROTONOSUPPORT) 735 return; 736 perror("ifconfig: socket"); 737 exit(1); 738 } 739 740 memset(&null_sipx, 0, sizeof(null_sipx)); 741 742 sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA]; 743 if (!sipx || sipx->sipx_family != AF_IPX) { 744 if (!force) 745 return; 746 warnx("%s has no AF_IPX IFA address!", name); 747 sipx = &null_sipx; 748 } 749 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 750 751 if (flags & IFF_POINTOPOINT) { 752 sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_BRD]; 753 if (!sipx) 754 sipx = &null_sipx; 755 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 756 } 757 putchar('\n'); 758 759 } 760 761 #ifdef NS 762 xns_status(force) 763 int force; 764 { 765 struct sockaddr_ns *sns, null_sns; 766 767 close(s); 768 s = socket(AF_NS, SOCK_DGRAM, 0); 769 if (s < 0) { 770 if (errno == EPROTONOSUPPORT) 771 return; 772 perror("ifconfig: socket"); 773 exit(1); 774 } 775 memset(&null_sns, 0, sizeof(null_sns)); 776 777 sns = (struct sockaddr_ns *)info.rti_info[RTAX_IFA]; 778 if (!sns || sns->sns_family != AF_NS) { 779 if (!force) 780 return; 781 /* warnx("%s has no AF_NS IFA address!", name); */ 782 sns = &null_sns; 783 } 784 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 785 786 if (flags & IFF_POINTOPOINT) { 787 sns = (struct sockaddr_ns *)info.rti_info[RTAX_BRD]; 788 if (!sns) 789 sns = &null_sns; 790 printf("--> %s ", ns_ntoa(sns->sns_addr)); 791 } 792 793 putchar('\n'); 794 } 795 #endif 796 797 #ifdef ISO 798 iso_status(force) 799 int force; 800 { 801 struct sockaddr_iso *siso, null_siso; 802 803 close(s); 804 s = socket(AF_ISO, SOCK_DGRAM, 0); 805 if (s < 0) { 806 if (errno == EPROTONOSUPPORT) 807 return; 808 perror("ifconfig: socket"); 809 exit(1); 810 } 811 812 memset(&null_siso, 0, sizeof(null_siso)); 813 814 siso = (struct sockaddr_iso *)info.rti_info[RTAX_IFA]; 815 if (!siso || siso->siso_family != AF_ISO) { 816 if (!force) 817 return; 818 /* warnx("%s has no AF_ISO IFA address!", name); */ 819 siso = &null_siso; 820 } 821 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 822 823 /* XXX: is this right? is the ISO netmask meant to be before P2P? */ 824 siso = (struct sockaddr_iso *)info.rti_info[RTAX_NETMASK]; 825 if (siso) 826 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 827 828 if (flags & IFF_POINTOPOINT) { 829 siso = (struct sockaddr_iso *)info.rti_info[RTAX_BRD]; 830 if (!siso) 831 siso = &null_siso; 832 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 833 } 834 835 putchar('\n'); 836 } 837 #endif 838 839 ether_status() 840 { 841 char *cp; 842 int n; 843 844 cp = (char *)LLADDR(sdl); 845 if ((n = sdl->sdl_alen) > 0) { 846 if (sdl->sdl_type == IFT_ETHER) 847 printf ("\tether "); 848 else 849 printf ("\tlladdr "); 850 while (--n >= 0) 851 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 852 putchar('\n'); 853 } 854 } 855 856 Perror(cmd) 857 char *cmd; 858 { 859 extern int errno; 860 861 switch (errno) { 862 863 case ENXIO: 864 errx(1, "%s: no such interface", cmd); 865 break; 866 867 case EPERM: 868 errx(1, "%s: permission denied", cmd); 869 break; 870 871 default: 872 err(1, "%s", cmd); 873 } 874 } 875 876 struct in_addr inet_makeaddr(); 877 878 #define SIN(x) ((struct sockaddr_in *) &(x)) 879 struct sockaddr_in *sintab[] = { 880 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 881 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 882 883 in_getaddr(s, which) 884 char *s; 885 { 886 register struct sockaddr_in *sin = sintab[which]; 887 struct hostent *hp; 888 struct netent *np; 889 int val; 890 891 sin->sin_len = sizeof(*sin); 892 if (which != MASK) 893 sin->sin_family = AF_INET; 894 895 if (inet_aton(s, &sin->sin_addr)) 896 ; 897 else if (hp = gethostbyname(s)) 898 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 899 else if (np = getnetbyname(s)) 900 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 901 else 902 errx(1, "%s: bad value", s); 903 } 904 905 /* 906 * Print a value a la the %b format of the kernel's printf 907 */ 908 printb(s, v, bits) 909 char *s; 910 register char *bits; 911 register unsigned short v; 912 { 913 register int i, any = 0; 914 register char c; 915 916 if (bits && *bits == 8) 917 printf("%s=%o", s, v); 918 else 919 printf("%s=%x", s, v); 920 bits++; 921 if (bits) { 922 putchar('<'); 923 while (i = *bits++) { 924 if (v & (1 << (i-1))) { 925 if (any) 926 putchar(','); 927 any = 1; 928 for (; (c = *bits) > 32; bits++) 929 putchar(c); 930 } else 931 for (; *bits > 32; bits++) 932 ; 933 } 934 putchar('>'); 935 } 936 } 937 938 #define SIPX(x) ((struct sockaddr_ipx *) &(x)) 939 struct sockaddr_ipx *sipxtab[] = { 940 SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 941 SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 942 943 ipx_getaddr(addr, which) 944 char *addr; 945 { 946 struct sockaddr_ipx *sipx = sipxtab[which]; 947 struct ipx_addr ipx_addr(); 948 949 sipx->sipx_family = AF_IPX; 950 sipx->sipx_len = sizeof(*sipx); 951 sipx->sipx_addr = ipx_addr(addr); 952 if (which == MASK) 953 printf("Attempt to set IPX netmask will be ineffectual\n"); 954 } 955 956 #ifdef NS 957 #define SNS(x) ((struct sockaddr_ns *) &(x)) 958 struct sockaddr_ns *snstab[] = { 959 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 960 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 961 962 xns_getaddr(addr, which) 963 char *addr; 964 { 965 struct sockaddr_ns *sns = snstab[which]; 966 struct ns_addr ns_addr(); 967 968 sns->sns_family = AF_NS; 969 sns->sns_len = sizeof(*sns); 970 sns->sns_addr = ns_addr(addr); 971 if (which == MASK) 972 printf("Attempt to set XNS netmask will be ineffectual\n"); 973 } 974 #endif 975 976 #ifdef ISO 977 #define SISO(x) ((struct sockaddr_iso *) &(x)) 978 struct sockaddr_iso *sisotab[] = { 979 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 980 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 981 982 iso_getaddr(addr, which) 983 char *addr; 984 { 985 register struct sockaddr_iso *siso = sisotab[which]; 986 struct iso_addr *iso_addr(); 987 siso->siso_addr = *iso_addr(addr); 988 989 if (which == MASK) { 990 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 991 siso->siso_nlen = 0; 992 } else { 993 siso->siso_len = sizeof(*siso); 994 siso->siso_family = AF_ISO; 995 } 996 } 997 998 setnsellength(val) 999 char *val; 1000 { 1001 nsellength = atoi(val); 1002 if (nsellength < 0) 1003 errx(1, "Negative NSEL length is absurd"); 1004 if (afp == 0 || afp->af_af != AF_ISO) 1005 errx(1, "Setting NSEL length valid only for iso"); 1006 } 1007 1008 fixnsel(s) 1009 register struct sockaddr_iso *s; 1010 { 1011 if (s->siso_family == 0) 1012 return; 1013 s->siso_tlen = nsellength; 1014 } 1015 1016 adjust_nsellength() 1017 { 1018 fixnsel(sisotab[RIDADDR]); 1019 fixnsel(sisotab[ADDR]); 1020 fixnsel(sisotab[DSTADDR]); 1021 } 1022 #endif 1023