1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1983, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 02/16/94"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/socket.h> 20 #include <sys/ioctl.h> 21 22 #include <net/if.h> 23 #include <netinet/in.h> 24 #include <arpa/inet.h> 25 26 #define NSIP 27 #include <netns/ns.h> 28 #include <netns/ns_if.h> 29 #include <netdb.h> 30 31 #define EON 32 #include <netiso/iso.h> 33 #include <netiso/iso_var.h> 34 #include <sys/protosw.h> 35 36 #include <ctype.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 struct ifreq ifr, ridreq; 45 struct ifaliasreq addreq; 46 struct iso_ifreq iso_ridreq; 47 struct iso_aliasreq iso_addreq; 48 struct sockaddr_in netmask; 49 50 char name[30]; 51 int flags; 52 int metric; 53 int nsellength = 1; 54 int setaddr; 55 int setipdst; 56 int doalias; 57 int clearaddr; 58 int newaddr = 1; 59 int s; 60 extern int errno; 61 62 int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 63 int setifmetric(), setifbroadaddr(), setifipdst(); 64 int notealias(), setsnpaoffset(), setnsellength(), notrailers(); 65 66 #define NEXTARG 0xffffff 67 68 struct cmd { 69 char *c_name; 70 int c_parameter; /* NEXTARG means next argv */ 71 int (*c_func)(); 72 } cmds[] = { 73 { "up", IFF_UP, setifflags } , 74 { "down", -IFF_UP, setifflags }, 75 { "trailers", -1, notrailers }, 76 { "-trailers", 1, notrailers }, 77 { "arp", -IFF_NOARP, setifflags }, 78 { "-arp", IFF_NOARP, setifflags }, 79 { "debug", IFF_DEBUG, setifflags }, 80 { "-debug", -IFF_DEBUG, setifflags }, 81 { "alias", IFF_UP, notealias }, 82 { "-alias", -IFF_UP, notealias }, 83 { "delete", -IFF_UP, notealias }, 84 #ifdef notdef 85 #define EN_SWABIPS 0x1000 86 { "swabips", EN_SWABIPS, setifflags }, 87 { "-swabips", -EN_SWABIPS, setifflags }, 88 #endif 89 { "netmask", NEXTARG, setifnetmask }, 90 { "metric", NEXTARG, setifmetric }, 91 { "broadcast", NEXTARG, setifbroadaddr }, 92 { "ipdst", NEXTARG, setifipdst }, 93 { "snpaoffset", NEXTARG, setsnpaoffset }, 94 { "nsellength", NEXTARG, setnsellength }, 95 { "link0", IFF_LINK0, setifflags } , 96 { "-link0", -IFF_LINK0, setifflags } , 97 { "link1", IFF_LINK1, setifflags } , 98 { "-link1", -IFF_LINK1, setifflags } , 99 { "link2", IFF_LINK2, setifflags } , 100 { "-link2", -IFF_LINK2, setifflags } , 101 { 0, 0, setifaddr }, 102 { 0, 0, setifdstaddr }, 103 }; 104 105 /* 106 * XNS support liberally adapted from code written at the University of 107 * Maryland principally by James O'Toole and Chris Torek. 108 */ 109 int in_status(), in_getaddr(); 110 int xns_status(), xns_getaddr(); 111 int iso_status(), iso_getaddr(); 112 113 /* Known address families */ 114 struct afswtch { 115 char *af_name; 116 short af_af; 117 int (*af_status)(); 118 int (*af_getaddr)(); 119 int af_difaddr; 120 int af_aifaddr; 121 caddr_t af_ridreq; 122 caddr_t af_addreq; 123 } afs[] = { 124 #define C(x) ((caddr_t) &x) 125 { "inet", AF_INET, in_status, in_getaddr, 126 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 127 { "ns", AF_NS, xns_status, xns_getaddr, 128 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 129 { "iso", AF_ISO, iso_status, iso_getaddr, 130 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) }, 131 { 0, 0, 0, 0 } 132 }; 133 134 struct afswtch *afp; /*the address family being set or asked about*/ 135 136 main(argc, argv) 137 int argc; 138 char *argv[]; 139 { 140 int af = AF_INET; 141 register struct afswtch *rafp; 142 143 if (argc < 2) { 144 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s", 145 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 146 "[ netmask mask ] ]\n", 147 "\t[ metric n ]\n", 148 "\t[ arp | -arp ]\n", 149 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n"); 150 exit(1); 151 } 152 argc--, argv++; 153 strncpy(name, *argv, sizeof(name)); 154 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 155 argc--, argv++; 156 if (argc > 0) { 157 for (afp = rafp = afs; rafp->af_name; rafp++) 158 if (strcmp(rafp->af_name, *argv) == 0) { 159 afp = rafp; argc--; argv++; 160 break; 161 } 162 rafp = afp; 163 af = ifr.ifr_addr.sa_family = rafp->af_af; 164 } 165 s = socket(af, SOCK_DGRAM, 0); 166 if (s < 0) { 167 perror("ifconfig: socket"); 168 exit(1); 169 } 170 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 171 Perror("ioctl (SIOCGIFFLAGS)"); 172 exit(1); 173 } 174 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 175 flags = ifr.ifr_flags; 176 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 177 perror("ioctl (SIOCGIFMETRIC)"); 178 else 179 metric = ifr.ifr_metric; 180 if (argc == 0) { 181 status(); 182 exit(0); 183 } 184 while (argc > 0) { 185 register struct cmd *p; 186 187 for (p = cmds; p->c_name; p++) 188 if (strcmp(*argv, p->c_name) == 0) 189 break; 190 if (p->c_name == 0 && setaddr) 191 p++; /* got src, do dst */ 192 if (p->c_func) { 193 if (p->c_parameter == NEXTARG) { 194 if (argv[1] == NULL) 195 errx(1, "'%s' requires argument", 196 p->c_name); 197 (*p->c_func)(argv[1]); 198 argc--, argv++; 199 } else 200 (*p->c_func)(*argv, p->c_parameter); 201 } 202 argc--, argv++; 203 } 204 if (af == AF_ISO) 205 adjust_nsellength(); 206 if (setipdst && af==AF_NS) { 207 struct nsip_req rq; 208 int size = sizeof(rq); 209 210 rq.rq_ns = addreq.ifra_addr; 211 rq.rq_ip = addreq.ifra_dstaddr; 212 213 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 214 Perror("Encapsulation Routing"); 215 } 216 if (clearaddr) { 217 int ret; 218 strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name); 219 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 220 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 221 /* means no previous address for interface */ 222 } else 223 Perror("ioctl (SIOCDIFADDR)"); 224 } 225 } 226 if (newaddr) { 227 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 228 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 229 Perror("ioctl (SIOCAIFADDR)"); 230 } 231 exit(0); 232 } 233 #define RIDADDR 0 234 #define ADDR 1 235 #define MASK 2 236 #define DSTADDR 3 237 238 /*ARGSUSED*/ 239 setifaddr(addr, param) 240 char *addr; 241 short param; 242 { 243 /* 244 * Delay the ioctl to set the interface addr until flags are all set. 245 * The address interpretation may depend on the flags, 246 * and the flags may change when the address is set. 247 */ 248 setaddr++; 249 if (doalias == 0) 250 clearaddr = 1; 251 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 252 } 253 254 setifnetmask(addr) 255 char *addr; 256 { 257 (*afp->af_getaddr)(addr, MASK); 258 } 259 260 setifbroadaddr(addr) 261 char *addr; 262 { 263 (*afp->af_getaddr)(addr, DSTADDR); 264 } 265 266 setifipdst(addr) 267 char *addr; 268 { 269 in_getaddr(addr, DSTADDR); 270 setipdst++; 271 clearaddr = 0; 272 newaddr = 0; 273 } 274 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 275 /*ARGSUSED*/ 276 notealias(addr, param) 277 char *addr; 278 { 279 if (setaddr && doalias == 0 && param < 0) 280 bcopy((caddr_t)rqtosa(af_addreq), 281 (caddr_t)rqtosa(af_ridreq), 282 rqtosa(af_addreq)->sa_len); 283 doalias = param; 284 if (param < 0) { 285 clearaddr = 1; 286 newaddr = 0; 287 } else 288 clearaddr = 0; 289 } 290 291 /*ARGSUSED*/ 292 notrailers(vname, value) 293 char *vname; 294 int value; 295 { 296 printf("Note: trailers are no longer sent, but always received\n"); 297 } 298 299 /*ARGSUSED*/ 300 setifdstaddr(addr, param) 301 char *addr; 302 int param; 303 { 304 (*afp->af_getaddr)(addr, DSTADDR); 305 } 306 307 setifflags(vname, value) 308 char *vname; 309 short value; 310 { 311 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 312 Perror("ioctl (SIOCGIFFLAGS)"); 313 exit(1); 314 } 315 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 316 flags = ifr.ifr_flags; 317 318 if (value < 0) { 319 value = -value; 320 flags &= ~value; 321 } else 322 flags |= value; 323 ifr.ifr_flags = flags; 324 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 325 Perror(vname); 326 } 327 328 setifmetric(val) 329 char *val; 330 { 331 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 332 ifr.ifr_metric = atoi(val); 333 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 334 perror("ioctl (set metric)"); 335 } 336 337 setsnpaoffset(val) 338 char *val; 339 { 340 iso_addreq.ifra_snpaoffset = atoi(val); 341 } 342 343 #define IFFBITS \ 344 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 345 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 346 347 /* 348 * Print the status of the interface. If an address family was 349 * specified, show it and it only; otherwise, show them all. 350 */ 351 status() 352 { 353 register struct afswtch *p = afp; 354 short af = ifr.ifr_addr.sa_family; 355 356 printf("%s: ", name); 357 printb("flags", flags, IFFBITS); 358 if (metric) 359 printf(" metric %d", metric); 360 putchar('\n'); 361 if ((p = afp) != NULL) { 362 (*p->af_status)(1); 363 } else for (p = afs; p->af_name; p++) { 364 ifr.ifr_addr.sa_family = p->af_af; 365 (*p->af_status)(0); 366 } 367 } 368 369 in_status(force) 370 int force; 371 { 372 struct sockaddr_in *sin; 373 char *inet_ntoa(); 374 375 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 376 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 377 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 378 if (!force) 379 return; 380 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 381 } else 382 perror("ioctl (SIOCGIFADDR)"); 383 } 384 sin = (struct sockaddr_in *)&ifr.ifr_addr; 385 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 386 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 387 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 388 if (errno != EADDRNOTAVAIL) 389 perror("ioctl (SIOCGIFNETMASK)"); 390 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 391 } else 392 netmask.sin_addr = 393 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 394 if (flags & IFF_POINTOPOINT) { 395 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 396 if (errno == EADDRNOTAVAIL) 397 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 398 else 399 perror("ioctl (SIOCGIFDSTADDR)"); 400 } 401 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 402 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 403 printf("--> %s ", inet_ntoa(sin->sin_addr)); 404 } 405 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr)); 406 if (flags & IFF_BROADCAST) { 407 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 408 if (errno == EADDRNOTAVAIL) 409 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 410 else 411 perror("ioctl (SIOCGIFADDR)"); 412 } 413 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 414 sin = (struct sockaddr_in *)&ifr.ifr_addr; 415 if (sin->sin_addr.s_addr != 0) 416 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 417 } 418 putchar('\n'); 419 } 420 421 422 xns_status(force) 423 int force; 424 { 425 struct sockaddr_ns *sns; 426 427 close(s); 428 s = socket(AF_NS, SOCK_DGRAM, 0); 429 if (s < 0) { 430 if (errno == EPROTONOSUPPORT) 431 return; 432 perror("ifconfig: socket"); 433 exit(1); 434 } 435 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 436 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 437 if (!force) 438 return; 439 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 440 } else 441 perror("ioctl (SIOCGIFADDR)"); 442 } 443 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 444 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 445 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 446 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 447 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 448 if (errno == EADDRNOTAVAIL) 449 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 450 else 451 Perror("ioctl (SIOCGIFDSTADDR)"); 452 } 453 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 454 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 455 printf("--> %s ", ns_ntoa(sns->sns_addr)); 456 } 457 putchar('\n'); 458 } 459 460 iso_status(force) 461 int force; 462 { 463 struct sockaddr_iso *siso; 464 struct iso_ifreq ifr; 465 466 close(s); 467 s = socket(AF_ISO, SOCK_DGRAM, 0); 468 if (s < 0) { 469 if (errno == EPROTONOSUPPORT) 470 return; 471 perror("ifconfig: socket"); 472 exit(1); 473 } 474 bzero((caddr_t)&ifr, sizeof(ifr)); 475 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 476 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) { 477 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 478 if (!force) 479 return; 480 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 481 } else { 482 perror("ioctl (SIOCGIFADDR_ISO)"); 483 exit(1); 484 } 485 } 486 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 487 siso = &ifr.ifr_Addr; 488 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 489 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) { 490 if (errno != EADDRNOTAVAIL) 491 perror("ioctl (SIOCGIFNETMASK_ISO)"); 492 } else { 493 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 494 } 495 if (flags & IFF_POINTOPOINT) { 496 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) { 497 if (errno == EADDRNOTAVAIL) 498 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 499 else 500 Perror("ioctl (SIOCGIFDSTADDR_ISO)"); 501 } 502 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 503 siso = &ifr.ifr_Addr; 504 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 505 } 506 putchar('\n'); 507 } 508 509 Perror(cmd) 510 char *cmd; 511 { 512 extern int errno; 513 514 switch (errno) { 515 516 case ENXIO: 517 errx(1, "%s: no such interface", cmd); 518 break; 519 520 case EPERM: 521 errx(1, "%s: permission denied", cmd); 522 break; 523 524 default: 525 err(1, "%s", cmd); 526 } 527 } 528 529 struct in_addr inet_makeaddr(); 530 531 #define SIN(x) ((struct sockaddr_in *) &(x)) 532 struct sockaddr_in *sintab[] = { 533 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 534 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 535 536 in_getaddr(s, which) 537 char *s; 538 { 539 register struct sockaddr_in *sin = sintab[which]; 540 struct hostent *hp; 541 struct netent *np; 542 int val; 543 544 sin->sin_len = sizeof(*sin); 545 if (which != MASK) 546 sin->sin_family = AF_INET; 547 548 if ((val = inet_addr(s)) != -1) 549 sin->sin_addr.s_addr = val; 550 else if (hp = gethostbyname(s)) 551 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 552 else if (np = getnetbyname(s)) 553 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 554 else 555 errx(1, "%s: bad value", s); 556 } 557 558 /* 559 * Print a value a la the %b format of the kernel's printf 560 */ 561 printb(s, v, bits) 562 char *s; 563 register char *bits; 564 register unsigned short v; 565 { 566 register int i, any = 0; 567 register char c; 568 569 if (bits && *bits == 8) 570 printf("%s=%o", s, v); 571 else 572 printf("%s=%x", s, v); 573 bits++; 574 if (bits) { 575 putchar('<'); 576 while (i = *bits++) { 577 if (v & (1 << (i-1))) { 578 if (any) 579 putchar(','); 580 any = 1; 581 for (; (c = *bits) > 32; bits++) 582 putchar(c); 583 } else 584 for (; *bits > 32; bits++) 585 ; 586 } 587 putchar('>'); 588 } 589 } 590 591 #define SNS(x) ((struct sockaddr_ns *) &(x)) 592 struct sockaddr_ns *snstab[] = { 593 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 594 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 595 596 xns_getaddr(addr, which) 597 char *addr; 598 { 599 struct sockaddr_ns *sns = snstab[which]; 600 struct ns_addr ns_addr(); 601 602 sns->sns_family = AF_NS; 603 sns->sns_len = sizeof(*sns); 604 sns->sns_addr = ns_addr(addr); 605 if (which == MASK) 606 printf("Attempt to set XNS netmask will be ineffectual\n"); 607 } 608 609 #define SISO(x) ((struct sockaddr_iso *) &(x)) 610 struct sockaddr_iso *sisotab[] = { 611 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 612 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 613 614 iso_getaddr(addr, which) 615 char *addr; 616 { 617 register struct sockaddr_iso *siso = sisotab[which]; 618 struct iso_addr *iso_addr(); 619 siso->siso_addr = *iso_addr(addr); 620 621 if (which == MASK) { 622 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 623 siso->siso_nlen = 0; 624 } else { 625 siso->siso_len = sizeof(*siso); 626 siso->siso_family = AF_ISO; 627 } 628 } 629 630 setnsellength(val) 631 char *val; 632 { 633 nsellength = atoi(val); 634 if (nsellength < 0) 635 errx(1, "Negative NSEL length is absurd"); 636 if (afp == 0 || afp->af_af != AF_ISO) 637 errx(1, "Setting NSEL length valid only for iso"); 638 } 639 640 fixnsel(s) 641 register struct sockaddr_iso *s; 642 { 643 if (s->siso_family == 0) 644 return; 645 s->siso_tlen = nsellength; 646 } 647 648 adjust_nsellength() 649 { 650 fixnsel(sisotab[RIDADDR]); 651 fixnsel(sisotab[ADDR]); 652 fixnsel(sisotab[DSTADDR]); 653 } 654