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 35 static 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 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 42 #endif /* not lint */ 43 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 #include <sys/ioctl.h> 47 48 #include <net/if.h> 49 #include <net/if_dl.h> 50 #include <netinet/in.h> 51 #include <netinet/in_var.h> 52 #include <arpa/inet.h> 53 54 #define NSIP 55 #include <netns/ns.h> 56 #include <netns/ns_if.h> 57 #include <netdb.h> 58 59 #define EON 60 #include <netiso/iso.h> 61 #include <netiso/iso_var.h> 62 #include <sys/protosw.h> 63 64 #include <ctype.h> 65 #include <err.h> 66 #include <errno.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <unistd.h> 71 #include <nlist.h> 72 #include <kvm.h> 73 #include <fcntl.h> 74 75 struct ifreq ifr, ridreq; 76 struct ifaliasreq addreq; 77 struct iso_ifreq iso_ridreq; 78 struct iso_aliasreq iso_addreq; 79 struct sockaddr_in netmask; 80 81 char name[30]; 82 int flags; 83 int metric; 84 int mtu; 85 int nsellength = 1; 86 int setaddr; 87 int setipdst; 88 int doalias; 89 int clearaddr; 90 int newaddr = 1; 91 int s; 92 kvm_t *kvmd; 93 extern int errno; 94 95 int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 96 int setifmetric(), setifmtu(), setifbroadaddr(), setifipdst(); 97 int notealias(), setsnpaoffset(), setnsellength(), notrailers(); 98 99 #define NEXTARG 0xffffff 100 101 struct cmd { 102 char *c_name; 103 int c_parameter; /* NEXTARG means next argv */ 104 int (*c_func)(); 105 } cmds[] = { 106 { "up", IFF_UP, setifflags } , 107 { "down", -IFF_UP, setifflags }, 108 { "trailers", -1, notrailers }, 109 { "-trailers", 1, notrailers }, 110 { "arp", -IFF_NOARP, setifflags }, 111 { "-arp", IFF_NOARP, setifflags }, 112 { "debug", IFF_DEBUG, setifflags }, 113 { "-debug", -IFF_DEBUG, setifflags }, 114 { "alias", IFF_UP, notealias }, 115 { "-alias", -IFF_UP, notealias }, 116 { "delete", -IFF_UP, notealias }, 117 #ifdef notdef 118 #define EN_SWABIPS 0x1000 119 { "swabips", EN_SWABIPS, setifflags }, 120 { "-swabips", -EN_SWABIPS, setifflags }, 121 #endif 122 { "netmask", NEXTARG, setifnetmask }, 123 { "metric", NEXTARG, setifmetric }, 124 { "broadcast", NEXTARG, setifbroadaddr }, 125 { "ipdst", NEXTARG, setifipdst }, 126 { "snpaoffset", NEXTARG, setsnpaoffset }, 127 { "nsellength", NEXTARG, setnsellength }, 128 { "link0", IFF_LINK0, setifflags }, 129 { "-link0", -IFF_LINK0, setifflags }, 130 { "link1", IFF_LINK1, setifflags }, 131 { "-link1", -IFF_LINK1, setifflags }, 132 { "link2", IFF_LINK2, setifflags }, 133 { "-link2", -IFF_LINK2, setifflags }, 134 { "normal", -IFF_LINK0, setifflags }, 135 { "compress", IFF_LINK0, setifflags }, 136 { "noicmp", IFF_LINK1, setifflags }, 137 { "mtu", NEXTARG, setifmtu }, 138 { 0, 0, setifaddr }, 139 { 0, 0, setifdstaddr }, 140 }; 141 142 /* 143 * XNS support liberally adapted from code written at the University of 144 * Maryland principally by James O'Toole and Chris Torek. 145 */ 146 int in_status(), in_getaddr(); 147 int xns_status(), xns_getaddr(); 148 int iso_status(), iso_getaddr(); 149 int ether_status(); 150 151 /* Known address families */ 152 struct afswtch { 153 char *af_name; 154 short af_af; 155 int (*af_status)(); 156 int (*af_getaddr)(); 157 int af_difaddr; 158 int af_aifaddr; 159 caddr_t af_ridreq; 160 caddr_t af_addreq; 161 } afs[] = { 162 #define C(x) ((caddr_t) &x) 163 { "inet", AF_INET, in_status, in_getaddr, 164 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 165 { "ns", AF_NS, xns_status, xns_getaddr, 166 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 167 { "iso", AF_ISO, iso_status, iso_getaddr, 168 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) }, 169 { "ether", AF_INET, ether_status, NULL }, 170 { 0, 0, 0, 0 } 171 }; 172 173 struct afswtch *afp; /*the address family being set or asked about*/ 174 175 main(argc, argv) 176 int argc; 177 char *argv[]; 178 { 179 int af = AF_INET; 180 register struct afswtch *rafp; 181 182 if (argc < 2) { 183 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s", 184 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 185 "[ netmask mask ] ]\n", 186 "\t[ metric n ]\n", 187 "\t[ mtu n ]\n", 188 "\t[ arp | -arp ]\n", 189 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n"); 190 exit(1); 191 } 192 argc--, argv++; 193 strncpy(name, *argv, sizeof(name)); 194 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 195 argc--, argv++; 196 if (argc > 0) { 197 for (afp = rafp = afs; rafp->af_name; rafp++) 198 if (strcmp(rafp->af_name, *argv) == 0) { 199 afp = rafp; argc--; argv++; 200 break; 201 } 202 rafp = afp; 203 af = ifr.ifr_addr.sa_family = rafp->af_af; 204 } 205 s = socket(af, SOCK_DGRAM, 0); 206 if (s < 0) { 207 perror("ifconfig: socket"); 208 exit(1); 209 } 210 if (!strcmp(name, "-a")) { 211 struct ifconf ifc; 212 #define MAX_INTERFACES 50 /* Yeah right. */ 213 char buffer[MAX_INTERFACES * sizeof(struct ifreq)]; 214 struct ifreq *ifptr, *end; 215 int ifflags; 216 217 ifc.ifc_len = sizeof(buffer); 218 ifc.ifc_buf = buffer; 219 if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) { 220 perror("ifconfig (SIOCGIFCONF)"); 221 exit (1); 222 } 223 ifflags = ifc.ifc_req->ifr_flags; 224 end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 225 ifptr = ifc.ifc_req; 226 while (ifptr < end) { 227 sprintf(ifr.ifr_name,"%s",ifptr->ifr_name); 228 sprintf(name,"%s",ifptr->ifr_name); 229 close(s); 230 s = socket(af, SOCK_DGRAM, 0); 231 if (s < 0) { 232 perror("ifconfig: socket"); 233 exit(1); 234 } 235 if (ifptr->ifr_flags == ifflags) 236 ifconfig(argc,argv,af,rafp); 237 if(ifptr->ifr_addr.sa_len) /* Dohw! */ 238 ifptr = (struct ifreq *) ((caddr_t) ifptr + 239 ifptr->ifr_addr.sa_len - 240 sizeof(struct sockaddr)); 241 ifptr++; 242 } 243 } else 244 ifconfig(argc,argv,af,rafp); 245 246 exit (0); 247 } 248 249 250 251 ifconfig(argc,argv,af,rafp) 252 int argc; 253 char *argv[]; 254 int af; 255 struct afswtch *rafp; 256 { 257 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 258 Perror("ioctl (SIOCGIFFLAGS)"); 259 exit(1); 260 } 261 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 262 flags = ifr.ifr_flags; 263 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 264 perror("ioctl (SIOCGIFMETRIC)"); 265 else 266 metric = ifr.ifr_metric; 267 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 268 perror("ioctl (SIOCGIFMTU)"); 269 else 270 mtu = ifr.ifr_mtu; 271 if (argc == 0) { 272 status(); 273 return(0); 274 } 275 while (argc > 0) { 276 register struct cmd *p; 277 278 for (p = cmds; p->c_name; p++) 279 if (strcmp(*argv, p->c_name) == 0) 280 break; 281 if (p->c_name == 0 && setaddr) 282 p++; /* got src, do dst */ 283 if (p->c_func) { 284 if (p->c_parameter == NEXTARG) { 285 if (argv[1] == NULL) 286 errx(1, "'%s' requires argument", 287 p->c_name); 288 (*p->c_func)(argv[1]); 289 argc--, argv++; 290 } else 291 (*p->c_func)(*argv, p->c_parameter); 292 } 293 argc--, argv++; 294 } 295 if (af == AF_ISO) 296 adjust_nsellength(); 297 if (setipdst && af==AF_NS) { 298 struct nsip_req rq; 299 int size = sizeof(rq); 300 301 rq.rq_ns = addreq.ifra_addr; 302 rq.rq_ip = addreq.ifra_dstaddr; 303 304 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 305 Perror("Encapsulation Routing"); 306 } 307 if (clearaddr) { 308 int ret; 309 strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name); 310 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 311 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 312 /* means no previous address for interface */ 313 } else 314 Perror("ioctl (SIOCDIFADDR)"); 315 } 316 } 317 if (newaddr) { 318 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 319 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 320 Perror("ioctl (SIOCAIFADDR)"); 321 } 322 return(0); 323 } 324 #define RIDADDR 0 325 #define ADDR 1 326 #define MASK 2 327 #define DSTADDR 3 328 329 /*ARGSUSED*/ 330 setifaddr(addr, param) 331 char *addr; 332 short param; 333 { 334 /* 335 * Delay the ioctl to set the interface addr until flags are all set. 336 * The address interpretation may depend on the flags, 337 * and the flags may change when the address is set. 338 */ 339 setaddr++; 340 if (doalias == 0) 341 clearaddr = 1; 342 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 343 } 344 345 setifnetmask(addr) 346 char *addr; 347 { 348 (*afp->af_getaddr)(addr, MASK); 349 } 350 351 setifbroadaddr(addr) 352 char *addr; 353 { 354 (*afp->af_getaddr)(addr, DSTADDR); 355 } 356 357 setifipdst(addr) 358 char *addr; 359 { 360 in_getaddr(addr, DSTADDR); 361 setipdst++; 362 clearaddr = 0; 363 newaddr = 0; 364 } 365 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 366 /*ARGSUSED*/ 367 notealias(addr, param) 368 char *addr; 369 { 370 if (setaddr && doalias == 0 && param < 0) 371 bcopy((caddr_t)rqtosa(af_addreq), 372 (caddr_t)rqtosa(af_ridreq), 373 rqtosa(af_addreq)->sa_len); 374 doalias = param; 375 if (param < 0) { 376 clearaddr = 1; 377 newaddr = 0; 378 } else 379 clearaddr = 0; 380 } 381 382 /*ARGSUSED*/ 383 notrailers(vname, value) 384 char *vname; 385 int value; 386 { 387 printf("Note: trailers are no longer sent, but always received\n"); 388 } 389 390 /*ARGSUSED*/ 391 setifdstaddr(addr, param) 392 char *addr; 393 int param; 394 { 395 (*afp->af_getaddr)(addr, DSTADDR); 396 } 397 398 setifflags(vname, value) 399 char *vname; 400 short value; 401 { 402 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 403 Perror("ioctl (SIOCGIFFLAGS)"); 404 exit(1); 405 } 406 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 407 flags = ifr.ifr_flags; 408 409 if (value < 0) { 410 value = -value; 411 flags &= ~value; 412 } else 413 flags |= value; 414 ifr.ifr_flags = flags; 415 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 416 Perror(vname); 417 } 418 419 setifmetric(val) 420 char *val; 421 { 422 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 423 ifr.ifr_metric = atoi(val); 424 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 425 perror("ioctl (set metric)"); 426 } 427 428 setifmtu(val) 429 char *val; 430 { 431 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 432 ifr.ifr_mtu = atoi(val); 433 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 434 perror("ioctl (set mtu)"); 435 } 436 437 setsnpaoffset(val) 438 char *val; 439 { 440 iso_addreq.ifra_snpaoffset = atoi(val); 441 } 442 443 #define IFFBITS \ 444 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 445 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 446 447 /* 448 * Print the status of the interface. If an address family was 449 * specified, show it and it only; otherwise, show them all. 450 */ 451 status() 452 { 453 register struct afswtch *p = afp; 454 short af = ifr.ifr_addr.sa_family; 455 456 printf("%s: ", name); 457 printb("flags", flags, IFFBITS); 458 if (metric) 459 printf(" metric %d", metric); 460 if (mtu) 461 printf(" mtu %d", mtu); 462 putchar('\n'); 463 if ((p = afp) != NULL) { 464 (*p->af_status)(1); 465 } else for (p = afs; p->af_name; p++) { 466 ifr.ifr_addr.sa_family = p->af_af; 467 (*p->af_status)(0); 468 } 469 } 470 471 in_status(force) 472 int force; 473 { 474 struct sockaddr_in *sin; 475 char *inet_ntoa(); 476 477 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 478 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 479 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 480 if (!force) 481 return; 482 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 483 } else 484 perror("ioctl (SIOCGIFADDR)"); 485 } 486 sin = (struct sockaddr_in *)&ifr.ifr_addr; 487 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 488 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 489 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 490 if (errno != EADDRNOTAVAIL) 491 perror("ioctl (SIOCGIFNETMASK)"); 492 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 493 } else 494 netmask.sin_addr = 495 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 496 if (flags & IFF_POINTOPOINT) { 497 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 498 if (errno == EADDRNOTAVAIL) 499 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 500 else 501 perror("ioctl (SIOCGIFDSTADDR)"); 502 } 503 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 504 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 505 printf("--> %s ", inet_ntoa(sin->sin_addr)); 506 } 507 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr)); 508 if (flags & IFF_BROADCAST) { 509 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 510 if (errno == EADDRNOTAVAIL) 511 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 512 else 513 perror("ioctl (SIOCGIFADDR)"); 514 } 515 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 516 sin = (struct sockaddr_in *)&ifr.ifr_addr; 517 if (sin->sin_addr.s_addr != 0) 518 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 519 } 520 putchar('\n'); 521 } 522 523 524 xns_status(force) 525 int force; 526 { 527 struct sockaddr_ns *sns; 528 529 close(s); 530 s = socket(AF_NS, SOCK_DGRAM, 0); 531 if (s < 0) { 532 if (errno == EPROTONOSUPPORT) 533 return; 534 perror("ifconfig: socket"); 535 exit(1); 536 } 537 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 538 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 539 if (!force) 540 return; 541 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 542 } else 543 perror("ioctl (SIOCGIFADDR)"); 544 } 545 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 546 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 547 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 548 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 549 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 550 if (errno == EADDRNOTAVAIL) 551 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 552 else 553 Perror("ioctl (SIOCGIFDSTADDR)"); 554 } 555 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 556 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 557 printf("--> %s ", ns_ntoa(sns->sns_addr)); 558 } 559 putchar('\n'); 560 } 561 562 iso_status(force) 563 int force; 564 { 565 struct sockaddr_iso *siso; 566 struct iso_ifreq ifr; 567 568 close(s); 569 s = socket(AF_ISO, SOCK_DGRAM, 0); 570 if (s < 0) { 571 if (errno == EPROTONOSUPPORT) 572 return; 573 perror("ifconfig: socket"); 574 exit(1); 575 } 576 bzero((caddr_t)&ifr, sizeof(ifr)); 577 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 578 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) { 579 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 580 if (!force) 581 return; 582 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 583 } else { 584 perror("ioctl (SIOCGIFADDR_ISO)"); 585 exit(1); 586 } 587 } 588 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 589 siso = &ifr.ifr_Addr; 590 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 591 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) { 592 if (errno != EADDRNOTAVAIL) 593 perror("ioctl (SIOCGIFNETMASK_ISO)"); 594 } else { 595 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 596 } 597 if (flags & IFF_POINTOPOINT) { 598 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) { 599 if (errno == EADDRNOTAVAIL) 600 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 601 else 602 Perror("ioctl (SIOCGIFDSTADDR_ISO)"); 603 } 604 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 605 siso = &ifr.ifr_Addr; 606 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 607 } 608 putchar('\n'); 609 } 610 611 kread(addr, buf, size) 612 u_long addr; 613 char *buf; 614 int size; 615 { 616 617 if (kvm_read(kvmd, addr, buf, size) != size) 618 return (-1); 619 return (0); 620 } 621 622 /* Unashamedly stolen from netstat -- maybe someday we can us sysctl() */ 623 ether_status() 624 { 625 struct nlist nl[] = { { "_ifnet" } , "" }; 626 u_long addr, addr2; 627 struct ifnet ifnet; 628 union { 629 struct ifaddr ifa; 630 struct in_ifaddr in; 631 struct ns_ifaddr ns; 632 struct iso_ifaddr iso; 633 } ifaddr; 634 char *cp; 635 struct sockaddr *sa; 636 struct sockaddr_dl *sdl; 637 int n,m; 638 char ifacename[IFNAMSIZ]; 639 640 /* 641 * If we fail here it probably means we don't have permission to 642 * read /dev/kmem. Best to just silently bail out. If we have 643 * an error *after* we succeed in opening /dev/kmem, then we 644 * should report it. 645 */ 646 if ((kvmd = kvm_open(NULL,NULL,NULL,O_RDONLY,NULL)) == NULL) 647 return; 648 if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) { 649 perror("ifconfig: kvm_nlist()"); 650 return; 651 } 652 if (kread(nl[0].n_value, (char *)&addr, sizeof(addr))) { 653 perror("_ifnet"); 654 return; 655 } 656 addr2 = 0; 657 while (addr || addr2) { 658 if (addr2 == 0) { 659 if (kread(addr, (char *)&ifnet, sizeof ifnet) || 660 kread((u_long)ifnet.if_name, ifacename, IFNAMSIZ)){ 661 perror("ifconfig: kvm_read()"); 662 return; 663 } 664 addr = (u_long)ifnet.if_next; 665 addr2 = (u_long)ifnet.if_addrlist; 666 } 667 if (kread(addr2, (char *)&ifaddr, sizeof ifaddr)) { 668 addr2 = 0; 669 continue; 670 } 671 sprintf(ifacename,"%s%d",ifacename, ifnet.if_unit); 672 if (!strncmp(name, ifacename, strlen(name))) { 673 #define CP(x) ((char *)(x)) 674 cp = (CP(ifaddr.ifa.ifa_addr) - CP(addr2)) + 675 CP(&ifaddr); sa = (struct sockaddr *)cp; 676 if (sa->sa_family == AF_LINK) { 677 sdl = (struct sockaddr_dl *)sa; 678 cp = (char *)LLADDR(sdl); 679 if ((n = sdl->sdl_alen) > 0) { 680 printf ("\tether "); 681 while (--n >= 0) 682 m += printf("%02x%c", 683 *cp++ & 0xff, 684 n > 0 ? ':' : ' '); 685 putchar('\n'); 686 } 687 break; 688 } 689 } 690 addr2 = (u_long)ifaddr.ifa.ifa_next; 691 } 692 kvm_close(kvmd); 693 } 694 695 Perror(cmd) 696 char *cmd; 697 { 698 extern int errno; 699 700 switch (errno) { 701 702 case ENXIO: 703 errx(1, "%s: no such interface", cmd); 704 break; 705 706 case EPERM: 707 errx(1, "%s: permission denied", cmd); 708 break; 709 710 default: 711 err(1, "%s", cmd); 712 } 713 } 714 715 struct in_addr inet_makeaddr(); 716 717 #define SIN(x) ((struct sockaddr_in *) &(x)) 718 struct sockaddr_in *sintab[] = { 719 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 720 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 721 722 in_getaddr(s, which) 723 char *s; 724 { 725 register struct sockaddr_in *sin = sintab[which]; 726 struct hostent *hp; 727 struct netent *np; 728 int val; 729 730 sin->sin_len = sizeof(*sin); 731 if (which != MASK) 732 sin->sin_family = AF_INET; 733 734 if ((val = inet_addr(s)) != -1) 735 sin->sin_addr.s_addr = val; 736 else if (hp = gethostbyname(s)) 737 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 738 else if (np = getnetbyname(s)) 739 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 740 else 741 errx(1, "%s: bad value", s); 742 } 743 744 /* 745 * Print a value a la the %b format of the kernel's printf 746 */ 747 printb(s, v, bits) 748 char *s; 749 register char *bits; 750 register unsigned short v; 751 { 752 register int i, any = 0; 753 register char c; 754 755 if (bits && *bits == 8) 756 printf("%s=%o", s, v); 757 else 758 printf("%s=%x", s, v); 759 bits++; 760 if (bits) { 761 putchar('<'); 762 while (i = *bits++) { 763 if (v & (1 << (i-1))) { 764 if (any) 765 putchar(','); 766 any = 1; 767 for (; (c = *bits) > 32; bits++) 768 putchar(c); 769 } else 770 for (; *bits > 32; bits++) 771 ; 772 } 773 putchar('>'); 774 } 775 } 776 777 #define SNS(x) ((struct sockaddr_ns *) &(x)) 778 struct sockaddr_ns *snstab[] = { 779 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 780 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 781 782 xns_getaddr(addr, which) 783 char *addr; 784 { 785 struct sockaddr_ns *sns = snstab[which]; 786 struct ns_addr ns_addr(); 787 788 sns->sns_family = AF_NS; 789 sns->sns_len = sizeof(*sns); 790 sns->sns_addr = ns_addr(addr); 791 if (which == MASK) 792 printf("Attempt to set XNS netmask will be ineffectual\n"); 793 } 794 795 #define SISO(x) ((struct sockaddr_iso *) &(x)) 796 struct sockaddr_iso *sisotab[] = { 797 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 798 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 799 800 iso_getaddr(addr, which) 801 char *addr; 802 { 803 register struct sockaddr_iso *siso = sisotab[which]; 804 struct iso_addr *iso_addr(); 805 siso->siso_addr = *iso_addr(addr); 806 807 if (which == MASK) { 808 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 809 siso->siso_nlen = 0; 810 } else { 811 siso->siso_len = sizeof(*siso); 812 siso->siso_family = AF_ISO; 813 } 814 } 815 816 setnsellength(val) 817 char *val; 818 { 819 nsellength = atoi(val); 820 if (nsellength < 0) 821 errx(1, "Negative NSEL length is absurd"); 822 if (afp == 0 || afp->af_af != AF_ISO) 823 errx(1, "Setting NSEL length valid only for iso"); 824 } 825 826 fixnsel(s) 827 register struct sockaddr_iso *s; 828 { 829 if (s->siso_family == 0) 830 return; 831 s->siso_tlen = nsellength; 832 } 833 834 adjust_nsellength() 835 { 836 fixnsel(sisotab[RIDADDR]); 837 fixnsel(sisotab[ADDR]); 838 fixnsel(sisotab[DSTADDR]); 839 } 840