1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)ifconfig.c 4.18 (Berkeley) 5/22/86"; 15: #endif not lint 16: 17: #include <sys/types.h> 18: #include <sys/socket.h> 19: #include <sys/ioctl.h> 20: 21: #include <net/if.h> 22: #include <netinet/in.h> 23: 24: #define NSIP 25: #include <netns/ns.h> 26: #include <netns/ns_if.h> 27: 28: #include <stdio.h> 29: #include <errno.h> 30: #include <ctype.h> 31: #include <netdb.h> 32: 33: extern int errno; 34: struct ifreq ifr; 35: struct sockaddr_in sin = { AF_INET }; 36: struct sockaddr_in broadaddr; 37: struct sockaddr_in netmask = { AF_INET }; 38: struct sockaddr_in ipdst = { AF_INET }; 39: char name[30]; 40: int flags; 41: int metric; 42: int setaddr; 43: int setmask; 44: int setbroadaddr; 45: int setipdst; 46: int s; 47: extern int errno; 48: 49: int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 50: int setifmetric(), setifbroadaddr(), setifipdst(); 51: 52: #define NEXTARG 0xffffff 53: 54: struct cmd { 55: char *c_name; 56: int c_parameter; /* NEXTARG means next argv */ 57: int (*c_func)(); 58: } cmds[] = { 59: { "up", IFF_UP, setifflags } , 60: { "down", -IFF_UP, setifflags }, 61: { "trailers", -IFF_NOTRAILERS,setifflags }, 62: { "-trailers", IFF_NOTRAILERS, setifflags }, 63: { "arp", -IFF_NOARP, setifflags }, 64: { "-arp", IFF_NOARP, setifflags }, 65: { "debug", IFF_DEBUG, setifflags }, 66: { "-debug", -IFF_DEBUG, setifflags }, 67: #ifdef notdef 68: #define EN_SWABIPS 0x1000 69: { "swabips", EN_SWABIPS, setifflags }, 70: { "-swabips", -EN_SWABIPS, setifflags }, 71: #endif 72: { "netmask", NEXTARG, setifnetmask }, 73: { "metric", NEXTARG, setifmetric }, 74: { "broadcast", NEXTARG, setifbroadaddr }, 75: { "ipdst", NEXTARG, setifipdst }, 76: { 0, 0, setifaddr }, 77: { 0, 0, setifdstaddr }, 78: }; 79: 80: /* 81: * XNS support liberally adapted from 82: * code written at the University of Maryland 83: * principally by James O'Toole and Chris Torek. 84: */ 85: 86: int in_status(), in_getaddr(); 87: int xns_status(), xns_getaddr(); 88: 89: /* Known address families */ 90: struct afswtch { 91: char *af_name; 92: short af_af; 93: int (*af_status)(); 94: int (*af_getaddr)(); 95: } afs[] = { 96: { "inet", AF_INET, in_status, in_getaddr }, 97: { "ns", AF_NS, xns_status, xns_getaddr }, 98: { 0, 0, 0, 0 } 99: }; 100: 101: struct afswtch *afp; /*the address family being set or asked about*/ 102: 103: main(argc, argv) 104: int argc; 105: char *argv[]; 106: { 107: int af = AF_INET; 108: 109: if (argc < 2) { 110: fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s", 111: "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 112: "[ netmask mask ] ]\n", 113: "\t[ metric n ]\n", 114: "\t[ trailers | -trailers ]\n", 115: "\t[ arp | -arp ]\n"); 116: exit(1); 117: } 118: argc--, argv++; 119: strncpy(name, *argv, sizeof(name)); 120: strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 121: argc--, argv++; 122: if (argc > 0) { 123: struct afswtch *myafp; 124: 125: for (myafp = afp = afs; myafp->af_name; myafp++) 126: if (strcmp(myafp->af_name, *argv) == 0) { 127: afp = myafp; argc--; argv++; 128: break; 129: } 130: af = ifr.ifr_addr.sa_family = afp->af_af; 131: } 132: s = socket(af, SOCK_DGRAM, 0); 133: if (s < 0) { 134: perror("ifconfig: socket"); 135: exit(1); 136: } 137: if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 138: Perror("ioctl (SIOCGIFFLAGS)"); 139: exit(1); 140: } 141: strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 142: flags = ifr.ifr_flags; 143: if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 144: perror("ioctl (SIOCGIFMETRIC)"); 145: else 146: metric = ifr.ifr_metric; 147: if (argc == 0) { 148: status(); 149: exit(0); 150: } 151: while (argc > 0) { 152: register struct cmd *p; 153: 154: for (p = cmds; p->c_name; p++) 155: if (strcmp(*argv, p->c_name) == 0) 156: break; 157: if (p->c_name == 0 && setaddr) 158: p++; /* got src, do dst */ 159: if (p->c_func) { 160: if (p->c_parameter == NEXTARG) { 161: (*p->c_func)(argv[1]); 162: argc--, argv++; 163: } else 164: (*p->c_func)(*argv, p->c_parameter); 165: } 166: argc--, argv++; 167: } 168: if ((setmask || setaddr) && (af == AF_INET)) { 169: /* 170: * If setting the address and not the mask, 171: * clear any existing mask and the kernel will then 172: * assign the default. If setting both, 173: * set the mask first, so the address will be 174: * interpreted correctly. 175: */ 176: ifr.ifr_addr = *(struct sockaddr *)&netmask; 177: if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 178: Perror("ioctl (SIOCSIFNETMASK)"); 179: } 180: if (setipdst && af==AF_NS) { 181: struct nsip_req rq; 182: int size = sizeof(rq); 183: 184: rq.rq_ns = *(struct sockaddr *) &sin; 185: rq.rq_ip = *(struct sockaddr *) &ipdst; 186: 187: if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 188: Perror("Encapsulation Routing"); 189: setaddr = 0; 190: } 191: if (setaddr) { 192: ifr.ifr_addr = *(struct sockaddr *) &sin; 193: if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 194: Perror("ioctl (SIOCSIFADDR)"); 195: } 196: if (setbroadaddr) { 197: ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 198: if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 199: Perror("ioctl (SIOCSIFBRDADDR)"); 200: } 201: exit(0); 202: } 203: 204: /*ARGSUSED*/ 205: setifaddr(addr, param) 206: char *addr; 207: short param; 208: { 209: /* 210: * Delay the ioctl to set the interface addr until flags are all set. 211: * The address interpretation may depend on the flags, 212: * and the flags may change when the address is set. 213: */ 214: setaddr++; 215: (*afp->af_getaddr)(addr, &sin); 216: } 217: 218: setifnetmask(addr) 219: char *addr; 220: { 221: in_getaddr(addr, &netmask); 222: setmask++; 223: } 224: 225: setifbroadaddr(addr) 226: char *addr; 227: { 228: (*afp->af_getaddr)(addr, &broadaddr); 229: setbroadaddr++; 230: } 231: 232: setifipdst(addr) 233: char *addr; 234: { 235: in_getaddr(addr, &ipdst); 236: setipdst++; 237: } 238: 239: /*ARGSUSED*/ 240: setifdstaddr(addr, param) 241: char *addr; 242: int param; 243: { 244: 245: (*afp->af_getaddr)(addr, &ifr.ifr_addr); 246: if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 247: Perror("ioctl (SIOCSIFDSTADDR)"); 248: } 249: 250: setifflags(vname, value) 251: char *vname; 252: short value; 253: { 254: if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 255: Perror("ioctl (SIOCGIFFLAGS)"); 256: exit(1); 257: } 258: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 259: flags = ifr.ifr_flags; 260: 261: if (value < 0) { 262: value = -value; 263: flags &= ~value; 264: } else 265: flags |= value; 266: ifr.ifr_flags = flags; 267: if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 268: Perror(vname); 269: } 270: 271: setifmetric(val) 272: char *val; 273: { 274: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 275: ifr.ifr_metric = atoi(val); 276: if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 277: perror("ioctl (set metric)"); 278: } 279: 280: #define IFFBITS \ 281: "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 282: " 283: 284: /* 285: * Print the status of the interface. If an address family was 286: * specified, show it and it only; otherwise, show them all. 287: */ 288: status() 289: { 290: register struct afswtch *p = afp; 291: short af = ifr.ifr_addr.sa_family; 292: 293: printf("%s: ", name); 294: printb("flags", flags, IFFBITS); 295: if (metric) 296: printf(" metric %d", metric); 297: putchar('\n'); 298: if ((p = afp) != NULL) { 299: (*p->af_status)(1); 300: } else for (p = afs; p->af_name; p++) { 301: ifr.ifr_addr.sa_family = p->af_af; 302: (*p->af_status)(0); 303: } 304: } 305: 306: in_status(force) 307: int force; 308: { 309: struct sockaddr_in *sin; 310: char *inet_ntoa(); 311: 312: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 313: if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 314: if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 315: if (!force) 316: return; 317: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 318: } else 319: perror("ioctl (SIOCGIFADDR)"); 320: } 321: sin = (struct sockaddr_in *)&ifr.ifr_addr; 322: printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 323: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 324: if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 325: if (errno != EADDRNOTAVAIL) 326: perror("ioctl (SIOCGIFNETMASK)"); 327: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 328: } else 329: netmask.sin_addr = 330: ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 331: if (flags & IFF_POINTOPOINT) { 332: if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 333: if (errno == EADDRNOTAVAIL) 334: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 335: else 336: perror("ioctl (SIOCGIFDSTADDR)"); 337: } 338: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 339: sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 340: printf("--> %s ", inet_ntoa(sin->sin_addr)); 341: } 342: printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 343: if (flags & IFF_BROADCAST) { 344: if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 345: if (errno == EADDRNOTAVAIL) 346: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 347: else 348: perror("ioctl (SIOCGIFADDR)"); 349: } 350: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 351: sin = (struct sockaddr_in *)&ifr.ifr_addr; 352: if (sin->sin_addr.s_addr != 0) 353: printf("broadcast %s", inet_ntoa(sin->sin_addr)); 354: } 355: putchar('\n'); 356: } 357: 358: 359: xns_status(force) 360: int force; 361: { 362: struct sockaddr_ns *sns; 363: 364: close(s); 365: s = socket(AF_NS, SOCK_DGRAM, 0); 366: if (s < 0) { 367: if (errno == EAFNOSUPPORT) 368: return; 369: perror("ifconfig: socket"); 370: exit(1); 371: } 372: if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 373: if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 374: if (!force) 375: return; 376: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 377: } else 378: perror("ioctl (SIOCGIFADDR)"); 379: } 380: strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 381: sns = (struct sockaddr_ns *)&ifr.ifr_addr; 382: printf("\tns %s ", ns_ntoa(sns->sns_addr)); 383: if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 384: if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 385: if (errno == EADDRNOTAVAIL) 386: bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 387: else 388: Perror("ioctl (SIOCGIFDSTADDR)"); 389: } 390: strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 391: sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 392: printf("--> %s ", ns_ntoa(sns->sns_addr)); 393: } 394: putchar('\n'); 395: } 396: 397: Perror(cmd) 398: char *cmd; 399: { 400: extern int errno; 401: 402: fprintf(stderr, "ifconfig: "); 403: switch (errno) { 404: 405: case ENXIO: 406: fprintf(stderr, "%s: no such interface\n", cmd); 407: break; 408: 409: case EPERM: 410: fprintf(stderr, "%s: permission denied\n", cmd); 411: break; 412: 413: default: 414: perror(cmd); 415: } 416: exit(1); 417: } 418: 419: struct in_addr inet_makeaddr(); 420: 421: in_getaddr(s, saddr) 422: char *s; 423: struct sockaddr *saddr; 424: { 425: register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 426: struct hostent *hp; 427: struct netent *np; 428: int val; 429: 430: sin->sin_family = AF_INET; 431: val = inet_addr(s); 432: if (val != -1) { 433: sin->sin_addr.s_addr = val; 434: return; 435: } 436: hp = gethostbyname(s); 437: if (hp) { 438: sin->sin_family = hp->h_addrtype; 439: bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 440: return; 441: } 442: np = getnetbyname(s); 443: if (np) { 444: sin->sin_family = np->n_addrtype; 445: sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 446: return; 447: } 448: fprintf(stderr, "%s: bad value\n", s); 449: exit(1); 450: } 451: 452: /* 453: * Print a value a la the %b format of the kernel's printf 454: */ 455: printb(s, v, bits) 456: char *s; 457: register char *bits; 458: register unsigned short v; 459: { 460: register int i, any = 0; 461: register char c; 462: 463: if (bits && *bits == 8) 464: printf("%s=%o", s, v); 465: else 466: printf("%s=%x", s, v); 467: bits++; 468: if (bits) { 469: putchar('<'); 470: while (i = *bits++) { 471: if (v & (1 << (i-1))) { 472: if (any) 473: putchar(','); 474: any = 1; 475: for (; (c = *bits) > 32; bits++) 476: putchar(c); 477: } else 478: for (; *bits > 32; bits++) 479: ; 480: } 481: putchar('>'); 482: } 483: } 484: 485: xns_getaddr(addr, saddr) 486: char *addr; 487: struct sockaddr *saddr; 488: { 489: struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 490: struct ns_addr ns_addr(); 491: sns->sns_family = AF_NS; 492: sns->sns_addr = ns_addr(addr); 493: }