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