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*26185Skarels static char sccsid[] = "@(#)ifconfig.c 4.15 (Berkeley) 02/16/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; 41*26185Skarels int metric; 4216329Skarels int setaddr; 4321811Skarels int setmask; 4421811Skarels int setbroadaddr; 4522485Ssklower int setipdst; 4614869Ssam int s; 4721811Skarels extern int errno; 4814869Ssam 4921811Skarels int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 50*26185Skarels int setifmetric(), setifbroadaddr(), setifipdst(); 5114869Ssam 5221811Skarels #define NEXTARG 0xffffff 5321811Skarels 5414869Ssam struct cmd { 5514869Ssam char *c_name; 5621811Skarels int c_parameter; /* NEXTARG means next argv */ 5714869Ssam int (*c_func)(); 5814869Ssam } cmds[] = { 5914869Ssam { "up", IFF_UP, setifflags } , 6014869Ssam { "down", -IFF_UP, setifflags }, 6114869Ssam { "trailers", -IFF_NOTRAILERS,setifflags }, 6214869Ssam { "-trailers", IFF_NOTRAILERS, setifflags }, 6315359Skarels { "arp", -IFF_NOARP, setifflags }, 6415359Skarels { "-arp", IFF_NOARP, setifflags }, 6515286Sleres { "debug", IFF_DEBUG, setifflags }, 6615286Sleres { "-debug", -IFF_DEBUG, setifflags }, 6715004Ssam #ifdef notdef 6821811Skarels #define EN_SWABIPS 0x1000 6915004Ssam { "swabips", EN_SWABIPS, setifflags }, 7015004Ssam { "-swabips", -EN_SWABIPS, setifflags }, 7115004Ssam #endif 7221811Skarels { "netmask", NEXTARG, setifnetmask }, 73*26185Skarels { "metric", NEXTARG, setifmetric }, 7421811Skarels { "broadcast", NEXTARG, setifbroadaddr }, 7522485Ssklower { "ipdst", NEXTARG, setifipdst }, 7614869Ssam { 0, 0, setifaddr }, 7717218Stef { 0, 0, setifdstaddr }, 7814869Ssam }; 7914869Ssam 8022485Ssklower /* 8122485Ssklower * XNS support liberally adapted from 8222485Ssklower * code written at the University of Maryland 8322485Ssklower * principally by James O'Toole and Chris Torek. 8422485Ssklower */ 8522485Ssklower 8622485Ssklower int in_status(), in_getaddr(); 8722485Ssklower int xns_status(), xns_getaddr(); 8822485Ssklower 8922485Ssklower /* Known address families */ 9022485Ssklower struct afswtch { 9122485Ssklower char *af_name; 9222485Ssklower short af_af; 9322485Ssklower int (*af_status)(); 9422485Ssklower int (*af_getaddr)(); 9522485Ssklower } afs[] = { 9622485Ssklower { "inet", AF_INET, in_status, in_getaddr }, 9722485Ssklower { "ns", AF_NS, xns_status, xns_getaddr }, 9822485Ssklower { 0, 0, 0, 0 } 9922485Ssklower }; 10022485Ssklower 10122485Ssklower struct afswtch *afp; /*the address family being set or asked about*/ 10222485Ssklower 10314869Ssam main(argc, argv) 10414869Ssam int argc; 10514869Ssam char *argv[]; 10614869Ssam { 10722485Ssklower int af = AF_INET; 10814869Ssam if (argc < 2) { 109*26185Skarels fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s", 110*26185Skarels "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 111*26185Skarels "[ netmask mask ] ]\n", 112*26185Skarels "\t[ metric n ]\n", 113*26185Skarels "\t[ trailers | -trailers ]\n", 114*26185Skarels "\t[ arp | -arp ]\n"); 11514869Ssam exit(1); 11614869Ssam } 11722485Ssklower argc--, argv++; 11824248Ssklower strncpy(name, *argv, sizeof(name)); 11922485Ssklower strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 12022485Ssklower argc--, argv++; 12122485Ssklower if (argc > 0) { 12222485Ssklower struct afswtch *myafp; 12322485Ssklower 12422485Ssklower for (myafp = afp = afs; myafp->af_name; myafp++) 12522485Ssklower if (strcmp(myafp->af_name, *argv) == 0) { 12622485Ssklower afp = myafp; argc--; argv++; 12722485Ssklower break; 12822485Ssklower } 12922485Ssklower af = ifr.ifr_addr.sa_family = afp->af_af; 13022485Ssklower } 13122485Ssklower s = socket(af, SOCK_DGRAM, 0); 13214869Ssam if (s < 0) { 13314869Ssam perror("ifconfig: socket"); 13414869Ssam exit(1); 13514869Ssam } 13614869Ssam if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 13714869Ssam Perror("ioctl (SIOCGIFFLAGS)"); 13814869Ssam exit(1); 13914869Ssam } 14022485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 14121811Skarels flags = ifr.ifr_flags; 142*26185Skarels if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 143*26185Skarels perror("ioctl (SIOCGIFMETRIC)"); 144*26185Skarels else 145*26185Skarels metric = ifr.ifr_metric; 14622485Ssklower if (af == AF_INET) { 14722485Ssklower if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 14822485Ssklower if (errno != EADDRNOTAVAIL) 14922485Ssklower Perror("ioctl (SIOCGIFNETMASK)"); 15022485Ssklower } else 15122485Ssklower netmask.sin_addr = 15222485Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 15322485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 15422485Ssklower } 15514869Ssam if (argc == 0) { 15614869Ssam status(); 15714869Ssam exit(0); 15814869Ssam } 15914869Ssam while (argc > 0) { 16014869Ssam register struct cmd *p; 16114869Ssam 16214869Ssam for (p = cmds; p->c_name; p++) 16314869Ssam if (strcmp(*argv, p->c_name) == 0) 16414869Ssam break; 16517218Stef if (p->c_name == 0 && setaddr) 16617218Stef p++; /* got src, do dst */ 16721811Skarels if (p->c_func) { 16821811Skarels if (p->c_parameter == NEXTARG) { 16921811Skarels (*p->c_func)(argv[1]); 17021811Skarels argc--, argv++; 17121811Skarels } else 17221811Skarels (*p->c_func)(*argv, p->c_parameter); 17321811Skarels } 17414869Ssam argc--, argv++; 17514869Ssam } 17622485Ssklower if ((setmask || setaddr) && (af == AF_INET)){ 17721811Skarels /* 17821811Skarels * If setting the address and not the mask, 17921811Skarels * clear any existing mask and the kernel will then 18021811Skarels * assign the default. If setting both, 18121811Skarels * set the mask first, so the address will be 18221811Skarels * interpreted correctly. 18321811Skarels */ 18421811Skarels ifr.ifr_addr = *(struct sockaddr *)&netmask; 18521811Skarels if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 18621811Skarels Perror("ioctl (SIOCSIFNETMASK)"); 18721811Skarels } 18822485Ssklower if (setipdst && af==AF_NS) { 18922485Ssklower struct nsip_req rq; 19022485Ssklower int size = sizeof(rq); 19122485Ssklower 19222485Ssklower rq.rq_ns = *(struct sockaddr *) &sin; 19322485Ssklower rq.rq_ip = *(struct sockaddr *) &ipdst; 19422485Ssklower 19522485Ssklower if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 19622485Ssklower Perror("Encapsulation Routing"); 19722485Ssklower setaddr = 0; 19822485Ssklower } 19916329Skarels if (setaddr) { 20016329Skarels ifr.ifr_addr = *(struct sockaddr *) &sin; 20116329Skarels if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 20216329Skarels Perror("ioctl (SIOCSIFADDR)"); 20316329Skarels } 20421811Skarels if (setbroadaddr) { 20521811Skarels ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 20621811Skarels if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 20721811Skarels Perror("ioctl (SIOCSIFBRDADDR)"); 20821811Skarels } 20914869Ssam exit(0); 21014869Ssam } 21114869Ssam 21214869Ssam /*ARGSUSED*/ 21314869Ssam setifaddr(addr, param) 21414869Ssam char *addr; 21522485Ssklower short param; 21614869Ssam { 21716329Skarels /* 21816329Skarels * Delay the ioctl to set the interface addr until flags are all set. 21916329Skarels * The address interpretation may depend on the flags, 22016329Skarels * and the flags may change when the address is set. 22115390Skarels */ 22216329Skarels setaddr++; 22322485Ssklower (*afp->af_getaddr)(addr, &sin); 22414869Ssam } 22514869Ssam 22621811Skarels setifnetmask(addr) 22721811Skarels char *addr; 22821811Skarels { 22922485Ssklower in_getaddr(addr, &netmask); 23021811Skarels setmask++; 23121811Skarels } 23221811Skarels 23321811Skarels setifbroadaddr(addr) 23421811Skarels char *addr; 23521811Skarels { 23622485Ssklower (*afp->af_getaddr)(addr, &broadaddr); 23721811Skarels setbroadaddr++; 23821811Skarels } 23921811Skarels 24022485Ssklower setifipdst(addr) 24122485Ssklower char *addr; 24222485Ssklower { 24322485Ssklower in_getaddr(addr, &ipdst); 24422485Ssklower setipdst++; 24522485Ssklower } 24622485Ssklower 24717218Stef /*ARGSUSED*/ 24817218Stef setifdstaddr(addr, param) 24917218Stef char *addr; 25017218Stef int param; 25117218Stef { 25217218Stef 25322485Ssklower (*afp->af_getaddr)(addr, &ifr.ifr_addr); 25417218Stef if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 25517218Stef Perror("ioctl (SIOCSIFDSTADDR)"); 25617218Stef } 25717218Stef 25814870Ssam setifflags(vname, value) 25914870Ssam char *vname; 26022485Ssklower short value; 26114869Ssam { 26222485Ssklower if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 26322485Ssklower Perror("ioctl (SIOCGIFFLAGS)"); 26422485Ssklower exit(1); 26522485Ssklower } 26622485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 26722485Ssklower flags = ifr.ifr_flags; 26814869Ssam 26914869Ssam if (value < 0) { 27014869Ssam value = -value; 27121811Skarels flags &= ~value; 27214869Ssam } else 27321811Skarels flags |= value; 27421811Skarels ifr.ifr_flags = flags; 27514869Ssam if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 27614870Ssam Perror(vname); 27714869Ssam } 27814869Ssam 279*26185Skarels setifmetric(val) 280*26185Skarels char *val; 281*26185Skarels { 282*26185Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 283*26185Skarels ifr.ifr_metric = atoi(val); 284*26185Skarels if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 285*26185Skarels perror("ioctl (set metric)"); 286*26185Skarels } 287*26185Skarels 288*26185Skarels #define IFFBITS \ 289*26185Skarels "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 290*26185Skarels " 291*26185Skarels 29222485Ssklower /* 29322485Ssklower * Print the status of the interface. If an address family was 29422485Ssklower * specified, show it and it only; otherwise, show them all. 29522485Ssklower */ 29614869Ssam status() 29714869Ssam { 29822485Ssklower register struct afswtch *p = afp; 29922485Ssklower short af = ifr.ifr_addr.sa_family; 30022485Ssklower 301*26185Skarels printf("%s: ", name); 302*26185Skarels printb("flags", flags, IFFBITS); 303*26185Skarels if (metric) 304*26185Skarels printf(" metric %d", metric); 305*26185Skarels putchar('\n'); 30622485Ssklower if ((p = afp) != NULL) { 30722485Ssklower (*p->af_status)(); 30822485Ssklower return; 30922485Ssklower } 31022485Ssklower for (p = afs; p->af_name; p++) { 31122485Ssklower ifr.ifr_addr.sa_family = p->af_af; 31222485Ssklower (*p->af_status)(); 31322485Ssklower } 31422485Ssklower } 31522485Ssklower 31622485Ssklower in_status() 31722485Ssklower { 31814869Ssam struct sockaddr_in *sin; 31922485Ssklower char *inet_ntoa(); 32014869Ssam 32121811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 32221811Skarels if (errno == EADDRNOTAVAIL) 32321811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 32421811Skarels else 32521811Skarels Perror("ioctl (SIOCGIFADDR)"); 32621811Skarels } 32722485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32814869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 329*26185Skarels printf("\tinet %s ", name, inet_ntoa(sin->sin_addr)); 33017218Stef if (flags & IFF_POINTOPOINT) { 33121811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 33221811Skarels if (errno == EADDRNOTAVAIL) 33321811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 33421811Skarels else 33521811Skarels Perror("ioctl (SIOCGIFDSTADDR)"); 33621811Skarels } 33722485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 33817218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 33917218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 34017218Stef } 34121811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 34221811Skarels if (flags & IFF_BROADCAST) { 34321811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 34421811Skarels if (errno == EADDRNOTAVAIL) 34521811Skarels return; 34621811Skarels Perror("ioctl (SIOCGIFADDR)"); 34721811Skarels } 34822485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 34921811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 350*26185Skarels printf("broadcast %s", inet_ntoa(sin->sin_addr)); 35121811Skarels } 352*26185Skarels putchar('\n'); 35314869Ssam } 35414869Ssam 35522485Ssklower 35622485Ssklower xns_status() 35722485Ssklower { 35822485Ssklower struct sockaddr_ns *sns; 35922485Ssklower 36022485Ssklower close(s); 36122485Ssklower s = socket(AF_NS, SOCK_DGRAM, 0); 36222485Ssklower if (s < 0) { 36324248Ssklower if (errno == EAFNOSUPPORT) 36424248Ssklower return; 36522485Ssklower perror("ifconfig: socket"); 36622485Ssklower exit(1); 36722485Ssklower } 36822485Ssklower if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 36924248Ssklower if (errno == EADDRNOTAVAIL || errno==EAFNOSUPPORT) 37022485Ssklower return; 37122485Ssklower Perror("ioctl (SIOCGIFADDR)"); 37222485Ssklower } 37322485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 37422485Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_addr; 375*26185Skarels printf("\tns %s ", ns_ntoa(sns->sns_addr)); 37626101Ssklower if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 37726101Ssklower if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 37826101Ssklower if (errno == EADDRNOTAVAIL) 37926101Ssklower bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 38026101Ssklower else 38126101Ssklower Perror("ioctl (SIOCGIFDSTADDR)"); 38226101Ssklower } 38326101Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 38426101Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 38526101Ssklower printf("--> %s ", ns_ntoa(sns->sns_addr)); 38626101Ssklower } 38722485Ssklower putchar('\n'); 38822485Ssklower } 38922485Ssklower 39014869Ssam Perror(cmd) 39114869Ssam char *cmd; 39214869Ssam { 39314869Ssam extern int errno; 39414869Ssam 39514869Ssam fprintf(stderr, "ifconfig: "); 39614869Ssam switch (errno) { 39714869Ssam 39814869Ssam case ENXIO: 39922485Ssklower fprintf(stderr, "%s: no such interface\n", cmd); 40014869Ssam break; 40114869Ssam 40214869Ssam case EPERM: 40316822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 40414869Ssam break; 40514869Ssam 40614869Ssam default: 40714869Ssam perror(cmd); 40814869Ssam } 40914869Ssam exit(1); 41014869Ssam } 41114869Ssam 41214869Ssam struct in_addr inet_makeaddr(); 41314869Ssam 41422485Ssklower in_getaddr(s, saddr) 41514869Ssam char *s; 41622485Ssklower struct sockaddr *saddr; 41714869Ssam { 41822485Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 41914869Ssam struct hostent *hp; 42014869Ssam struct netent *np; 42114869Ssam int val; 42214869Ssam 42321811Skarels sin->sin_family = AF_INET; 42421811Skarels val = inet_addr(s); 42521811Skarels if (val != -1) { 42621811Skarels sin->sin_addr.s_addr = val; 42721811Skarels return; 42821811Skarels } 42914869Ssam hp = gethostbyname(s); 43014869Ssam if (hp) { 43114869Ssam sin->sin_family = hp->h_addrtype; 43214869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 43314869Ssam return; 43414869Ssam } 43514869Ssam np = getnetbyname(s); 43614869Ssam if (np) { 43714869Ssam sin->sin_family = np->n_addrtype; 43814869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 43914869Ssam return; 44014869Ssam } 44114869Ssam fprintf(stderr, "%s: bad value\n", s); 44214869Ssam exit(1); 44314869Ssam } 44414869Ssam 44514869Ssam /* 44614869Ssam * Print a value a la the %b format of the kernel's printf 44714869Ssam */ 44814869Ssam printb(s, v, bits) 44914869Ssam char *s; 45014869Ssam register char *bits; 45114869Ssam register unsigned short v; 45214869Ssam { 45314869Ssam register int i, any = 0; 45414869Ssam register char c; 45514869Ssam 45614869Ssam if (bits && *bits == 8) 45714869Ssam printf("%s=%o", s, v); 45814869Ssam else 45914869Ssam printf("%s=%x", s, v); 46014869Ssam bits++; 46114869Ssam if (bits) { 46214869Ssam putchar('<'); 46314869Ssam while (i = *bits++) { 46414869Ssam if (v & (1 << (i-1))) { 46514869Ssam if (any) 46614869Ssam putchar(','); 46714869Ssam any = 1; 46814869Ssam for (; (c = *bits) > 32; bits++) 46914869Ssam putchar(c); 47014869Ssam } else 47114869Ssam for (; *bits > 32; bits++) 47214869Ssam ; 47314869Ssam } 47414869Ssam putchar('>'); 47514869Ssam } 47614869Ssam } 47722485Ssklower 47822485Ssklower xns_getaddr(addr, saddr) 47922485Ssklower char *addr; 48022485Ssklower struct sockaddr *saddr; 48122485Ssklower { 48226101Ssklower struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 48326101Ssklower struct ns_addr ns_addr(); 48422485Ssklower sns->sns_family = AF_NS; 48526101Ssklower sns->sns_addr = ns_addr(addr); 48622485Ssklower } 487