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