1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)ifconfig.c 5.4 (Berkeley) 10/16/91"; 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(); 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", -IFF_NOTRAILERS,setifflags }, 75 { "-trailers", IFF_NOTRAILERS, setifflags }, 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 { "llc0", IFF_LLC0, setifflags } , 95 { "-llc0", -IFF_LLC0, setifflags } , 96 { "llc1", IFF_LLC1, setifflags } , 97 { "-llc1", -IFF_LLC1, setifflags } , 98 { "llc2", IFF_LLC2, setifflags } , 99 { "-llc2", -IFF_LLC2, 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%s", 145 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 146 "[ netmask mask ] ]\n", 147 "\t[ metric n ]\n", 148 "\t[ trailers | -trailers ]\n", 149 "\t[ arp | -arp ]\n", 150 "\t[ llc0 | -llc0 ] [ llc1 | -llc1 ] [ llc2 | -llc2 ] \n"); 151 exit(1); 152 } 153 argc--, argv++; 154 strncpy(name, *argv, sizeof(name)); 155 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 156 argc--, argv++; 157 if (argc > 0) { 158 for (afp = rafp = afs; rafp->af_name; rafp++) 159 if (strcmp(rafp->af_name, *argv) == 0) { 160 afp = rafp; argc--; argv++; 161 break; 162 } 163 rafp = afp; 164 af = ifr.ifr_addr.sa_family = rafp->af_af; 165 } 166 s = socket(af, SOCK_DGRAM, 0); 167 if (s < 0) { 168 perror("ifconfig: socket"); 169 exit(1); 170 } 171 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 172 Perror("ioctl (SIOCGIFFLAGS)"); 173 exit(1); 174 } 175 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 176 flags = ifr.ifr_flags; 177 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 178 perror("ioctl (SIOCGIFMETRIC)"); 179 else 180 metric = ifr.ifr_metric; 181 if (argc == 0) { 182 status(); 183 exit(0); 184 } 185 while (argc > 0) { 186 register struct cmd *p; 187 188 for (p = cmds; p->c_name; p++) 189 if (strcmp(*argv, p->c_name) == 0) 190 break; 191 if (p->c_name == 0 && setaddr) 192 p++; /* got src, do dst */ 193 if (p->c_func) { 194 if (p->c_parameter == NEXTARG) { 195 (*p->c_func)(argv[1]); 196 argc--, argv++; 197 } else 198 (*p->c_func)(*argv, p->c_parameter); 199 } 200 argc--, argv++; 201 } 202 if (af == AF_ISO) 203 adjust_nsellength(); 204 if (setipdst && af==AF_NS) { 205 struct nsip_req rq; 206 int size = sizeof(rq); 207 208 rq.rq_ns = addreq.ifra_addr; 209 rq.rq_ip = addreq.ifra_dstaddr; 210 211 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 212 Perror("Encapsulation Routing"); 213 } 214 if (clearaddr) { 215 int ret; 216 strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name); 217 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 218 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 219 /* means no previous address for interface */ 220 } else 221 Perror("ioctl (SIOCDIFADDR)"); 222 } 223 } 224 if (newaddr) { 225 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 226 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 227 Perror("ioctl (SIOCAIFADDR)"); 228 } 229 exit(0); 230 } 231 #define RIDADDR 0 232 #define ADDR 1 233 #define MASK 2 234 #define DSTADDR 3 235 236 /*ARGSUSED*/ 237 setifaddr(addr, param) 238 char *addr; 239 short param; 240 { 241 /* 242 * Delay the ioctl to set the interface addr until flags are all set. 243 * The address interpretation may depend on the flags, 244 * and the flags may change when the address is set. 245 */ 246 setaddr++; 247 if (doalias == 0) 248 clearaddr = 1; 249 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 250 } 251 252 setifnetmask(addr) 253 char *addr; 254 { 255 (*afp->af_getaddr)(addr, MASK); 256 } 257 258 setifbroadaddr(addr) 259 char *addr; 260 { 261 (*afp->af_getaddr)(addr, DSTADDR); 262 } 263 264 setifipdst(addr) 265 char *addr; 266 { 267 in_getaddr(addr, DSTADDR); 268 setipdst++; 269 clearaddr = 0; 270 newaddr = 0; 271 } 272 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 273 /*ARGSUSED*/ 274 notealias(addr, param) 275 char *addr; 276 { 277 if (setaddr && doalias == 0 && param < 0) 278 bcopy((caddr_t)rqtosa(af_addreq), 279 (caddr_t)rqtosa(af_ridreq), 280 rqtosa(af_addreq)->sa_len); 281 doalias = param; 282 if (param < 0) { 283 clearaddr = 1; 284 newaddr = 0; 285 } else 286 clearaddr = 0; 287 } 288 289 /*ARGSUSED*/ 290 setifdstaddr(addr, param) 291 char *addr; 292 int param; 293 { 294 (*afp->af_getaddr)(addr, DSTADDR); 295 } 296 297 setifflags(vname, value) 298 char *vname; 299 short value; 300 { 301 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 302 Perror("ioctl (SIOCGIFFLAGS)"); 303 exit(1); 304 } 305 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 306 flags = ifr.ifr_flags; 307 308 if (value < 0) { 309 value = -value; 310 flags &= ~value; 311 } else 312 flags |= value; 313 ifr.ifr_flags = flags; 314 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 315 Perror(vname); 316 } 317 318 setifmetric(val) 319 char *val; 320 { 321 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 322 ifr.ifr_metric = atoi(val); 323 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 324 perror("ioctl (set metric)"); 325 } 326 327 setsnpaoffset(val) 328 char *val; 329 { 330 iso_addreq.ifra_snpaoffset = atoi(val); 331 } 332 333 #define IFFBITS \ 334 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 335 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LLC0\16LLC1\16LLC2" 336 337 /* 338 * Print the status of the interface. If an address family was 339 * specified, show it and it only; otherwise, show them all. 340 */ 341 status() 342 { 343 register struct afswtch *p = afp; 344 short af = ifr.ifr_addr.sa_family; 345 346 printf("%s: ", name); 347 printb("flags", flags, IFFBITS); 348 if (metric) 349 printf(" metric %d", metric); 350 putchar('\n'); 351 if ((p = afp) != NULL) { 352 (*p->af_status)(1); 353 } else for (p = afs; p->af_name; p++) { 354 ifr.ifr_addr.sa_family = p->af_af; 355 (*p->af_status)(0); 356 } 357 } 358 359 in_status(force) 360 int force; 361 { 362 struct sockaddr_in *sin; 363 char *inet_ntoa(); 364 365 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 366 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 367 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 368 if (!force) 369 return; 370 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 371 } else 372 perror("ioctl (SIOCGIFADDR)"); 373 } 374 sin = (struct sockaddr_in *)&ifr.ifr_addr; 375 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 376 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 377 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 378 if (errno != EADDRNOTAVAIL) 379 perror("ioctl (SIOCGIFNETMASK)"); 380 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 381 } else 382 netmask.sin_addr = 383 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 384 if (flags & IFF_POINTOPOINT) { 385 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 386 if (errno == EADDRNOTAVAIL) 387 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 388 else 389 perror("ioctl (SIOCGIFDSTADDR)"); 390 } 391 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 392 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 393 printf("--> %s ", inet_ntoa(sin->sin_addr)); 394 } 395 printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 396 if (flags & IFF_BROADCAST) { 397 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 398 if (errno == EADDRNOTAVAIL) 399 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 400 else 401 perror("ioctl (SIOCGIFADDR)"); 402 } 403 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 404 sin = (struct sockaddr_in *)&ifr.ifr_addr; 405 if (sin->sin_addr.s_addr != 0) 406 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 407 } 408 putchar('\n'); 409 } 410 411 412 xns_status(force) 413 int force; 414 { 415 struct sockaddr_ns *sns; 416 417 close(s); 418 s = socket(AF_NS, SOCK_DGRAM, 0); 419 if (s < 0) { 420 if (errno == EPROTONOSUPPORT) 421 return; 422 perror("ifconfig: socket"); 423 exit(1); 424 } 425 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 426 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 427 if (!force) 428 return; 429 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 430 } else 431 perror("ioctl (SIOCGIFADDR)"); 432 } 433 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 434 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 435 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 436 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 437 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 438 if (errno == EADDRNOTAVAIL) 439 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 440 else 441 Perror("ioctl (SIOCGIFDSTADDR)"); 442 } 443 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 444 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 445 printf("--> %s ", ns_ntoa(sns->sns_addr)); 446 } 447 putchar('\n'); 448 } 449 450 iso_status(force) 451 int force; 452 { 453 struct sockaddr_iso *siso; 454 struct iso_ifreq ifr; 455 456 close(s); 457 s = socket(AF_ISO, SOCK_DGRAM, 0); 458 if (s < 0) { 459 if (errno == EPROTONOSUPPORT) 460 return; 461 perror("ifconfig: socket"); 462 exit(1); 463 } 464 bzero((caddr_t)&ifr, sizeof(ifr)); 465 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 466 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) { 467 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 468 if (!force) 469 return; 470 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 471 } else { 472 perror("ioctl (SIOCGIFADDR_ISO)"); 473 exit(1); 474 } 475 } 476 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 477 siso = &ifr.ifr_Addr; 478 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 479 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) { 480 if (errno != EADDRNOTAVAIL) 481 perror("ioctl (SIOCGIFNETMASK_ISO)"); 482 } else { 483 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 484 } 485 if (flags & IFF_POINTOPOINT) { 486 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) { 487 if (errno == EADDRNOTAVAIL) 488 bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr)); 489 else 490 Perror("ioctl (SIOCGIFDSTADDR_ISO)"); 491 } 492 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 493 siso = &ifr.ifr_Addr; 494 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 495 } 496 putchar('\n'); 497 } 498 499 Perror(cmd) 500 char *cmd; 501 { 502 extern int errno; 503 504 fprintf(stderr, "ifconfig: "); 505 switch (errno) { 506 507 case ENXIO: 508 fprintf(stderr, "%s: no such interface\n", cmd); 509 break; 510 511 case EPERM: 512 fprintf(stderr, "%s: permission denied\n", cmd); 513 break; 514 515 default: 516 perror(cmd); 517 } 518 exit(1); 519 } 520 521 struct in_addr inet_makeaddr(); 522 523 #define SIN(x) ((struct sockaddr_in *) &(x)) 524 struct sockaddr_in *sintab[] = { 525 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 526 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 527 528 in_getaddr(s, which) 529 char *s; 530 { 531 register struct sockaddr_in *sin = sintab[which]; 532 struct hostent *hp; 533 struct netent *np; 534 int val; 535 536 sin->sin_len = sizeof(*sin); 537 if (which != MASK) 538 sin->sin_family = AF_INET; 539 540 if ((val = inet_addr(s)) != -1) 541 sin->sin_addr.s_addr = val; 542 else if (hp = gethostbyname(s)) 543 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 544 else if (np = getnetbyname(s)) 545 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 546 else { 547 fprintf(stderr, "%s: bad value\n", s); 548 exit(1); 549 } 550 } 551 552 /* 553 * Print a value a la the %b format of the kernel's printf 554 */ 555 printb(s, v, bits) 556 char *s; 557 register char *bits; 558 register unsigned short v; 559 { 560 register int i, any = 0; 561 register char c; 562 563 if (bits && *bits == 8) 564 printf("%s=%o", s, v); 565 else 566 printf("%s=%x", s, v); 567 bits++; 568 if (bits) { 569 putchar('<'); 570 while (i = *bits++) { 571 if (v & (1 << (i-1))) { 572 if (any) 573 putchar(','); 574 any = 1; 575 for (; (c = *bits) > 32; bits++) 576 putchar(c); 577 } else 578 for (; *bits > 32; bits++) 579 ; 580 } 581 putchar('>'); 582 } 583 } 584 585 #define SNS(x) ((struct sockaddr_ns *) &(x)) 586 struct sockaddr_ns *snstab[] = { 587 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 588 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 589 590 xns_getaddr(addr, which) 591 char *addr; 592 { 593 struct sockaddr_ns *sns = snstab[which]; 594 struct ns_addr ns_addr(); 595 596 sns->sns_family = AF_NS; 597 sns->sns_len = sizeof(*sns); 598 sns->sns_addr = ns_addr(addr); 599 if (which == MASK) 600 printf("Attempt to set XNS netmask will be ineffectual\n"); 601 } 602 603 #define SISO(x) ((struct sockaddr_iso *) &(x)) 604 struct sockaddr_iso *sisotab[] = { 605 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 606 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 607 608 iso_getaddr(addr, which) 609 char *addr; 610 { 611 register struct sockaddr_iso *siso = sisotab[which]; 612 struct iso_addr *iso_addr(); 613 siso->siso_addr = *iso_addr(addr); 614 615 if (which == MASK) { 616 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 617 siso->siso_nlen = 0; 618 } else { 619 siso->siso_len = sizeof(*siso); 620 siso->siso_family = AF_ISO; 621 } 622 } 623 624 setnsellength(val) 625 char *val; 626 { 627 nsellength = atoi(val); 628 if (nsellength < 0) { 629 fprintf(stderr, "Negative NSEL length is absurd\n"); 630 exit (1); 631 } 632 if (afp == 0 || afp->af_af != AF_ISO) { 633 fprintf(stderr, "Setting NSEL length valid only for iso\n"); 634 exit (1); 635 } 636 } 637 638 fixnsel(s) 639 register struct sockaddr_iso *s; 640 { 641 if (s->siso_family == 0) 642 return; 643 s->siso_tlen = nsellength; 644 } 645 646 adjust_nsellength() 647 { 648 fixnsel(sisotab[RIDADDR]); 649 fixnsel(sisotab[ADDR]); 650 fixnsel(sisotab[DSTADDR]); 651 } 652