ifconfig.c revision 34691
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.34 1997/12/26 23:28:04 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 (afp == NULL || 452 afp->af_status != ether_status || 453 sdl->sdl_type == IFT_ETHER) { 454 if (need_nl) 455 putchar(' '); 456 fputs(name, stdout); 457 need_nl++; 458 } 459 continue; 460 } 461 } else { 462 if (strlen(name) != sdl->sdl_nlen) 463 continue; /* not same len */ 464 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 465 continue; /* not same name */ 466 } 467 468 if (argc > 0) 469 ifconfig(argc, argv, afp); 470 else 471 status(afp, addrcount, sdl, ifm, ifam); 472 473 if (all == 0 && namesonly == 0) { 474 foundit++; /* flag it as 'done' */ 475 break; 476 } 477 } 478 free(buf); 479 480 if (namesonly && need_nl > 0) 481 putchar('\n'); 482 483 if (all == 0 && namesonly == 0 && foundit == 0) 484 errx(1, "interface %s does not exist", name); 485 486 487 exit (0); 488} 489 490 491int 492ifconfig(argc, argv, afp) 493 int argc; 494 char *const *argv; 495 const struct afswtch *afp; 496{ 497 int s; 498 499 if (afp == NULL) 500 afp = &afs[0]; 501 ifr.ifr_addr.sa_family = afp->af_af; 502 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 503 504 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) { 505 perror("ifconfig: socket"); 506 exit(1); 507 } 508 509 while (argc > 0) { 510 register const struct cmd *p; 511 512 for (p = cmds; p->c_name; p++) 513 if (strcmp(*argv, p->c_name) == 0) 514 break; 515 if (p->c_name == 0 && setaddr) 516 p++; /* got src, do dst */ 517 if (p->c_func) { 518 if (p->c_parameter == NEXTARG) { 519 if (argv[1] == NULL) 520 errx(1, "'%s' requires argument", 521 p->c_name); 522 (*p->c_func)(argv[1], 0, s, afp); 523 argc--, argv++; 524 } else 525 (*p->c_func)(*argv, p->c_parameter, s, afp); 526 } 527 argc--, argv++; 528 } 529#ifdef ISO 530 if (af == AF_ISO) 531 adjust_nsellength(); 532#endif 533 if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) { 534 struct ipxip_req rq; 535 int size = sizeof(rq); 536 537 rq.rq_ipx = addreq.ifra_addr; 538 rq.rq_ip = addreq.ifra_dstaddr; 539 540 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 541 Perror("Encapsulation Routing"); 542 } 543 if (ifr.ifr_addr.sa_family == AF_APPLETALK) 544 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 545#ifdef NS 546 if (setipdst && ifr.ifr_addr.sa_family == AF_NS) { 547 struct nsip_req rq; 548 int size = sizeof(rq); 549 550 rq.rq_ns = addreq.ifra_addr; 551 rq.rq_ip = addreq.ifra_dstaddr; 552 553 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 554 Perror("Encapsulation Routing"); 555 } 556#endif 557 if (clearaddr) { 558 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 559 warnx("interface %s cannot change %s addresses!", 560 name, afp->af_name); 561 clearaddr = NULL; 562 } 563 } 564 if (clearaddr) { 565 int ret; 566 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 567 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 568 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 569 /* means no previous address for interface */ 570 } else 571 Perror("ioctl (SIOCDIFADDR)"); 572 } 573 } 574 if (newaddr) { 575 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 576 warnx("interface %s cannot change %s addresses!", 577 name, afp->af_name); 578 newaddr = NULL; 579 } 580 } 581 if (newaddr) { 582 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 583 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 584 Perror("ioctl (SIOCAIFADDR)"); 585 } 586 close(s); 587 return(0); 588} 589#define RIDADDR 0 590#define ADDR 1 591#define MASK 2 592#define DSTADDR 3 593 594/*ARGSUSED*/ 595void 596setifaddr(addr, param, s, afp) 597 const char *addr; 598 int param; 599 int s; 600 const struct afswtch *afp; 601{ 602 /* 603 * Delay the ioctl to set the interface addr until flags are all set. 604 * The address interpretation may depend on the flags, 605 * and the flags may change when the address is set. 606 */ 607 setaddr++; 608 if (doalias == 0) 609 clearaddr = 1; 610 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 611} 612 613void 614setifnetmask(addr, dummy, s, afp) 615 const char *addr; 616 int dummy __unused; 617 int s; 618 const struct afswtch *afp; 619{ 620 (*afp->af_getaddr)(addr, MASK); 621} 622 623void 624setifbroadaddr(addr, dummy, s, afp) 625 const char *addr; 626 int dummy __unused; 627 int s; 628 const struct afswtch *afp; 629{ 630 (*afp->af_getaddr)(addr, DSTADDR); 631} 632 633void 634setifipdst(addr, dummy, s, afp) 635 const char *addr; 636 int dummy __unused; 637 int s; 638 const struct afswtch *afp; 639{ 640 in_getaddr(addr, DSTADDR); 641 setipdst++; 642 clearaddr = 0; 643 newaddr = 0; 644} 645#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 646 647void 648notealias(addr, param, s, afp) 649 const char *addr; 650 int param; 651 int s; 652 const struct afswtch *afp; 653{ 654 if (setaddr && doalias == 0 && param < 0) 655 bcopy((caddr_t)rqtosa(af_addreq), 656 (caddr_t)rqtosa(af_ridreq), 657 rqtosa(af_addreq)->sa_len); 658 doalias = param; 659 if (param < 0) { 660 clearaddr = 1; 661 newaddr = 0; 662 } else 663 clearaddr = 0; 664} 665 666/*ARGSUSED*/ 667void 668setifdstaddr(addr, param, s, afp) 669 const char *addr; 670 int param __unused; 671 int s; 672 const struct afswtch *afp; 673{ 674 (*afp->af_getaddr)(addr, DSTADDR); 675} 676 677void 678setifflags(vname, value, s, afp) 679 const char *vname; 680 int value; 681 int s; 682 const struct afswtch *afp; 683{ 684 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 685 Perror("ioctl (SIOCGIFFLAGS)"); 686 exit(1); 687 } 688 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 689 flags = ifr.ifr_flags; 690 691 if (value < 0) { 692 value = -value; 693 flags &= ~value; 694 } else 695 flags |= value; 696 ifr.ifr_flags = flags; 697 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 698 Perror(vname); 699} 700 701void 702setifmetric(val, dummy, s, afp) 703 const char *val; 704 int dummy __unused; 705 int s; 706 const struct afswtch *afp; 707{ 708 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 709 ifr.ifr_metric = atoi(val); 710 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 711 perror("ioctl (set metric)"); 712} 713 714void 715setifmtu(val, dummy, s, afp) 716 const char *val; 717 int dummy __unused; 718 int s; 719 const struct afswtch *afp; 720{ 721 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 722 ifr.ifr_mtu = atoi(val); 723 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 724 perror("ioctl (set mtu)"); 725} 726 727#ifdef ISO 728void 729setsnpaoffset(val, dummy) 730 char *val; 731 int dummy __unused; 732{ 733 iso_addreq.ifra_snpaoffset = atoi(val); 734} 735#endif 736 737#define IFFBITS \ 738"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \ 739"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 740"\20MULTICAST" 741 742/* 743 * Print the status of the interface. If an address family was 744 * specified, show it and it only; otherwise, show them all. 745 */ 746void 747status(afp, addrcount, sdl, ifm, ifam) 748 const struct afswtch *afp; 749 int addrcount; 750 struct sockaddr_dl *sdl; 751 struct if_msghdr *ifm; 752 struct ifa_msghdr *ifam; 753{ 754 const struct afswtch *p = NULL; 755 struct rt_addrinfo info; 756 int allfamilies, s; 757 758 if (afp == NULL) { 759 allfamilies = 1; 760 afp = &afs[0]; 761 } else 762 allfamilies = 0; 763 764 ifr.ifr_addr.sa_family = afp->af_af; 765 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 766 767 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) { 768 perror("ifconfig: socket"); 769 exit(1); 770 } 771 772 /* 773 * XXX is it we are doing a SIOCGIFMETRIC etc for one family. 774 * is it possible that the metric and mtu can be different for 775 * each family? If so, we have a format problem, because the 776 * metric and mtu is printed on the global the flags line. 777 */ 778 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 779 perror("ioctl (SIOCGIFMETRIC)"); 780 else 781 metric = ifr.ifr_metric; 782 783 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 784 perror("ioctl (SIOCGIFMTU)"); 785 else 786 mtu = ifr.ifr_mtu; 787 788 printf("%s: ", name); 789 printb("flags", flags, IFFBITS); 790 if (metric) 791 printf(" metric %d", metric); 792 if (mtu) 793 printf(" mtu %d", mtu); 794 putchar('\n'); 795 796 while (addrcount > 0) { 797 798 info.rti_addrs = ifam->ifam_addrs; 799 800 /* Expand the compacted addresses */ 801 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 802 &info); 803 804 if (!allfamilies) { 805 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family && 806#ifdef USE_IF_MEDIA 807 afp->af_status != media_status && 808#endif 809 afp->af_status != ether_status) { 810 p = afp; 811 (*p->af_status)(s, &info); 812 } 813 } else for (p = afs; p->af_name; p++) { 814 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family && 815#ifdef USE_IF_MEDIA 816 p->af_status != media_status && 817#endif 818 p->af_status != ether_status) 819 (*p->af_status)(s, &info); 820 } 821 addrcount--; 822 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 823 } 824 if (allfamilies || afp->af_status == ether_status) 825 ether_status(s, (struct rt_addrinfo *)sdl); 826#ifdef USE_IF_MEDIA 827 if (allfamilies || afp->af_status == media_status) 828 media_status(s, NULL); 829#endif 830 if (!allfamilies && !p && afp->af_status != media_status && 831 afp->af_status != ether_status) 832 warnx("%s has no %s interface address!", name, afp->af_name); 833 834 close(s); 835 return; 836} 837 838void 839in_status(s, info) 840 int s __unused; 841 struct rt_addrinfo * info; 842{ 843 struct sockaddr_in *sin, null_sin; 844 845 memset(&null_sin, 0, sizeof(null_sin)); 846 847 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 848 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 849 850 if (flags & IFF_POINTOPOINT) { 851 /* note RTAX_BRD overlap with IFF_BROADCAST */ 852 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 853 if (!sin) 854 sin = &null_sin; 855 printf("--> %s ", inet_ntoa(sin->sin_addr)); 856 } 857 858 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 859 if (!sin) 860 sin = &null_sin; 861 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 862 863 if (flags & IFF_BROADCAST) { 864 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 865 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 866 if (sin && sin->sin_addr.s_addr != 0) 867 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 868 } 869 putchar('\n'); 870} 871 872void 873ipx_status(s, info) 874 int s __unused; 875 struct rt_addrinfo * info; 876{ 877 struct sockaddr_ipx *sipx, null_sipx; 878 879 memset(&null_sipx, 0, sizeof(null_sipx)); 880 881 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 882 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 883 884 if (flags & IFF_POINTOPOINT) { 885 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 886 if (!sipx) 887 sipx = &null_sipx; 888 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 889 } 890 putchar('\n'); 891} 892 893void 894at_status(s, info) 895 int s __unused; 896 struct rt_addrinfo * info; 897{ 898 struct sockaddr_at *sat, null_sat; 899 struct netrange *nr; 900 901 memset(&null_sat, 0, sizeof(null_sat)); 902 903 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 904 nr = &sat->sat_range.r_netrange; 905 printf("\tatalk %d.%d range %d-%d phase %d", 906 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 907 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 908 if (flags & IFF_POINTOPOINT) { 909 /* note RTAX_BRD overlap with IFF_BROADCAST */ 910 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 911 if (!sat) 912 sat = &null_sat; 913 printf("--> %d.%d", 914 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 915 } 916 if (flags & IFF_BROADCAST) { 917 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 918 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 919 if (sat) 920 printf(" broadcast %d.%d", 921 ntohs(sat->sat_addr.s_net), 922 sat->sat_addr.s_node); 923 } 924 925 putchar('\n'); 926} 927 928#ifdef NS 929void 930xns_status(s, info) 931 int s __unused; 932 struct rt_addrinfo * info; 933{ 934 struct sockaddr_ns *sns, null_sns; 935 936 memset(&null_sns, 0, sizeof(null_sns)); 937 938 sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA]; 939 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 940 941 if (flags & IFF_POINTOPOINT) { 942 sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD]; 943 if (!sns) 944 sns = &null_sns; 945 printf("--> %s ", ns_ntoa(sns->sns_addr)); 946 } 947 948 putchar('\n'); 949 close(s); 950} 951#endif 952 953#ifdef ISO 954void 955iso_status(s, info) 956 int s __unused; 957 struct rt_addrinfo * info; 958{ 959 struct sockaddr_iso *siso, null_siso; 960 961 memset(&null_siso, 0, sizeof(null_siso)); 962 963 siso = (struct sockaddr_iso *)info->rti_info[RTAX_IFA]; 964 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 965 966 if (flags & IFF_POINTOPOINT) { 967 siso = (struct sockaddr_iso *)info->rti_info[RTAX_BRD]; 968 if (!siso) 969 siso = &null_siso; 970 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 971 } 972 973 siso = (struct sockaddr_iso *)info->rti_info[RTAX_NETMASK]; 974 if (siso) 975 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 976 977 putchar('\n'); 978} 979#endif 980 981void 982ether_status(s, info) 983 int s __unused; 984 struct rt_addrinfo *info; 985{ 986 char *cp; 987 int n; 988 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 989 990 cp = (char *)LLADDR(sdl); 991 if ((n = sdl->sdl_alen) > 0) { 992 if (sdl->sdl_type == IFT_ETHER) 993 printf ("\tether "); 994 else 995 printf ("\tlladdr "); 996 while (--n >= 0) 997 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 998 putchar('\n'); 999 } 1000} 1001 1002void 1003Perror(cmd) 1004 const char *cmd; 1005{ 1006 switch (errno) { 1007 1008 case ENXIO: 1009 errx(1, "%s: no such interface", cmd); 1010 break; 1011 1012 case EPERM: 1013 errx(1, "%s: permission denied", cmd); 1014 break; 1015 1016 default: 1017 err(1, "%s", cmd); 1018 } 1019} 1020 1021#define SIN(x) ((struct sockaddr_in *) &(x)) 1022struct sockaddr_in *sintab[] = { 1023SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1024SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1025 1026void 1027in_getaddr(s, which) 1028 const char *s; 1029 int which; 1030{ 1031 register struct sockaddr_in *sin = sintab[which]; 1032 struct hostent *hp; 1033 struct netent *np; 1034 1035 sin->sin_len = sizeof(*sin); 1036 if (which != MASK) 1037 sin->sin_family = AF_INET; 1038 1039 if (inet_aton(s, &sin->sin_addr)) 1040 return; 1041 if ((hp = gethostbyname(s)) != 0) 1042 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1043 MIN(hp->h_length, sizeof(sin->sin_addr))); 1044 else if ((np = getnetbyname(s)) != 0) 1045 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1046 else 1047 errx(1, "%s: bad value", s); 1048} 1049 1050/* 1051 * Print a value a la the %b format of the kernel's printf 1052 */ 1053void 1054printb(s, v, bits) 1055 const char *s; 1056 register unsigned v; 1057 register const char *bits; 1058{ 1059 register int i, any = 0; 1060 register char c; 1061 1062 if (bits && *bits == 8) 1063 printf("%s=%o", s, v); 1064 else 1065 printf("%s=%x", s, v); 1066 bits++; 1067 if (bits) { 1068 putchar('<'); 1069 while ((i = *bits++) != '\0') { 1070 if (v & (1 << (i-1))) { 1071 if (any) 1072 putchar(','); 1073 any = 1; 1074 for (; (c = *bits) > 32; bits++) 1075 putchar(c); 1076 } else 1077 for (; *bits > 32; bits++) 1078 ; 1079 } 1080 putchar('>'); 1081 } 1082} 1083 1084#define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1085struct sockaddr_ipx *sipxtab[] = { 1086SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1087SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1088 1089void 1090ipx_getaddr(addr, which) 1091 const char *addr; 1092 int which; 1093{ 1094 struct sockaddr_ipx *sipx = sipxtab[which]; 1095 1096 sipx->sipx_family = AF_IPX; 1097 sipx->sipx_len = sizeof(*sipx); 1098 sipx->sipx_addr = ipx_addr(addr); 1099 if (which == MASK) 1100 printf("Attempt to set IPX netmask will be ineffectual\n"); 1101} 1102 1103void 1104at_getaddr(addr, which) 1105 const char *addr; 1106 int which; 1107{ 1108 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1109 u_int net, node; 1110 1111 sat->sat_family = AF_APPLETALK; 1112 sat->sat_len = sizeof(*sat); 1113 if (which == MASK) 1114 errx(1, "AppleTalk does not use netmasks\n"); 1115 if (sscanf(addr, "%u.%u", &net, &node) != 2 1116 || net > 0xffff || node > 0xfe) 1117 errx(1, "%s: illegal address", addr); 1118 sat->sat_addr.s_net = htons(net); 1119 sat->sat_addr.s_node = node; 1120} 1121 1122/* XXX FIXME -- should use strtoul for better parsing. */ 1123void 1124setatrange(range, dummy, s, afp) 1125 const char *range; 1126 int dummy __unused; 1127 int s; 1128 const struct afswtch *afp; 1129{ 1130 u_short first = 123, last = 123; 1131 1132 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1133 || first == 0 || first > 0xffff 1134 || last == 0 || last > 0xffff || first > last) 1135 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1136 at_nr.nr_firstnet = htons(first); 1137 at_nr.nr_lastnet = htons(last); 1138} 1139 1140void 1141setatphase(phase, dummy, s, afp) 1142 const char *phase; 1143 int dummy __unused; 1144 int s; 1145 const struct afswtch *afp; 1146{ 1147 if (!strcmp(phase, "1")) 1148 at_nr.nr_phase = 1; 1149 else if (!strcmp(phase, "2")) 1150 at_nr.nr_phase = 2; 1151 else 1152 errx(1, "%s: illegal phase", phase); 1153} 1154 1155void 1156checkatrange(struct sockaddr_at *sat) 1157{ 1158 if (at_nr.nr_phase == 0) 1159 at_nr.nr_phase = 2; /* Default phase 2 */ 1160 if (at_nr.nr_firstnet == 0) 1161 at_nr.nr_firstnet = /* Default range of one */ 1162 at_nr.nr_lastnet = sat->sat_addr.s_net; 1163printf("\tatalk %d.%d range %d-%d phase %d\n", 1164 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1165 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1166 if ((u_short) ntohs(at_nr.nr_firstnet) > 1167 (u_short) ntohs(sat->sat_addr.s_net) 1168 || (u_short) ntohs(at_nr.nr_lastnet) < 1169 (u_short) ntohs(sat->sat_addr.s_net)) 1170 errx(1, "AppleTalk address is not in range"); 1171 sat->sat_range.r_netrange = at_nr; 1172} 1173 1174#ifdef NS 1175#define SNS(x) ((struct sockaddr_ns *) &(x)) 1176struct sockaddr_ns *snstab[] = { 1177SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1178SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1179 1180void 1181xns_getaddr(addr, which) 1182 const char *addr; 1183 int which; 1184{ 1185 struct sockaddr_ns *sns = snstab[which]; 1186 1187 sns->sns_family = AF_NS; 1188 sns->sns_len = sizeof(*sns); 1189 sns->sns_addr = ns_addr(addr); 1190 if (which == MASK) 1191 printf("Attempt to set XNS netmask will be ineffectual\n"); 1192} 1193#endif 1194 1195#ifdef ISO 1196#define SISO(x) ((struct sockaddr_iso *) &(x)) 1197struct sockaddr_iso *sisotab[] = { 1198SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 1199SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 1200 1201void 1202iso_getaddr(addr, which) 1203char *addr; 1204{ 1205 register struct sockaddr_iso *siso = sisotab[which]; 1206 struct iso_addr *iso_addr(); 1207 siso->siso_addr = *iso_addr(addr); 1208 1209 if (which == MASK) { 1210 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 1211 siso->siso_nlen = 0; 1212 } else { 1213 siso->siso_len = sizeof(*siso); 1214 siso->siso_family = AF_ISO; 1215 } 1216} 1217 1218void 1219setnsellength(val) 1220 char *val; 1221{ 1222 nsellength = atoi(val); 1223 if (nsellength < 0) 1224 errx(1, "Negative NSEL length is absurd"); 1225 if (afp == 0 || afp->af_af != AF_ISO) 1226 errx(1, "Setting NSEL length valid only for iso"); 1227} 1228 1229void 1230fixnsel(s) 1231register struct sockaddr_iso *s; 1232{ 1233 if (s->siso_family == 0) 1234 return; 1235 s->siso_tlen = nsellength; 1236} 1237 1238void 1239adjust_nsellength() 1240{ 1241 fixnsel(sisotab[RIDADDR]); 1242 fixnsel(sisotab[ADDR]); 1243 fixnsel(sisotab[DSTADDR]); 1244} 1245#endif 1246