121811Skarels /* 221811Skarels * Copyright (c) 1983 Regents of the University of California. 321811Skarels * All rights reserved. The Berkeley software License Agreement 421811Skarels * specifies the terms and conditions for redistribution. 521811Skarels */ 621811Skarels 714869Ssam #ifndef lint 821811Skarels char copyright[] = 921811Skarels "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021811Skarels All rights reserved.\n"; 1121811Skarels #endif not lint 1214869Ssam 1321811Skarels #ifndef lint 14*26101Ssklower static char sccsid[] = "@(#)ifconfig.c 4.14 (Berkeley) 02/07/86"; 1521811Skarels #endif not lint 1621811Skarels 1714869Ssam #include <sys/types.h> 1814869Ssam #include <sys/socket.h> 1914869Ssam #include <sys/ioctl.h> 2014869Ssam 2122485Ssklower #include <net/if.h> 2214869Ssam #include <netinet/in.h> 2314869Ssam 2422485Ssklower #define NSIP 2522485Ssklower #include <netns/ns.h> 2622485Ssklower #include <netns/ns_if.h> 2722485Ssklower 2814869Ssam #include <stdio.h> 2914869Ssam #include <errno.h> 3014869Ssam #include <ctype.h> 3114869Ssam #include <netdb.h> 3214869Ssam 3322485Ssklower extern int errno; 3414869Ssam struct ifreq ifr; 3514869Ssam struct sockaddr_in sin = { AF_INET }; 3621811Skarels struct sockaddr_in broadaddr; 3721811Skarels struct sockaddr_in netmask = { AF_INET }; 3822485Ssklower struct sockaddr_in ipdst = { AF_INET }; 3914869Ssam char name[30]; 4021811Skarels int flags; 4116329Skarels int setaddr; 4221811Skarels int setmask; 4321811Skarels int setbroadaddr; 4422485Ssklower int setipdst; 4514869Ssam int s; 4621811Skarels extern int errno; 4714869Ssam 4821811Skarels int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 4922485Ssklower int setifbroadaddr(), setifipdst(); 5014869Ssam 5121811Skarels #define NEXTARG 0xffffff 5221811Skarels 5314869Ssam struct cmd { 5414869Ssam char *c_name; 5521811Skarels int c_parameter; /* NEXTARG means next argv */ 5614869Ssam int (*c_func)(); 5714869Ssam } cmds[] = { 5814869Ssam { "up", IFF_UP, setifflags } , 5914869Ssam { "down", -IFF_UP, setifflags }, 6014869Ssam { "trailers", -IFF_NOTRAILERS,setifflags }, 6114869Ssam { "-trailers", IFF_NOTRAILERS, setifflags }, 6215359Skarels { "arp", -IFF_NOARP, setifflags }, 6315359Skarels { "-arp", IFF_NOARP, setifflags }, 6421811Skarels #ifdef IFF_LOCAL 6516329Skarels { "local", IFF_LOCAL, setifflags }, 6616329Skarels { "-local", -IFF_LOCAL, setifflags }, 6721811Skarels #endif 6815286Sleres { "debug", IFF_DEBUG, setifflags }, 6915286Sleres { "-debug", -IFF_DEBUG, setifflags }, 7015004Ssam #ifdef notdef 7121811Skarels #define EN_SWABIPS 0x1000 7215004Ssam { "swabips", EN_SWABIPS, setifflags }, 7315004Ssam { "-swabips", -EN_SWABIPS, setifflags }, 7415004Ssam #endif 7521811Skarels { "netmask", NEXTARG, setifnetmask }, 7621811Skarels { "broadcast", NEXTARG, setifbroadaddr }, 7722485Ssklower { "ipdst", NEXTARG, setifipdst }, 7814869Ssam { 0, 0, setifaddr }, 7917218Stef { 0, 0, setifdstaddr }, 8014869Ssam }; 8114869Ssam 8222485Ssklower /* 8322485Ssklower * XNS support liberally adapted from 8422485Ssklower * code written at the University of Maryland 8522485Ssklower * principally by James O'Toole and Chris Torek. 8622485Ssklower */ 8722485Ssklower 8822485Ssklower int in_status(), in_getaddr(); 8922485Ssklower int xns_status(), xns_getaddr(); 9022485Ssklower 9122485Ssklower /* Known address families */ 9222485Ssklower struct afswtch { 9322485Ssklower char *af_name; 9422485Ssklower short af_af; 9522485Ssklower int (*af_status)(); 9622485Ssklower int (*af_getaddr)(); 9722485Ssklower } afs[] = { 9822485Ssklower { "inet", AF_INET, in_status, in_getaddr }, 9922485Ssklower { "ns", AF_NS, xns_status, xns_getaddr }, 10022485Ssklower { 0, 0, 0, 0 } 10122485Ssklower }; 10222485Ssklower 10322485Ssklower struct afswtch *afp; /*the address family being set or asked about*/ 10422485Ssklower 10514869Ssam main(argc, argv) 10614869Ssam int argc; 10714869Ssam char *argv[]; 10814869Ssam { 10922485Ssklower int af = AF_INET; 11014869Ssam if (argc < 2) { 11122485Ssklower fprintf(stderr, "usage: ifconfig interface [ af %s %s %s %s\n", 11217218Stef "[ address [ dest_addr ] ] [ up ] [ down ]", 11322485Ssklower "[ netmask mask ] ]", 11414869Ssam "[ trailers | -trailers ]", 11522485Ssklower "[ arp | -arp ] ]"); 11614869Ssam exit(1); 11714869Ssam } 11822485Ssklower argc--, argv++; 11924248Ssklower strncpy(name, *argv, sizeof(name)); 12022485Ssklower strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 12122485Ssklower argc--, argv++; 12222485Ssklower if (argc > 0) { 12322485Ssklower struct afswtch *myafp; 12422485Ssklower 12522485Ssklower for (myafp = afp = afs; myafp->af_name; myafp++) 12622485Ssklower if (strcmp(myafp->af_name, *argv) == 0) { 12722485Ssklower afp = myafp; argc--; argv++; 12822485Ssklower break; 12922485Ssklower } 13022485Ssklower af = ifr.ifr_addr.sa_family = afp->af_af; 13122485Ssklower } 13222485Ssklower s = socket(af, SOCK_DGRAM, 0); 13314869Ssam if (s < 0) { 13414869Ssam perror("ifconfig: socket"); 13514869Ssam exit(1); 13614869Ssam } 13714869Ssam if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 13814869Ssam Perror("ioctl (SIOCGIFFLAGS)"); 13914869Ssam exit(1); 14014869Ssam } 14122485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 14221811Skarels flags = ifr.ifr_flags; 14322485Ssklower if (af == AF_INET) { 14422485Ssklower if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 14522485Ssklower if (errno != EADDRNOTAVAIL) 14622485Ssklower Perror("ioctl (SIOCGIFNETMASK)"); 14722485Ssklower } else 14822485Ssklower netmask.sin_addr = 14922485Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 15022485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 15122485Ssklower } 15214869Ssam if (argc == 0) { 15314869Ssam status(); 15414869Ssam exit(0); 15514869Ssam } 15614869Ssam while (argc > 0) { 15714869Ssam register struct cmd *p; 15814869Ssam 15914869Ssam for (p = cmds; p->c_name; p++) 16014869Ssam if (strcmp(*argv, p->c_name) == 0) 16114869Ssam break; 16217218Stef if (p->c_name == 0 && setaddr) 16317218Stef p++; /* got src, do dst */ 16421811Skarels if (p->c_func) { 16521811Skarels if (p->c_parameter == NEXTARG) { 16621811Skarels (*p->c_func)(argv[1]); 16721811Skarels argc--, argv++; 16821811Skarels } else 16921811Skarels (*p->c_func)(*argv, p->c_parameter); 17021811Skarels } 17114869Ssam argc--, argv++; 17214869Ssam } 17322485Ssklower if ((setmask || setaddr) && (af == AF_INET)){ 17421811Skarels /* 17521811Skarels * If setting the address and not the mask, 17621811Skarels * clear any existing mask and the kernel will then 17721811Skarels * assign the default. If setting both, 17821811Skarels * set the mask first, so the address will be 17921811Skarels * interpreted correctly. 18021811Skarels */ 18121811Skarels ifr.ifr_addr = *(struct sockaddr *)&netmask; 18221811Skarels if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 18321811Skarels Perror("ioctl (SIOCSIFNETMASK)"); 18421811Skarels } 18522485Ssklower if (setipdst && af==AF_NS) { 18622485Ssklower struct nsip_req rq; 18722485Ssklower int size = sizeof(rq); 18822485Ssklower 18922485Ssklower rq.rq_ns = *(struct sockaddr *) &sin; 19022485Ssklower rq.rq_ip = *(struct sockaddr *) &ipdst; 19122485Ssklower 19222485Ssklower if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 19322485Ssklower Perror("Encapsulation Routing"); 19422485Ssklower setaddr = 0; 19522485Ssklower } 19616329Skarels if (setaddr) { 19716329Skarels ifr.ifr_addr = *(struct sockaddr *) &sin; 19816329Skarels if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 19916329Skarels Perror("ioctl (SIOCSIFADDR)"); 20016329Skarels } 20121811Skarels if (setbroadaddr) { 20221811Skarels ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 20321811Skarels if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 20421811Skarels Perror("ioctl (SIOCSIFBRDADDR)"); 20521811Skarels } 20614869Ssam exit(0); 20714869Ssam } 20814869Ssam 20914869Ssam /*ARGSUSED*/ 21014869Ssam setifaddr(addr, param) 21114869Ssam char *addr; 21222485Ssklower short param; 21314869Ssam { 21416329Skarels /* 21516329Skarels * Delay the ioctl to set the interface addr until flags are all set. 21616329Skarels * The address interpretation may depend on the flags, 21716329Skarels * and the flags may change when the address is set. 21815390Skarels */ 21916329Skarels setaddr++; 22022485Ssklower (*afp->af_getaddr)(addr, &sin); 22114869Ssam } 22214869Ssam 22321811Skarels setifnetmask(addr) 22421811Skarels char *addr; 22521811Skarels { 22622485Ssklower in_getaddr(addr, &netmask); 22721811Skarels setmask++; 22821811Skarels } 22921811Skarels 23021811Skarels setifbroadaddr(addr) 23121811Skarels char *addr; 23221811Skarels { 23322485Ssklower (*afp->af_getaddr)(addr, &broadaddr); 23421811Skarels setbroadaddr++; 23521811Skarels } 23621811Skarels 23722485Ssklower setifipdst(addr) 23822485Ssklower char *addr; 23922485Ssklower { 24022485Ssklower in_getaddr(addr, &ipdst); 24122485Ssklower setipdst++; 24222485Ssklower } 24322485Ssklower 24417218Stef /*ARGSUSED*/ 24517218Stef setifdstaddr(addr, param) 24617218Stef char *addr; 24717218Stef int param; 24817218Stef { 24917218Stef 25022485Ssklower (*afp->af_getaddr)(addr, &ifr.ifr_addr); 25117218Stef if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 25217218Stef Perror("ioctl (SIOCSIFDSTADDR)"); 25317218Stef } 25417218Stef 25514870Ssam setifflags(vname, value) 25614870Ssam char *vname; 25722485Ssklower short value; 25814869Ssam { 25922485Ssklower if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 26022485Ssklower Perror("ioctl (SIOCGIFFLAGS)"); 26122485Ssklower exit(1); 26222485Ssklower } 26322485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 26422485Ssklower flags = ifr.ifr_flags; 26514869Ssam 26614869Ssam if (value < 0) { 26714869Ssam value = -value; 26821811Skarels flags &= ~value; 26914869Ssam } else 27021811Skarels flags |= value; 27121811Skarels ifr.ifr_flags = flags; 27214869Ssam if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 27314870Ssam Perror(vname); 27414869Ssam } 27514869Ssam 27622485Ssklower /* 27722485Ssklower * Print the status of the interface. If an address family was 27822485Ssklower * specified, show it and it only; otherwise, show them all. 27922485Ssklower */ 28014869Ssam status() 28114869Ssam { 28222485Ssklower register struct afswtch *p = afp; 28322485Ssklower short af = ifr.ifr_addr.sa_family; 28422485Ssklower 28522485Ssklower if ((p = afp) != NULL) { 28622485Ssklower (*p->af_status)(); 28722485Ssklower return; 28822485Ssklower } 28922485Ssklower for (p = afs; p->af_name; p++) { 29022485Ssklower ifr.ifr_addr.sa_family = p->af_af; 29122485Ssklower (*p->af_status)(); 29222485Ssklower } 29322485Ssklower } 29422485Ssklower 29522485Ssklower #define IFFBITS \ 29622485Ssklower "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 29722485Ssklower \11LOCAL" 29822485Ssklower 29922485Ssklower in_status() 30022485Ssklower { 30114869Ssam struct sockaddr_in *sin; 30222485Ssklower char *inet_ntoa(); 30314869Ssam 30421811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 30521811Skarels if (errno == EADDRNOTAVAIL) 30621811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 30721811Skarels else 30821811Skarels Perror("ioctl (SIOCGIFADDR)"); 30921811Skarels } 31022485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 31114869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 31214869Ssam printf("%s: %s ", name, inet_ntoa(sin->sin_addr)); 31317218Stef if (flags & IFF_POINTOPOINT) { 31421811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 31521811Skarels if (errno == EADDRNOTAVAIL) 31621811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 31721811Skarels else 31821811Skarels Perror("ioctl (SIOCGIFDSTADDR)"); 31921811Skarels } 32022485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32117218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 32217218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 32317218Stef } 32421811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 32514869Ssam printb("flags", flags, IFFBITS); putchar('\n'); 32621811Skarels if (flags & IFF_BROADCAST) { 32721811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 32821811Skarels if (errno == EADDRNOTAVAIL) 32921811Skarels return; 33021811Skarels Perror("ioctl (SIOCGIFADDR)"); 33121811Skarels } 33222485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 33321811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 33421811Skarels printf("broadcast: %s\n", inet_ntoa(sin->sin_addr)); 33521811Skarels } 33614869Ssam } 33714869Ssam 33822485Ssklower 33922485Ssklower xns_status() 34022485Ssklower { 34122485Ssklower struct sockaddr_ns *sns; 34222485Ssklower 34322485Ssklower close(s); 34422485Ssklower s = socket(AF_NS, SOCK_DGRAM, 0); 34522485Ssklower if (s < 0) { 34624248Ssklower if (errno == EAFNOSUPPORT) 34724248Ssklower return; 34822485Ssklower perror("ifconfig: socket"); 34922485Ssklower exit(1); 35022485Ssklower } 35122485Ssklower if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 35224248Ssklower if (errno == EADDRNOTAVAIL || errno==EAFNOSUPPORT) 35322485Ssklower return; 35422485Ssklower Perror("ioctl (SIOCGIFADDR)"); 35522485Ssklower } 35622485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 35722485Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_addr; 358*26101Ssklower printf("%s: ns:%s ", name, ns_ntoa(sns->sns_addr)); 359*26101Ssklower if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 360*26101Ssklower if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 361*26101Ssklower if (errno == EADDRNOTAVAIL) 362*26101Ssklower bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 363*26101Ssklower else 364*26101Ssklower Perror("ioctl (SIOCGIFDSTADDR)"); 365*26101Ssklower } 366*26101Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 367*26101Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 368*26101Ssklower printf("--> %s ", ns_ntoa(sns->sns_addr)); 369*26101Ssklower } 37022485Ssklower printb("flags", flags, IFFBITS); 37122485Ssklower putchar('\n'); 37222485Ssklower } 37322485Ssklower 37414869Ssam Perror(cmd) 37514869Ssam char *cmd; 37614869Ssam { 37714869Ssam extern int errno; 37814869Ssam 37914869Ssam fprintf(stderr, "ifconfig: "); 38014869Ssam switch (errno) { 38114869Ssam 38214869Ssam case ENXIO: 38322485Ssklower fprintf(stderr, "%s: no such interface\n", cmd); 38414869Ssam break; 38514869Ssam 38614869Ssam case EPERM: 38716822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 38814869Ssam break; 38914869Ssam 39014869Ssam default: 39114869Ssam perror(cmd); 39214869Ssam } 39314869Ssam exit(1); 39414869Ssam } 39514869Ssam 39614869Ssam struct in_addr inet_makeaddr(); 39714869Ssam 39822485Ssklower in_getaddr(s, saddr) 39914869Ssam char *s; 40022485Ssklower struct sockaddr *saddr; 40114869Ssam { 40222485Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 40314869Ssam struct hostent *hp; 40414869Ssam struct netent *np; 40514869Ssam int val; 40614869Ssam 40721811Skarels sin->sin_family = AF_INET; 40821811Skarels val = inet_addr(s); 40921811Skarels if (val != -1) { 41021811Skarels sin->sin_addr.s_addr = val; 41121811Skarels return; 41221811Skarels } 41314869Ssam hp = gethostbyname(s); 41414869Ssam if (hp) { 41514869Ssam sin->sin_family = hp->h_addrtype; 41614869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 41714869Ssam return; 41814869Ssam } 41914869Ssam np = getnetbyname(s); 42014869Ssam if (np) { 42114869Ssam sin->sin_family = np->n_addrtype; 42214869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 42314869Ssam return; 42414869Ssam } 42514869Ssam fprintf(stderr, "%s: bad value\n", s); 42614869Ssam exit(1); 42714869Ssam } 42814869Ssam 42914869Ssam /* 43014869Ssam * Print a value a la the %b format of the kernel's printf 43114869Ssam */ 43214869Ssam printb(s, v, bits) 43314869Ssam char *s; 43414869Ssam register char *bits; 43514869Ssam register unsigned short v; 43614869Ssam { 43714869Ssam register int i, any = 0; 43814869Ssam register char c; 43914869Ssam 44014869Ssam if (bits && *bits == 8) 44114869Ssam printf("%s=%o", s, v); 44214869Ssam else 44314869Ssam printf("%s=%x", s, v); 44414869Ssam bits++; 44514869Ssam if (bits) { 44614869Ssam putchar('<'); 44714869Ssam while (i = *bits++) { 44814869Ssam if (v & (1 << (i-1))) { 44914869Ssam if (any) 45014869Ssam putchar(','); 45114869Ssam any = 1; 45214869Ssam for (; (c = *bits) > 32; bits++) 45314869Ssam putchar(c); 45414869Ssam } else 45514869Ssam for (; *bits > 32; bits++) 45614869Ssam ; 45714869Ssam } 45814869Ssam putchar('>'); 45914869Ssam } 46014869Ssam } 46122485Ssklower 46222485Ssklower xns_getaddr(addr, saddr) 46322485Ssklower char *addr; 46422485Ssklower struct sockaddr *saddr; 46522485Ssklower { 466*26101Ssklower struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 467*26101Ssklower struct ns_addr ns_addr(); 46822485Ssklower sns->sns_family = AF_NS; 469*26101Ssklower sns->sns_addr = ns_addr(addr); 47022485Ssklower } 471