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