1*21811Skarels /* 2*21811Skarels * Copyright (c) 1983 Regents of the University of California. 3*21811Skarels * All rights reserved. The Berkeley software License Agreement 4*21811Skarels * specifies the terms and conditions for redistribution. 5*21811Skarels */ 6*21811Skarels 714869Ssam #ifndef lint 8*21811Skarels char copyright[] = 9*21811Skarels "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*21811Skarels All rights reserved.\n"; 11*21811Skarels #endif not lint 1214869Ssam 13*21811Skarels #ifndef lint 14*21811Skarels static char sccsid[] = "@(#)ifconfig.c 4.11 (Berkeley) 06/03/85"; 15*21811Skarels #endif not lint 16*21811Skarels 17*21811Skarels 1814869Ssam #include <sys/types.h> 1914869Ssam #include <sys/socket.h> 2014869Ssam #include <sys/ioctl.h> 2114869Ssam 2214869Ssam #include <netinet/in.h> 2314869Ssam #include <net/if.h> 2414869Ssam 2514869Ssam #include <stdio.h> 2614869Ssam #include <errno.h> 2714869Ssam #include <ctype.h> 2814869Ssam #include <netdb.h> 2914869Ssam 3014869Ssam struct ifreq ifr; 3114869Ssam struct sockaddr_in sin = { AF_INET }; 32*21811Skarels struct sockaddr_in broadaddr; 33*21811Skarels struct sockaddr_in netmask = { AF_INET }; 3414869Ssam char name[30]; 35*21811Skarels int flags; 3616329Skarels int setaddr; 37*21811Skarels int setmask; 38*21811Skarels int setbroadaddr; 3914869Ssam int s; 40*21811Skarels extern int errno; 4114869Ssam 42*21811Skarels int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 43*21811Skarels int setifbroadaddr(); 4414869Ssam 45*21811Skarels #define NEXTARG 0xffffff 46*21811Skarels 4714869Ssam struct cmd { 4814869Ssam char *c_name; 49*21811Skarels int c_parameter; /* NEXTARG means next argv */ 5014869Ssam int (*c_func)(); 5114869Ssam } cmds[] = { 5214869Ssam { "up", IFF_UP, setifflags } , 5314869Ssam { "down", -IFF_UP, setifflags }, 5414869Ssam { "trailers", -IFF_NOTRAILERS,setifflags }, 5514869Ssam { "-trailers", IFF_NOTRAILERS, setifflags }, 5615359Skarels { "arp", -IFF_NOARP, setifflags }, 5715359Skarels { "-arp", IFF_NOARP, setifflags }, 58*21811Skarels #ifdef IFF_LOCAL 5916329Skarels { "local", IFF_LOCAL, setifflags }, 6016329Skarels { "-local", -IFF_LOCAL, setifflags }, 61*21811Skarels #endif 6215286Sleres { "debug", IFF_DEBUG, setifflags }, 6315286Sleres { "-debug", -IFF_DEBUG, setifflags }, 6415004Ssam #ifdef notdef 65*21811Skarels #define EN_SWABIPS 0x1000 6615004Ssam { "swabips", EN_SWABIPS, setifflags }, 6715004Ssam { "-swabips", -EN_SWABIPS, setifflags }, 6815004Ssam #endif 69*21811Skarels { "netmask", NEXTARG, setifnetmask }, 70*21811Skarels { "broadcast", NEXTARG, setifbroadaddr }, 7114869Ssam { 0, 0, setifaddr }, 7217218Stef { 0, 0, setifdstaddr }, 7314869Ssam }; 7414869Ssam 7514869Ssam main(argc, argv) 7614869Ssam int argc; 7714869Ssam char *argv[]; 7814869Ssam { 7914869Ssam 8014869Ssam if (argc < 2) { 8114869Ssam fprintf(stderr, "usage: ifconfig interface %s %s %s\n", 8217218Stef "[ address [ dest_addr ] ] [ up ] [ down ]", 83*21811Skarels "[ netmask mask ]", 8414869Ssam "[ trailers | -trailers ]", 8514869Ssam "[ arp | -arp ]"); 8614869Ssam exit(1); 8714869Ssam } 8814869Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 8914869Ssam if (s < 0) { 9014869Ssam perror("ifconfig: socket"); 9114869Ssam exit(1); 9214869Ssam } 9314869Ssam argc--, argv++; 9414869Ssam strcpy(name, *argv); 9514869Ssam strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 9614869Ssam if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 9714869Ssam Perror("ioctl (SIOCGIFFLAGS)"); 9814869Ssam exit(1); 9914869Ssam } 100*21811Skarels flags = ifr.ifr_flags; 101*21811Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 102*21811Skarels if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 103*21811Skarels if (errno != EADDRNOTAVAIL) 104*21811Skarels Perror("ioctl (SIOCGIFNETMASK)"); 105*21811Skarels } else 106*21811Skarels netmask.sin_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 10714869Ssam argc--, argv++; 10814869Ssam if (argc == 0) { 10914869Ssam status(); 11014869Ssam exit(0); 11114869Ssam } 11214869Ssam while (argc > 0) { 11314869Ssam register struct cmd *p; 11414869Ssam 11514869Ssam for (p = cmds; p->c_name; p++) 11614869Ssam if (strcmp(*argv, p->c_name) == 0) 11714869Ssam break; 11817218Stef if (p->c_name == 0 && setaddr) 11917218Stef p++; /* got src, do dst */ 120*21811Skarels if (p->c_func) { 121*21811Skarels if (p->c_parameter == NEXTARG) { 122*21811Skarels (*p->c_func)(argv[1]); 123*21811Skarels argc--, argv++; 124*21811Skarels } else 125*21811Skarels (*p->c_func)(*argv, p->c_parameter); 126*21811Skarels } 12714869Ssam argc--, argv++; 12814869Ssam } 129*21811Skarels if (setmask || setaddr) { 130*21811Skarels /* 131*21811Skarels * If setting the address and not the mask, 132*21811Skarels * clear any existing mask and the kernel will then 133*21811Skarels * assign the default. If setting both, 134*21811Skarels * set the mask first, so the address will be 135*21811Skarels * interpreted correctly. 136*21811Skarels */ 137*21811Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 138*21811Skarels ifr.ifr_addr = *(struct sockaddr *)&netmask; 139*21811Skarels if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 140*21811Skarels Perror("ioctl (SIOCSIFNETMASK)"); 141*21811Skarels } 14216329Skarels if (setaddr) { 14316329Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 14416329Skarels ifr.ifr_addr = *(struct sockaddr *) &sin; 14516329Skarels if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 14616329Skarels Perror("ioctl (SIOCSIFADDR)"); 14716329Skarels } 148*21811Skarels if (setbroadaddr) { 149*21811Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 150*21811Skarels ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 151*21811Skarels if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 152*21811Skarels Perror("ioctl (SIOCSIFBRDADDR)"); 153*21811Skarels } 15414869Ssam exit(0); 15514869Ssam } 15614869Ssam 15714869Ssam /*ARGSUSED*/ 15814869Ssam setifaddr(addr, param) 15914869Ssam char *addr; 16014869Ssam int param; 16114869Ssam { 16214869Ssam 16316329Skarels getaddr(addr, &sin); 16416329Skarels /* 16516329Skarels * Delay the ioctl to set the interface addr until flags are all set. 16616329Skarels * The address interpretation may depend on the flags, 16716329Skarels * and the flags may change when the address is set. 16815390Skarels */ 16916329Skarels setaddr++; 17014869Ssam } 17114869Ssam 172*21811Skarels setifnetmask(addr) 173*21811Skarels char *addr; 174*21811Skarels { 175*21811Skarels 176*21811Skarels getaddr(addr, &netmask); 177*21811Skarels setmask++; 178*21811Skarels } 179*21811Skarels 180*21811Skarels setifbroadaddr(addr) 181*21811Skarels char *addr; 182*21811Skarels { 183*21811Skarels getaddr(addr, &broadaddr); 184*21811Skarels setbroadaddr++; 185*21811Skarels } 186*21811Skarels 18717218Stef /*ARGSUSED*/ 18817218Stef setifdstaddr(addr, param) 18917218Stef char *addr; 19017218Stef int param; 19117218Stef { 19217218Stef 19317218Stef getaddr(addr, (struct sockaddr_in *)&ifr.ifr_dstaddr); 19417218Stef strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 19517218Stef if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 19617218Stef Perror("ioctl (SIOCSIFDSTADDR)"); 19717218Stef } 19817218Stef 19914870Ssam setifflags(vname, value) 20014870Ssam char *vname; 20114869Ssam int value; 20214869Ssam { 20314869Ssam 20414869Ssam if (value < 0) { 20514869Ssam value = -value; 206*21811Skarels flags &= ~value; 20714869Ssam } else 208*21811Skarels flags |= value; 20914869Ssam strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 210*21811Skarels ifr.ifr_flags = flags; 21114869Ssam if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 21214870Ssam Perror(vname); 21314869Ssam } 21414869Ssam 21514869Ssam status() 21614869Ssam { 21714869Ssam struct sockaddr_in *sin; 21814869Ssam 21914869Ssam strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 220*21811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 221*21811Skarels if (errno == EADDRNOTAVAIL) 222*21811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 223*21811Skarels else 224*21811Skarels Perror("ioctl (SIOCGIFADDR)"); 225*21811Skarels } 22614869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 22714869Ssam printf("%s: %s ", name, inet_ntoa(sin->sin_addr)); 22817218Stef if (flags & IFF_POINTOPOINT) { 22917218Stef strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 230*21811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 231*21811Skarels if (errno == EADDRNOTAVAIL) 232*21811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 233*21811Skarels else 234*21811Skarels Perror("ioctl (SIOCGIFDSTADDR)"); 235*21811Skarels } 23617218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 23717218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 23817218Stef } 239*21811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 24014869Ssam #define IFFBITS \ 24116329Skarels "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 24216329Skarels \11LOCAL" 24314869Ssam printb("flags", flags, IFFBITS); putchar('\n'); 244*21811Skarels if (flags & IFF_BROADCAST) { 245*21811Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 246*21811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 247*21811Skarels if (errno == EADDRNOTAVAIL) 248*21811Skarels return; 249*21811Skarels Perror("ioctl (SIOCGIFADDR)"); 250*21811Skarels } 251*21811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 252*21811Skarels printf("broadcast: %s\n", inet_ntoa(sin->sin_addr)); 253*21811Skarels } 25414869Ssam } 25514869Ssam 25614869Ssam Perror(cmd) 25714869Ssam char *cmd; 25814869Ssam { 25914869Ssam extern int errno; 26014869Ssam 26114869Ssam fprintf(stderr, "ifconfig: "); 26214869Ssam switch (errno) { 26314869Ssam 26414869Ssam case ENXIO: 26514869Ssam fprintf(stderr, "%s: ", cmd); 26614869Ssam fprintf(stderr, "no such interface\n"); 26714869Ssam break; 26814869Ssam 26914869Ssam case EPERM: 27016822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 27114869Ssam break; 27214869Ssam 27314869Ssam default: 27414869Ssam perror(cmd); 27514869Ssam } 27614869Ssam exit(1); 27714869Ssam } 27814869Ssam 27914869Ssam struct in_addr inet_makeaddr(); 28014869Ssam 28114869Ssam getaddr(s, sin) 28214869Ssam char *s; 28314869Ssam struct sockaddr_in *sin; 28414869Ssam { 28514869Ssam struct hostent *hp; 28614869Ssam struct netent *np; 28714869Ssam int val; 28814869Ssam 289*21811Skarels sin->sin_family = AF_INET; 290*21811Skarels val = inet_addr(s); 291*21811Skarels if (val != -1) { 292*21811Skarels sin->sin_addr.s_addr = val; 293*21811Skarels return; 294*21811Skarels } 29514869Ssam hp = gethostbyname(s); 29614869Ssam if (hp) { 29714869Ssam sin->sin_family = hp->h_addrtype; 29814869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 29914869Ssam return; 30014869Ssam } 30114869Ssam np = getnetbyname(s); 30214869Ssam if (np) { 30314869Ssam sin->sin_family = np->n_addrtype; 30414869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 30514869Ssam return; 30614869Ssam } 30714869Ssam fprintf(stderr, "%s: bad value\n", s); 30814869Ssam exit(1); 30914869Ssam } 31014869Ssam 31114869Ssam /* 31214869Ssam * Print a value a la the %b format of the kernel's printf 31314869Ssam */ 31414869Ssam printb(s, v, bits) 31514869Ssam char *s; 31614869Ssam register char *bits; 31714869Ssam register unsigned short v; 31814869Ssam { 31914869Ssam register int i, any = 0; 32014869Ssam register char c; 32114869Ssam 32214869Ssam if (bits && *bits == 8) 32314869Ssam printf("%s=%o", s, v); 32414869Ssam else 32514869Ssam printf("%s=%x", s, v); 32614869Ssam bits++; 32714869Ssam if (bits) { 32814869Ssam putchar('<'); 32914869Ssam while (i = *bits++) { 33014869Ssam if (v & (1 << (i-1))) { 33114869Ssam if (any) 33214869Ssam putchar(','); 33314869Ssam any = 1; 33414869Ssam for (; (c = *bits) > 32; bits++) 33514869Ssam putchar(c); 33614869Ssam } else 33714869Ssam for (; *bits > 32; bits++) 33814869Ssam ; 33914869Ssam } 34014869Ssam putchar('>'); 34114869Ssam } 34214869Ssam } 343