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