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