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