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*22485Ssklower static char sccsid[] = "@(#)ifconfig.c 4.12 (Berkeley) 06/06/85"; 1521811Skarels #endif not lint 1621811Skarels 1721811Skarels 1814869Ssam #include <sys/types.h> 1914869Ssam #include <sys/socket.h> 2014869Ssam #include <sys/ioctl.h> 2114869Ssam 22*22485Ssklower #include <net/if.h> 2314869Ssam #include <netinet/in.h> 2414869Ssam 25*22485Ssklower #define NSIP 26*22485Ssklower #include <netns/ns.h> 27*22485Ssklower #include <netns/ns_if.h> 28*22485Ssklower 2914869Ssam #include <stdio.h> 3014869Ssam #include <errno.h> 3114869Ssam #include <ctype.h> 3214869Ssam #include <netdb.h> 3314869Ssam 34*22485Ssklower extern int errno; 3514869Ssam struct ifreq ifr; 3614869Ssam struct sockaddr_in sin = { AF_INET }; 3721811Skarels struct sockaddr_in broadaddr; 3821811Skarels struct sockaddr_in netmask = { AF_INET }; 39*22485Ssklower struct sockaddr_in ipdst = { AF_INET }; 4014869Ssam char name[30]; 4121811Skarels int flags; 4216329Skarels int setaddr; 4321811Skarels int setmask; 4421811Skarels int setbroadaddr; 45*22485Ssklower int setipdst; 4614869Ssam int s; 4721811Skarels extern int errno; 4814869Ssam 4921811Skarels int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 50*22485Ssklower int 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 }, 6521811Skarels #ifdef IFF_LOCAL 6616329Skarels { "local", IFF_LOCAL, setifflags }, 6716329Skarels { "-local", -IFF_LOCAL, setifflags }, 6821811Skarels #endif 6915286Sleres { "debug", IFF_DEBUG, setifflags }, 7015286Sleres { "-debug", -IFF_DEBUG, setifflags }, 7115004Ssam #ifdef notdef 7221811Skarels #define EN_SWABIPS 0x1000 7315004Ssam { "swabips", EN_SWABIPS, setifflags }, 7415004Ssam { "-swabips", -EN_SWABIPS, setifflags }, 7515004Ssam #endif 7621811Skarels { "netmask", NEXTARG, setifnetmask }, 7721811Skarels { "broadcast", NEXTARG, setifbroadaddr }, 78*22485Ssklower { "ipdst", NEXTARG, setifipdst }, 7914869Ssam { 0, 0, setifaddr }, 8017218Stef { 0, 0, setifdstaddr }, 8114869Ssam }; 8214869Ssam 83*22485Ssklower /* 84*22485Ssklower * XNS support liberally adapted from 85*22485Ssklower * code written at the University of Maryland 86*22485Ssklower * principally by James O'Toole and Chris Torek. 87*22485Ssklower */ 88*22485Ssklower 89*22485Ssklower int in_status(), in_getaddr(); 90*22485Ssklower int xns_status(), xns_getaddr(); 91*22485Ssklower 92*22485Ssklower /* Known address families */ 93*22485Ssklower struct afswtch { 94*22485Ssklower char *af_name; 95*22485Ssklower short af_af; 96*22485Ssklower int (*af_status)(); 97*22485Ssklower int (*af_getaddr)(); 98*22485Ssklower } afs[] = { 99*22485Ssklower { "inet", AF_INET, in_status, in_getaddr }, 100*22485Ssklower { "ns", AF_NS, xns_status, xns_getaddr }, 101*22485Ssklower { 0, 0, 0, 0 } 102*22485Ssklower }; 103*22485Ssklower 104*22485Ssklower struct afswtch *afp; /*the address family being set or asked about*/ 105*22485Ssklower 10614869Ssam main(argc, argv) 10714869Ssam int argc; 10814869Ssam char *argv[]; 10914869Ssam { 110*22485Ssklower int af = AF_INET; 11114869Ssam if (argc < 2) { 112*22485Ssklower fprintf(stderr, "usage: ifconfig interface [ af %s %s %s %s\n", 11317218Stef "[ address [ dest_addr ] ] [ up ] [ down ]", 114*22485Ssklower "[ netmask mask ] ]", 11514869Ssam "[ trailers | -trailers ]", 116*22485Ssklower "[ arp | -arp ] ]"); 11714869Ssam exit(1); 11814869Ssam } 119*22485Ssklower argc--, argv++; 120*22485Ssklower strncpy(name, *argv, sizeof(name - 1)); 121*22485Ssklower name[sizeof name - 1] = 0; 122*22485Ssklower strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 123*22485Ssklower argc--, argv++; 124*22485Ssklower if (argc > 0) { 125*22485Ssklower struct afswtch *myafp; 126*22485Ssklower 127*22485Ssklower for (myafp = afp = afs; myafp->af_name; myafp++) 128*22485Ssklower if (strcmp(myafp->af_name, *argv) == 0) { 129*22485Ssklower afp = myafp; argc--; argv++; 130*22485Ssklower break; 131*22485Ssklower } 132*22485Ssklower af = ifr.ifr_addr.sa_family = afp->af_af; 133*22485Ssklower } 134*22485Ssklower s = socket(af, SOCK_DGRAM, 0); 13514869Ssam if (s < 0) { 13614869Ssam perror("ifconfig: socket"); 13714869Ssam exit(1); 13814869Ssam } 13914869Ssam if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 14014869Ssam Perror("ioctl (SIOCGIFFLAGS)"); 14114869Ssam exit(1); 14214869Ssam } 143*22485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 14421811Skarels flags = ifr.ifr_flags; 145*22485Ssklower if (af == AF_INET) { 146*22485Ssklower if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 147*22485Ssklower if (errno != EADDRNOTAVAIL) 148*22485Ssklower Perror("ioctl (SIOCGIFNETMASK)"); 149*22485Ssklower } else 150*22485Ssklower netmask.sin_addr = 151*22485Ssklower ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 152*22485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 153*22485Ssklower } 15414869Ssam if (argc == 0) { 15514869Ssam status(); 15614869Ssam exit(0); 15714869Ssam } 15814869Ssam while (argc > 0) { 15914869Ssam register struct cmd *p; 16014869Ssam 16114869Ssam for (p = cmds; p->c_name; p++) 16214869Ssam if (strcmp(*argv, p->c_name) == 0) 16314869Ssam break; 16417218Stef if (p->c_name == 0 && setaddr) 16517218Stef p++; /* got src, do dst */ 16621811Skarels if (p->c_func) { 16721811Skarels if (p->c_parameter == NEXTARG) { 16821811Skarels (*p->c_func)(argv[1]); 16921811Skarels argc--, argv++; 17021811Skarels } else 17121811Skarels (*p->c_func)(*argv, p->c_parameter); 17221811Skarels } 17314869Ssam argc--, argv++; 17414869Ssam } 175*22485Ssklower if ((setmask || setaddr) && (af == AF_INET)){ 17621811Skarels /* 17721811Skarels * If setting the address and not the mask, 17821811Skarels * clear any existing mask and the kernel will then 17921811Skarels * assign the default. If setting both, 18021811Skarels * set the mask first, so the address will be 18121811Skarels * interpreted correctly. 18221811Skarels */ 18321811Skarels ifr.ifr_addr = *(struct sockaddr *)&netmask; 18421811Skarels if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 18521811Skarels Perror("ioctl (SIOCSIFNETMASK)"); 18621811Skarels } 187*22485Ssklower if (setipdst && af==AF_NS) { 188*22485Ssklower struct nsip_req rq; 189*22485Ssklower int size = sizeof(rq); 190*22485Ssklower 191*22485Ssklower rq.rq_ns = *(struct sockaddr *) &sin; 192*22485Ssklower rq.rq_ip = *(struct sockaddr *) &ipdst; 193*22485Ssklower 194*22485Ssklower if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 195*22485Ssklower Perror("Encapsulation Routing"); 196*22485Ssklower setaddr = 0; 197*22485Ssklower } 19816329Skarels if (setaddr) { 19916329Skarels ifr.ifr_addr = *(struct sockaddr *) &sin; 20016329Skarels if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 20116329Skarels Perror("ioctl (SIOCSIFADDR)"); 20216329Skarels } 20321811Skarels if (setbroadaddr) { 20421811Skarels ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 20521811Skarels if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 20621811Skarels Perror("ioctl (SIOCSIFBRDADDR)"); 20721811Skarels } 20814869Ssam exit(0); 20914869Ssam } 21014869Ssam 21114869Ssam /*ARGSUSED*/ 21214869Ssam setifaddr(addr, param) 21314869Ssam char *addr; 214*22485Ssklower short param; 21514869Ssam { 21616329Skarels /* 21716329Skarels * Delay the ioctl to set the interface addr until flags are all set. 21816329Skarels * The address interpretation may depend on the flags, 21916329Skarels * and the flags may change when the address is set. 22015390Skarels */ 22116329Skarels setaddr++; 222*22485Ssklower (*afp->af_getaddr)(addr, &sin); 22314869Ssam } 22414869Ssam 22521811Skarels setifnetmask(addr) 22621811Skarels char *addr; 22721811Skarels { 228*22485Ssklower in_getaddr(addr, &netmask); 22921811Skarels setmask++; 23021811Skarels } 23121811Skarels 23221811Skarels setifbroadaddr(addr) 23321811Skarels char *addr; 23421811Skarels { 235*22485Ssklower (*afp->af_getaddr)(addr, &broadaddr); 23621811Skarels setbroadaddr++; 23721811Skarels } 23821811Skarels 239*22485Ssklower setifipdst(addr) 240*22485Ssklower char *addr; 241*22485Ssklower { 242*22485Ssklower in_getaddr(addr, &ipdst); 243*22485Ssklower setipdst++; 244*22485Ssklower } 245*22485Ssklower 24617218Stef /*ARGSUSED*/ 24717218Stef setifdstaddr(addr, param) 24817218Stef char *addr; 24917218Stef int param; 25017218Stef { 25117218Stef 252*22485Ssklower (*afp->af_getaddr)(addr, &ifr.ifr_addr); 25317218Stef if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 25417218Stef Perror("ioctl (SIOCSIFDSTADDR)"); 25517218Stef } 25617218Stef 25714870Ssam setifflags(vname, value) 25814870Ssam char *vname; 259*22485Ssklower short value; 26014869Ssam { 261*22485Ssklower if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 262*22485Ssklower Perror("ioctl (SIOCGIFFLAGS)"); 263*22485Ssklower exit(1); 264*22485Ssklower } 265*22485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 266*22485Ssklower flags = ifr.ifr_flags; 26714869Ssam 26814869Ssam if (value < 0) { 26914869Ssam value = -value; 27021811Skarels flags &= ~value; 27114869Ssam } else 27221811Skarels flags |= value; 27321811Skarels ifr.ifr_flags = flags; 27414869Ssam if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 27514870Ssam Perror(vname); 27614869Ssam } 27714869Ssam 278*22485Ssklower /* 279*22485Ssklower * Print the status of the interface. If an address family was 280*22485Ssklower * specified, show it and it only; otherwise, show them all. 281*22485Ssklower */ 28214869Ssam status() 28314869Ssam { 284*22485Ssklower register struct afswtch *p = afp; 285*22485Ssklower short af = ifr.ifr_addr.sa_family; 286*22485Ssklower 287*22485Ssklower if ((p = afp) != NULL) { 288*22485Ssklower (*p->af_status)(); 289*22485Ssklower return; 290*22485Ssklower } 291*22485Ssklower for (p = afs; p->af_name; p++) { 292*22485Ssklower ifr.ifr_addr.sa_family = p->af_af; 293*22485Ssklower (*p->af_status)(); 294*22485Ssklower } 295*22485Ssklower } 296*22485Ssklower 297*22485Ssklower #define IFFBITS \ 298*22485Ssklower "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 299*22485Ssklower \11LOCAL" 300*22485Ssklower 301*22485Ssklower in_status() 302*22485Ssklower { 30314869Ssam struct sockaddr_in *sin; 304*22485Ssklower char *inet_ntoa(); 30514869Ssam 30621811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 30721811Skarels if (errno == EADDRNOTAVAIL) 30821811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 30921811Skarels else 31021811Skarels Perror("ioctl (SIOCGIFADDR)"); 31121811Skarels } 312*22485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 31314869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 31414869Ssam printf("%s: %s ", name, inet_ntoa(sin->sin_addr)); 31517218Stef if (flags & IFF_POINTOPOINT) { 31621811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 31721811Skarels if (errno == EADDRNOTAVAIL) 31821811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 31921811Skarels else 32021811Skarels Perror("ioctl (SIOCGIFDSTADDR)"); 32121811Skarels } 322*22485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32317218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 32417218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 32517218Stef } 32621811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 32714869Ssam printb("flags", flags, IFFBITS); putchar('\n'); 32821811Skarels if (flags & IFF_BROADCAST) { 32921811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 33021811Skarels if (errno == EADDRNOTAVAIL) 33121811Skarels return; 33221811Skarels Perror("ioctl (SIOCGIFADDR)"); 33321811Skarels } 334*22485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 33521811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 33621811Skarels printf("broadcast: %s\n", inet_ntoa(sin->sin_addr)); 33721811Skarels } 33814869Ssam } 33914869Ssam 340*22485Ssklower 341*22485Ssklower xns_status() 342*22485Ssklower { 343*22485Ssklower struct sockaddr_ns *sns; 344*22485Ssklower char *xns_ntoa(); 345*22485Ssklower 346*22485Ssklower close(s); 347*22485Ssklower s = socket(AF_NS, SOCK_DGRAM, 0); 348*22485Ssklower if (s < 0) { 349*22485Ssklower perror("ifconfig: socket"); 350*22485Ssklower exit(1); 351*22485Ssklower } 352*22485Ssklower if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 353*22485Ssklower if (errno == EAFNOSUPPORT) 354*22485Ssklower return; 355*22485Ssklower Perror("ioctl (SIOCGIFADDR)"); 356*22485Ssklower } 357*22485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 358*22485Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_addr; 359*22485Ssklower printf("%s: xns %s ", name, xns_ntoa(sns)); 360*22485Ssklower printb("flags", flags, IFFBITS); 361*22485Ssklower putchar('\n'); 362*22485Ssklower } 363*22485Ssklower 36414869Ssam Perror(cmd) 36514869Ssam char *cmd; 36614869Ssam { 36714869Ssam extern int errno; 36814869Ssam 36914869Ssam fprintf(stderr, "ifconfig: "); 37014869Ssam switch (errno) { 37114869Ssam 37214869Ssam case ENXIO: 373*22485Ssklower fprintf(stderr, "%s: no such interface\n", cmd); 37414869Ssam break; 37514869Ssam 37614869Ssam case EPERM: 37716822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 37814869Ssam break; 37914869Ssam 38014869Ssam default: 38114869Ssam perror(cmd); 38214869Ssam } 38314869Ssam exit(1); 38414869Ssam } 38514869Ssam 38614869Ssam struct in_addr inet_makeaddr(); 38714869Ssam 388*22485Ssklower in_getaddr(s, saddr) 38914869Ssam char *s; 390*22485Ssklower struct sockaddr *saddr; 39114869Ssam { 392*22485Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 39314869Ssam struct hostent *hp; 39414869Ssam struct netent *np; 39514869Ssam int val; 39614869Ssam 39721811Skarels sin->sin_family = AF_INET; 39821811Skarels val = inet_addr(s); 39921811Skarels if (val != -1) { 40021811Skarels sin->sin_addr.s_addr = val; 40121811Skarels return; 40221811Skarels } 40314869Ssam hp = gethostbyname(s); 40414869Ssam if (hp) { 40514869Ssam sin->sin_family = hp->h_addrtype; 40614869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 40714869Ssam return; 40814869Ssam } 40914869Ssam np = getnetbyname(s); 41014869Ssam if (np) { 41114869Ssam sin->sin_family = np->n_addrtype; 41214869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 41314869Ssam return; 41414869Ssam } 41514869Ssam fprintf(stderr, "%s: bad value\n", s); 41614869Ssam exit(1); 41714869Ssam } 41814869Ssam 41914869Ssam /* 42014869Ssam * Print a value a la the %b format of the kernel's printf 42114869Ssam */ 42214869Ssam printb(s, v, bits) 42314869Ssam char *s; 42414869Ssam register char *bits; 42514869Ssam register unsigned short v; 42614869Ssam { 42714869Ssam register int i, any = 0; 42814869Ssam register char c; 42914869Ssam 43014869Ssam if (bits && *bits == 8) 43114869Ssam printf("%s=%o", s, v); 43214869Ssam else 43314869Ssam printf("%s=%x", s, v); 43414869Ssam bits++; 43514869Ssam if (bits) { 43614869Ssam putchar('<'); 43714869Ssam while (i = *bits++) { 43814869Ssam if (v & (1 << (i-1))) { 43914869Ssam if (any) 44014869Ssam putchar(','); 44114869Ssam any = 1; 44214869Ssam for (; (c = *bits) > 32; bits++) 44314869Ssam putchar(c); 44414869Ssam } else 44514869Ssam for (; *bits > 32; bits++) 44614869Ssam ; 44714869Ssam } 44814869Ssam putchar('>'); 44914869Ssam } 45014869Ssam } 451*22485Ssklower 452*22485Ssklower #define setxnnet(a,b) {a = * (union ns_net *) &(b);} 453*22485Ssklower 454*22485Ssklower xns_getaddr(addr, saddr) 455*22485Ssklower char *addr; 456*22485Ssklower struct sockaddr *saddr; 457*22485Ssklower { 458*22485Ssklower register struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 459*22485Ssklower u_long netnum; 460*22485Ssklower char *index(); 461*22485Ssklower register char *s = index(addr, ':'); 462*22485Ssklower register int i; 463*22485Ssklower 464*22485Ssklower if (s!=NULL) *s = 0; 465*22485Ssklower netnum = atoi(addr); 466*22485Ssklower netnum = htonl(netnum); 467*22485Ssklower setxnnet(sns->sns_addr.x_net, netnum); 468*22485Ssklower sns->sns_family = AF_NS; 469*22485Ssklower 470*22485Ssklower for (i = 0; i < 6; i++) { 471*22485Ssklower if (s == NULL || *++s == 0) 472*22485Ssklower break; 473*22485Ssklower sns->sns_addr.x_host.c_host[i] = xtoi(s); 474*22485Ssklower s = index(s, '.'); 475*22485Ssklower } 476*22485Ssklower 477*22485Ssklower } 478*22485Ssklower 479*22485Ssklower char * 480*22485Ssklower xns_ntoa(sns) 481*22485Ssklower register struct sockaddr_ns *sns; 482*22485Ssklower { 483*22485Ssklower static char buf[30]; 484*22485Ssklower 485*22485Ssklower sprintf (buf, "%d:%x.%x.%x.%x.%x.%x", 486*22485Ssklower ntohl(ns_netof(sns->sns_addr)), 487*22485Ssklower sns->sns_addr.x_host.c_host[0], sns->sns_addr.x_host.c_host[1], 488*22485Ssklower sns->sns_addr.x_host.c_host[2], sns->sns_addr.x_host.c_host[3], 489*22485Ssklower sns->sns_addr.x_host.c_host[4], sns->sns_addr.x_host.c_host[5]); 490*22485Ssklower return (buf); 491*22485Ssklower } 492*22485Ssklower 493*22485Ssklower int xtoi(s) 494*22485Ssklower register char *s; 495*22485Ssklower { 496*22485Ssklower register int res = 0, delta; 497*22485Ssklower register char *cp; 498*22485Ssklower static char base[] = "0123456789ABCDEFabcdef"; 499*22485Ssklower 500*22485Ssklower for(; *s; s++) { 501*22485Ssklower cp = index(base, *s); 502*22485Ssklower if (cp==NULL) 503*22485Ssklower break; 504*22485Ssklower if ((delta = cp - base) > 15) 505*22485Ssklower delta -= 6; 506*22485Ssklower res = (res << 4) + delta; 507*22485Ssklower } 508*22485Ssklower return(res); 509*22485Ssklower } 510