ifconfig.c revision 13940
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/* 35 * 951109 - Andrew@pubnix.net - Changed to iterative buffer growing mechanism 36 * for ifconfig -a so all interfaces are queried. 37 * 38 * 960101 - peter@freebsd.org - Blow away the SIOCGIFCONF code and use 39 * sysctl() to get the structured interface conf 40 * and parse the messages in there. REALLY UGLY! 41 */ 42#ifndef lint 43static char copyright[] = 44"@(#) Copyright (c) 1983, 1993\n\ 45 The Regents of the University of California. All rights reserved.\n"; 46#endif /* not lint */ 47 48#ifndef lint 49static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 50#endif /* not lint */ 51 52#include <sys/param.h> 53#include <sys/socket.h> 54#include <sys/ioctl.h> 55#include <sys/sysctl.h> 56 57#include <net/if.h> 58#include <net/if_dl.h> 59#include <net/if_types.h> 60#include <net/route.h> 61#include <netinet/in.h> 62#include <netinet/in_var.h> 63#include <arpa/inet.h> 64#include <netdb.h> 65 66#define IPXIP 67#define IPTUNNEL 68#include <netipx/ipx.h> 69#include <netipx/ipx_if.h> 70 71#define NSIP 72#include <netns/ns.h> 73#include <netns/ns_if.h> 74 75#ifdef ISO 76#define EON 77#include <netiso/iso.h> 78#include <netiso/iso_var.h> 79#endif 80#include <sys/protosw.h> 81 82#include <ctype.h> 83#include <err.h> 84#include <errno.h> 85#include <stdio.h> 86#include <stdlib.h> 87#include <string.h> 88#include <unistd.h> 89#include <nlist.h> 90#include <kvm.h> 91#include <fcntl.h> 92 93struct ifreq ifr, ridreq; 94struct ifaliasreq addreq; 95#ifdef ISO 96struct iso_ifreq iso_ridreq; 97struct iso_aliasreq iso_addreq; 98#endif 99struct sockaddr_in netmask; 100 101char name[32]; 102int flags; 103int metric; 104int mtu; 105int nsellength = 1; 106int setaddr; 107int setipdst; 108int doalias; 109int clearaddr; 110int newaddr = 1; 111int s; 112kvm_t *kvmd; 113extern int errno; 114 115int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 116int setifmetric(), setifmtu(), setifbroadaddr(), setifipdst(); 117int notealias(); 118#ifdef ISO 119int setsnpaoffset(), setnsellength(); 120#endif 121int notrailers(); 122 123#define NEXTARG 0xffffff 124 125struct cmd { 126 char *c_name; 127 int c_parameter; /* NEXTARG means next argv */ 128 int (*c_func)(); 129} cmds[] = { 130 { "up", IFF_UP, setifflags } , 131 { "down", -IFF_UP, setifflags }, 132 { "trailers", -1, notrailers }, 133 { "-trailers", 1, notrailers }, 134 { "arp", -IFF_NOARP, setifflags }, 135 { "-arp", IFF_NOARP, setifflags }, 136 { "debug", IFF_DEBUG, setifflags }, 137 { "-debug", -IFF_DEBUG, setifflags }, 138 { "alias", IFF_UP, notealias }, 139 { "-alias", -IFF_UP, notealias }, 140 { "delete", -IFF_UP, notealias }, 141#ifdef notdef 142#define EN_SWABIPS 0x1000 143 { "swabips", EN_SWABIPS, setifflags }, 144 { "-swabips", -EN_SWABIPS, setifflags }, 145#endif 146 { "netmask", NEXTARG, setifnetmask }, 147 { "metric", NEXTARG, setifmetric }, 148 { "broadcast", NEXTARG, setifbroadaddr }, 149 { "ipdst", NEXTARG, setifipdst }, 150#ifdef ISO 151 { "snpaoffset", NEXTARG, setsnpaoffset }, 152 { "nsellength", NEXTARG, setnsellength }, 153#endif 154 { "link0", IFF_LINK0, setifflags }, 155 { "-link0", -IFF_LINK0, setifflags }, 156 { "link1", IFF_LINK1, setifflags }, 157 { "-link1", -IFF_LINK1, setifflags }, 158 { "link2", IFF_LINK2, setifflags }, 159 { "-link2", -IFF_LINK2, setifflags }, 160 { "normal", -IFF_LINK0, setifflags }, 161 { "compress", IFF_LINK0, setifflags }, 162 { "noicmp", IFF_LINK1, setifflags }, 163 { "mtu", NEXTARG, setifmtu }, 164 { 0, 0, setifaddr }, 165 { 0, 0, setifdstaddr }, 166}; 167 168/* 169 * XNS support liberally adapted from code written at the University of 170 * Maryland principally by James O'Toole and Chris Torek. 171 */ 172int in_status(), in_getaddr(); 173int ipx_status(), ipx_getaddr(); 174int xns_status(), xns_getaddr(); 175#ifdef ISO 176int iso_status(), iso_getaddr(); 177#endif 178int ether_status(); 179 180/* Known address families */ 181struct afswtch { 182 char *af_name; 183 short af_af; 184 int (*af_status)(); 185 int (*af_getaddr)(); 186 int af_difaddr; 187 int af_aifaddr; 188 caddr_t af_ridreq; 189 caddr_t af_addreq; 190} afs[] = { 191#define C(x) ((caddr_t) &x) 192 { "inet", AF_INET, in_status, in_getaddr, 193 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 194 { "ipx", AF_IPX, ipx_status, ipx_getaddr, 195 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 196 { "ns", AF_NS, xns_status, xns_getaddr, 197 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 198#ifdef ISO 199 { "iso", AF_ISO, iso_status, iso_getaddr, 200 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) }, 201#endif 202 { "ether", AF_INET, ether_status, NULL }, /* XXX not real!! */ 203 { 0, 0, 0, 0 } 204}; 205 206struct afswtch *afp; /*the address family being set or asked about*/ 207 208void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 209int ifconfig __P((int argc, char *argv[], int af, struct afswtch *rafp)); 210 211 212/* 213 * Expand the compacted form of addresses as returned via the 214 * configuration read via sysctl(). 215 */ 216 217#define ROUNDUP(a) \ 218 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 219#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 220 221void 222rt_xaddrs(cp, cplim, rtinfo) 223 caddr_t cp, cplim; 224 struct rt_addrinfo *rtinfo; 225{ 226 struct sockaddr *sa; 227 int i; 228 229 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 230 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 231 if ((rtinfo->rti_addrs & (1 << i)) == 0) 232 continue; 233 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 234 ADVANCE(cp, sa); 235 } 236} 237 238 239/* 240 * Grunge for new-style sysctl() decoding.. :-( 241 * Apologies to the world for committing gross things like this in 1996.. 242 */ 243struct if_msghdr *ifm; 244struct ifa_msghdr *ifam; 245struct sockaddr_dl *sdl; 246struct rt_addrinfo info; 247char *buf, *lim, *next; 248 249 250 251main(argc, argv) 252 int argc; 253 char *argv[]; 254{ 255 int af = AF_INET; 256 struct afswtch *rafp; 257 258 size_t needed; 259 int mib[6], len; 260 int all; 261 262 if (argc < 2) { 263 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s%s", 264 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 265 "[ netmask mask ] ]\n", 266 "\t[ metric n ]\n", 267 "\t[ mtu n ]\n", 268 "\t[ arp | -arp ]\n", 269 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n", 270 "\t[ -a ] [ -ad ] [ -au ]\n"); 271 exit(1); 272 } 273 argc--, argv++; 274 strncpy(name, *argv, sizeof(name)); 275 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 276 argc--, argv++; 277 if (argc > 0) { 278 for (afp = rafp = afs; rafp->af_name; rafp++) 279 if (strcmp(rafp->af_name, *argv) == 0) { 280 afp = rafp; argc--; argv++; 281 break; 282 } 283 rafp = afp; 284 af = ifr.ifr_addr.sa_family = rafp->af_af; 285 } 286 287 mib[0] = CTL_NET; 288 mib[1] = PF_ROUTE; 289 mib[2] = 0; 290 mib[3] = 0; /* address family */ 291 mib[4] = NET_RT_IFLIST; 292 mib[5] = 0; 293 294 /* if particular family specified, only ask about it */ 295 if (afp) { 296 mib[3] = afp->af_af; 297 } 298 299 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 300 errx(1, "iflist-sysctl-estimate"); 301 if ((buf = malloc(needed)) == NULL) 302 errx(1, "malloc"); 303 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 304 errx(1, "actual retrieval of interface table"); 305 lim = buf + needed; 306 307 all = 0; 308 if (strcmp(name, "-a") == 0) 309 all = 1; /* All interfaces */ 310 else if (strcmp(name, "-au") == 0) 311 all = 2; /* All IFF_UPinterfaces */ 312 else if (strcmp(name, "-ad") == 0) 313 all = 3; /* All !IFF_UP interfaces */ 314 315 for (next = buf; next < lim; next += ifm->ifm_msglen) { 316 317 ifm = (struct if_msghdr *)next; 318 319 /* XXX: Swallow up leftover NEWADDR messages */ 320 if (ifm->ifm_type == RTM_NEWADDR) 321 continue; 322 323 if (ifm->ifm_type == RTM_IFINFO) { 324 sdl = (struct sockaddr_dl *)(ifm + 1); 325 flags = ifm->ifm_flags; 326 } else { 327 errx(1, "out of sync parsing NET_RT_IFLIST"); 328 } 329 330 switch(all) { 331 case -1: 332 case 0: 333 if (strlen(name) != sdl->sdl_nlen) 334 continue; /* not same len */ 335 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 336 continue; /* not same name */ 337 break; 338 case 1: 339 break; /* always do it */ 340 case 2: 341 if ((flags & IFF_UP) == 0) 342 continue; /* not up */ 343 break; 344 case 3: 345 if (flags & IFF_UP) 346 continue; /* not down */ 347 break; 348 } 349 350 if (all > 0) { 351 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 352 name[sdl->sdl_nlen] = '\0'; 353 } 354 355 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) { 356 perror("ifconfig: socket"); 357 exit(1); 358 } 359 360 ifconfig(argc,argv,af,rafp); 361 362 close(s); 363 364 if (all == 0) { 365 all = -1; /* flag it as 'done' */ 366 break; 367 } 368 } 369 free(buf); 370 371 if (all == 0) 372 errx(1, "interface %s does not exist..", name); 373 374 375 exit (0); 376} 377 378 379 380int 381ifconfig(argc,argv,af,rafp) 382 int argc; 383 char *argv[]; 384 int af; 385 struct afswtch *rafp; 386{ 387 388 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 389 390 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 391 perror("ioctl (SIOCGIFMETRIC)"); 392 else 393 metric = ifr.ifr_metric; 394 395 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 396 perror("ioctl (SIOCGIFMTU)"); 397 else 398 mtu = ifr.ifr_mtu; 399 400 if (argc == 0) { 401 status(); 402 return(0); 403 } 404 405 while (argc > 0) { 406 register struct cmd *p; 407 408 for (p = cmds; p->c_name; p++) 409 if (strcmp(*argv, p->c_name) == 0) 410 break; 411 if (p->c_name == 0 && setaddr) 412 p++; /* got src, do dst */ 413 if (p->c_func) { 414 if (p->c_parameter == NEXTARG) { 415 if (argv[1] == NULL) 416 errx(1, "'%s' requires argument", 417 p->c_name); 418 (*p->c_func)(argv[1]); 419 argc--, argv++; 420 } else 421 (*p->c_func)(*argv, p->c_parameter); 422 } 423 argc--, argv++; 424 } 425#ifdef ISO 426 if (af == AF_ISO) 427 adjust_nsellength(); 428#endif 429 if (setipdst && af==AF_IPX) { 430 struct ipxip_req rq; 431 int size = sizeof(rq); 432 433 rq.rq_ipx = addreq.ifra_addr; 434 rq.rq_ip = addreq.ifra_dstaddr; 435 436 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 437 Perror("Encapsulation Routing"); 438 } 439 if (setipdst && af==AF_NS) { 440 struct nsip_req rq; 441 int size = sizeof(rq); 442 443 rq.rq_ns = addreq.ifra_addr; 444 rq.rq_ip = addreq.ifra_dstaddr; 445 446 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 447 Perror("Encapsulation Routing"); 448 } 449 if (clearaddr) { 450 if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) { 451 warnx("interface %s cannot change %s addresses!", 452 name, rafp->af_name); 453 clearaddr = NULL; 454 } 455 } 456 if (clearaddr) { 457 int ret; 458 strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name); 459 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 460 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 461 /* means no previous address for interface */ 462 } else 463 Perror("ioctl (SIOCDIFADDR)"); 464 } 465 } 466 if (newaddr) { 467 if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) { 468 warnx("interface %s cannot change %s addresses!", 469 name, rafp->af_name); 470 newaddr = NULL; 471 } 472 } 473 if (newaddr) { 474 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 475 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 476 Perror("ioctl (SIOCAIFADDR)"); 477 } 478 return(0); 479} 480#define RIDADDR 0 481#define ADDR 1 482#define MASK 2 483#define DSTADDR 3 484 485/*ARGSUSED*/ 486setifaddr(addr, param) 487 char *addr; 488 short param; 489{ 490 /* 491 * Delay the ioctl to set the interface addr until flags are all set. 492 * The address interpretation may depend on the flags, 493 * and the flags may change when the address is set. 494 */ 495 setaddr++; 496 if (doalias == 0) 497 clearaddr = 1; 498 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 499} 500 501setifnetmask(addr) 502 char *addr; 503{ 504 (*afp->af_getaddr)(addr, MASK); 505} 506 507setifbroadaddr(addr) 508 char *addr; 509{ 510 (*afp->af_getaddr)(addr, DSTADDR); 511} 512 513setifipdst(addr) 514 char *addr; 515{ 516 in_getaddr(addr, DSTADDR); 517 setipdst++; 518 clearaddr = 0; 519 newaddr = 0; 520} 521#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 522/*ARGSUSED*/ 523notealias(addr, param) 524 char *addr; 525{ 526 if (setaddr && doalias == 0 && param < 0) 527 bcopy((caddr_t)rqtosa(af_addreq), 528 (caddr_t)rqtosa(af_ridreq), 529 rqtosa(af_addreq)->sa_len); 530 doalias = param; 531 if (param < 0) { 532 clearaddr = 1; 533 newaddr = 0; 534 } else 535 clearaddr = 0; 536} 537 538/*ARGSUSED*/ 539notrailers(vname, value) 540 char *vname; 541 int value; 542{ 543 printf("Note: trailers are no longer sent, but always received\n"); 544} 545 546/*ARGSUSED*/ 547setifdstaddr(addr, param) 548 char *addr; 549 int param; 550{ 551 (*afp->af_getaddr)(addr, DSTADDR); 552} 553 554setifflags(vname, value) 555 char *vname; 556 short value; 557{ 558 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 559 Perror("ioctl (SIOCGIFFLAGS)"); 560 exit(1); 561 } 562 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 563 flags = ifr.ifr_flags; 564 565 if (value < 0) { 566 value = -value; 567 flags &= ~value; 568 } else 569 flags |= value; 570 ifr.ifr_flags = flags; 571 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 572 Perror(vname); 573} 574 575setifmetric(val) 576 char *val; 577{ 578 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 579 ifr.ifr_metric = atoi(val); 580 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 581 perror("ioctl (set metric)"); 582} 583 584setifmtu(val) 585 char *val; 586{ 587 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 588 ifr.ifr_mtu = atoi(val); 589 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 590 perror("ioctl (set mtu)"); 591} 592 593#ifdef ISO 594setsnpaoffset(val) 595 char *val; 596{ 597 iso_addreq.ifra_snpaoffset = atoi(val); 598} 599#endif 600 601#define IFFBITS \ 602"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 603\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 604 605/* 606 * Print the status of the interface. If an address family was 607 * specified, show it and it only; otherwise, show them all. 608 */ 609status() 610{ 611 struct afswtch *p = NULL; 612 short af = ifr.ifr_addr.sa_family; 613 char *mynext; 614 struct if_msghdr *myifm; 615 616 printf("%s: ", name); 617 printb("flags", flags, IFFBITS); 618 if (metric) 619 printf(" metric %d", metric); 620 if (mtu) 621 printf(" mtu %d", mtu); 622 putchar('\n'); 623 624 /* 625 * XXX: Sigh. This is bad, I know. At this point, we may have 626 * *zero* RTM_NEWADDR's, so we have to "feel the water" before 627 * incrementing the loop. One day, I might feel inspired enough 628 * to get the top level loop to pass a count down here so we 629 * dont have to mess with this. -Peter 630 */ 631 myifm = ifm; 632 633 while (1) { 634 635 mynext = next + ifm->ifm_msglen; 636 637 if (mynext >= lim) 638 break; 639 640 myifm = (struct if_msghdr *)mynext; 641 642 if (myifm->ifm_type != RTM_NEWADDR) 643 break; 644 645 next = mynext; 646 647 ifm = (struct if_msghdr *)next; 648 649 ifam = (struct ifa_msghdr *)myifm; 650 info.rti_addrs = ifam->ifam_addrs; 651 652 /* Expand the compacted addresses */ 653 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 654 &info); 655 656 if (afp) { 657 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family && 658 afp->af_status != ether_status) { 659 p = afp; 660 if (p->af_status != ether_status) 661 (*p->af_status)(1); 662 } 663 } else for (p = afs; p->af_name; p++) { 664 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family && 665 p->af_status != ether_status) 666 (*p->af_status)(0); 667 } 668 } 669 if (afp == NULL || afp->af_status == ether_status) 670 ether_status(); 671 else if (afp && !p) { 672 warnx("%s has no %s IFA address!", name, afp->af_name); 673 } 674} 675 676in_status(force) 677 int force; 678{ 679 struct sockaddr_in *sin, null_sin; 680 char *inet_ntoa(); 681 682 683 memset(&null_sin, 0, sizeof(null_sin)); 684 685 sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; 686 if (!sin || sin->sin_family != AF_INET) { 687 if (!force) 688 return; 689 /* warnx("%s has no AF_INET IFA address!", name); */ 690 sin = &null_sin; 691 } 692 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 693 694 if (flags & IFF_POINTOPOINT) { 695 /* note RTAX_BRD overlap with IFF_BROADCAST */ 696 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 697 if (!sin) 698 sin = &null_sin; 699 printf("--> %s ", inet_ntoa(sin->sin_addr)); 700 } 701 702 sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK]; 703 if (!sin) 704 sin = &null_sin; 705 printf("netmask 0x%x ", ntohl(sin->sin_addr.s_addr)); 706 707 if (flags & IFF_BROADCAST) { 708 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 709 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 710 if (sin && sin->sin_addr.s_addr != 0) 711 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 712 } 713 putchar('\n'); 714} 715 716ipx_status(force) 717 int force; 718{ 719 struct sockaddr_ipx *sipx, null_sipx; 720 721 close(s); 722 s = socket(AF_IPX, SOCK_DGRAM, 0); 723 if (s < 0) { 724 if (errno == EPROTONOSUPPORT) 725 return; 726 perror("ifconfig: socket"); 727 exit(1); 728 } 729 730 memset(&null_sipx, 0, sizeof(null_sipx)); 731 732 sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA]; 733 if (!sipx || sipx->sipx_family != AF_IPX) { 734 if (!force) 735 return; 736 warnx("%s has no AF_IPX IFA address!", name); 737 sipx = &null_sipx; 738 } 739 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 740 741 if (flags & IFF_POINTOPOINT) { 742 sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_BRD]; 743 if (!sipx) 744 sipx = &null_sipx; 745 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 746 } 747 putchar('\n'); 748 749} 750 751xns_status(force) 752 int force; 753{ 754 struct sockaddr_ns *sns, null_sns; 755 756 close(s); 757 s = socket(AF_NS, SOCK_DGRAM, 0); 758 if (s < 0) { 759 if (errno == EPROTONOSUPPORT) 760 return; 761 perror("ifconfig: socket"); 762 exit(1); 763 } 764 memset(&null_sns, 0, sizeof(null_sns)); 765 766 sns = (struct sockaddr_ns *)info.rti_info[RTAX_IFA]; 767 if (!sns || sns->sns_family != AF_NS) { 768 if (!force) 769 return; 770 /* warnx("%s has no AF_NS IFA address!", name); */ 771 sns = &null_sns; 772 } 773 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 774 775 if (flags & IFF_POINTOPOINT) { 776 sns = (struct sockaddr_ns *)info.rti_info[RTAX_BRD]; 777 if (!sns) 778 sns = &null_sns; 779 printf("--> %s ", ns_ntoa(sns->sns_addr)); 780 } 781 782 putchar('\n'); 783} 784 785#ifdef ISO 786iso_status(force) 787 int force; 788{ 789 struct sockaddr_iso *siso, null_siso; 790 791 close(s); 792 s = socket(AF_ISO, SOCK_DGRAM, 0); 793 if (s < 0) { 794 if (errno == EPROTONOSUPPORT) 795 return; 796 perror("ifconfig: socket"); 797 exit(1); 798 } 799 800 memset(&null_siso, 0, sizeof(null_siso)); 801 802 siso = (struct sockaddr_iso *)info.rti_info[RTAX_IFA]; 803 if (!siso || siso->siso_family != AF_ISO) { 804 if (!force) 805 return; 806 /* warnx("%s has no AF_ISO IFA address!", name); */ 807 siso = &null_siso; 808 } 809 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 810 811 /* XXX: is this right? is the ISO netmask meant to be before P2P? */ 812 siso = (struct sockaddr_iso *)info.rti_info[RTAX_NETMASK]; 813 if (siso) 814 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 815 816 if (flags & IFF_POINTOPOINT) { 817 siso = (struct sockaddr_iso *)info.rti_info[RTAX_BRD]; 818 if (!siso) 819 siso = &null_siso; 820 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 821 } 822 823 putchar('\n'); 824} 825#endif 826 827ether_status() 828{ 829 char *cp; 830 int n; 831 832 cp = (char *)LLADDR(sdl); 833 if ((n = sdl->sdl_alen) > 0) { 834 if (sdl->sdl_type == IFT_ETHER) 835 printf ("\tether "); 836 else 837 printf ("\tlladdr "); 838 while (--n >= 0) 839 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 840 putchar('\n'); 841 } 842} 843 844Perror(cmd) 845 char *cmd; 846{ 847 extern int errno; 848 849 switch (errno) { 850 851 case ENXIO: 852 errx(1, "%s: no such interface", cmd); 853 break; 854 855 case EPERM: 856 errx(1, "%s: permission denied", cmd); 857 break; 858 859 default: 860 err(1, "%s", cmd); 861 } 862} 863 864struct in_addr inet_makeaddr(); 865 866#define SIN(x) ((struct sockaddr_in *) &(x)) 867struct sockaddr_in *sintab[] = { 868SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 869SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 870 871in_getaddr(s, which) 872 char *s; 873{ 874 register struct sockaddr_in *sin = sintab[which]; 875 struct hostent *hp; 876 struct netent *np; 877 int val; 878 879 sin->sin_len = sizeof(*sin); 880 if (which != MASK) 881 sin->sin_family = AF_INET; 882 883 if (inet_aton(s, &sin->sin_addr)) 884 ; 885 else if (hp = gethostbyname(s)) 886 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 887 else if (np = getnetbyname(s)) 888 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 889 else 890 errx(1, "%s: bad value", s); 891} 892 893/* 894 * Print a value a la the %b format of the kernel's printf 895 */ 896printb(s, v, bits) 897 char *s; 898 register char *bits; 899 register unsigned short v; 900{ 901 register int i, any = 0; 902 register char c; 903 904 if (bits && *bits == 8) 905 printf("%s=%o", s, v); 906 else 907 printf("%s=%x", s, v); 908 bits++; 909 if (bits) { 910 putchar('<'); 911 while (i = *bits++) { 912 if (v & (1 << (i-1))) { 913 if (any) 914 putchar(','); 915 any = 1; 916 for (; (c = *bits) > 32; bits++) 917 putchar(c); 918 } else 919 for (; *bits > 32; bits++) 920 ; 921 } 922 putchar('>'); 923 } 924} 925 926#define SIPX(x) ((struct sockaddr_ipx *) &(x)) 927struct sockaddr_ipx *sipxtab[] = { 928SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 929SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 930 931ipx_getaddr(addr, which) 932char *addr; 933{ 934 struct sockaddr_ipx *sipx = sipxtab[which]; 935 struct ipx_addr ipx_addr(); 936 937 sipx->sipx_family = AF_IPX; 938 sipx->sipx_len = sizeof(*sipx); 939 sipx->sipx_addr = ipx_addr(addr); 940 if (which == MASK) 941 printf("Attempt to set IPX netmask will be ineffectual\n"); 942} 943 944#define SNS(x) ((struct sockaddr_ns *) &(x)) 945struct sockaddr_ns *snstab[] = { 946SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 947SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 948 949xns_getaddr(addr, which) 950char *addr; 951{ 952 struct sockaddr_ns *sns = snstab[which]; 953 struct ns_addr ns_addr(); 954 955 sns->sns_family = AF_NS; 956 sns->sns_len = sizeof(*sns); 957 sns->sns_addr = ns_addr(addr); 958 if (which == MASK) 959 printf("Attempt to set XNS netmask will be ineffectual\n"); 960} 961 962#ifdef ISO 963#define SISO(x) ((struct sockaddr_iso *) &(x)) 964struct sockaddr_iso *sisotab[] = { 965SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 966SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 967 968iso_getaddr(addr, which) 969char *addr; 970{ 971 register struct sockaddr_iso *siso = sisotab[which]; 972 struct iso_addr *iso_addr(); 973 siso->siso_addr = *iso_addr(addr); 974 975 if (which == MASK) { 976 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 977 siso->siso_nlen = 0; 978 } else { 979 siso->siso_len = sizeof(*siso); 980 siso->siso_family = AF_ISO; 981 } 982} 983 984setnsellength(val) 985 char *val; 986{ 987 nsellength = atoi(val); 988 if (nsellength < 0) 989 errx(1, "Negative NSEL length is absurd"); 990 if (afp == 0 || afp->af_af != AF_ISO) 991 errx(1, "Setting NSEL length valid only for iso"); 992} 993 994fixnsel(s) 995register struct sockaddr_iso *s; 996{ 997 if (s->siso_family == 0) 998 return; 999 s->siso_tlen = nsellength; 1000} 1001 1002adjust_nsellength() 1003{ 1004 fixnsel(sisotab[RIDADDR]); 1005 fixnsel(sisotab[ADDR]); 1006 fixnsel(sisotab[DSTADDR]); 1007} 1008#endif 1009