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