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