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