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