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