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