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*27061Skarels static char sccsid[] = "@(#)ifconfig.c 4.17 (Berkeley) 04/12/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; 4126185Skarels 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(); 5026185Skarels 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 }, 7326185Skarels { "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; 108*27061Skarels 10914869Ssam if (argc < 2) { 11026185Skarels fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s", 11126185Skarels "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]", 11226185Skarels "[ netmask mask ] ]\n", 11326185Skarels "\t[ metric n ]\n", 11426185Skarels "\t[ trailers | -trailers ]\n", 11526185Skarels "\t[ arp | -arp ]\n"); 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; 14326185Skarels if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 14426185Skarels perror("ioctl (SIOCGIFMETRIC)"); 14526185Skarels else 14626185Skarels metric = ifr.ifr_metric; 14714869Ssam if (argc == 0) { 14814869Ssam status(); 14914869Ssam exit(0); 15014869Ssam } 15114869Ssam while (argc > 0) { 15214869Ssam register struct cmd *p; 15314869Ssam 15414869Ssam for (p = cmds; p->c_name; p++) 15514869Ssam if (strcmp(*argv, p->c_name) == 0) 15614869Ssam break; 15717218Stef if (p->c_name == 0 && setaddr) 15817218Stef p++; /* got src, do dst */ 15921811Skarels if (p->c_func) { 16021811Skarels if (p->c_parameter == NEXTARG) { 16121811Skarels (*p->c_func)(argv[1]); 16221811Skarels argc--, argv++; 16321811Skarels } else 16421811Skarels (*p->c_func)(*argv, p->c_parameter); 16521811Skarels } 16614869Ssam argc--, argv++; 16714869Ssam } 168*27061Skarels if ((setmask || setaddr) && (af == AF_INET)) { 16921811Skarels /* 17021811Skarels * If setting the address and not the mask, 17121811Skarels * clear any existing mask and the kernel will then 17221811Skarels * assign the default. If setting both, 17321811Skarels * set the mask first, so the address will be 17421811Skarels * interpreted correctly. 17521811Skarels */ 17621811Skarels ifr.ifr_addr = *(struct sockaddr *)&netmask; 17721811Skarels if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 17821811Skarels Perror("ioctl (SIOCSIFNETMASK)"); 17921811Skarels } 18022485Ssklower if (setipdst && af==AF_NS) { 18122485Ssklower struct nsip_req rq; 18222485Ssklower int size = sizeof(rq); 18322485Ssklower 18422485Ssklower rq.rq_ns = *(struct sockaddr *) &sin; 18522485Ssklower rq.rq_ip = *(struct sockaddr *) &ipdst; 18622485Ssklower 18722485Ssklower if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 18822485Ssklower Perror("Encapsulation Routing"); 18922485Ssklower setaddr = 0; 19022485Ssklower } 19116329Skarels if (setaddr) { 19216329Skarels ifr.ifr_addr = *(struct sockaddr *) &sin; 19316329Skarels if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 19416329Skarels Perror("ioctl (SIOCSIFADDR)"); 19516329Skarels } 19621811Skarels if (setbroadaddr) { 19721811Skarels ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 19821811Skarels if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 19921811Skarels Perror("ioctl (SIOCSIFBRDADDR)"); 20021811Skarels } 20114869Ssam exit(0); 20214869Ssam } 20314869Ssam 20414869Ssam /*ARGSUSED*/ 20514869Ssam setifaddr(addr, param) 20614869Ssam char *addr; 20722485Ssklower short param; 20814869Ssam { 20916329Skarels /* 21016329Skarels * Delay the ioctl to set the interface addr until flags are all set. 21116329Skarels * The address interpretation may depend on the flags, 21216329Skarels * and the flags may change when the address is set. 21315390Skarels */ 21416329Skarels setaddr++; 21522485Ssklower (*afp->af_getaddr)(addr, &sin); 21614869Ssam } 21714869Ssam 21821811Skarels setifnetmask(addr) 21921811Skarels char *addr; 22021811Skarels { 22122485Ssklower in_getaddr(addr, &netmask); 22221811Skarels setmask++; 22321811Skarels } 22421811Skarels 22521811Skarels setifbroadaddr(addr) 22621811Skarels char *addr; 22721811Skarels { 22822485Ssklower (*afp->af_getaddr)(addr, &broadaddr); 22921811Skarels setbroadaddr++; 23021811Skarels } 23121811Skarels 23222485Ssklower setifipdst(addr) 23322485Ssklower char *addr; 23422485Ssklower { 23522485Ssklower in_getaddr(addr, &ipdst); 23622485Ssklower setipdst++; 23722485Ssklower } 23822485Ssklower 23917218Stef /*ARGSUSED*/ 24017218Stef setifdstaddr(addr, param) 24117218Stef char *addr; 24217218Stef int param; 24317218Stef { 24417218Stef 24522485Ssklower (*afp->af_getaddr)(addr, &ifr.ifr_addr); 24617218Stef if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 24717218Stef Perror("ioctl (SIOCSIFDSTADDR)"); 24817218Stef } 24917218Stef 25014870Ssam setifflags(vname, value) 25114870Ssam char *vname; 25222485Ssklower short value; 25314869Ssam { 25422485Ssklower if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 25522485Ssklower Perror("ioctl (SIOCGIFFLAGS)"); 25622485Ssklower exit(1); 25722485Ssklower } 25822485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 25922485Ssklower flags = ifr.ifr_flags; 26014869Ssam 26114869Ssam if (value < 0) { 26214869Ssam value = -value; 26321811Skarels flags &= ~value; 26414869Ssam } else 26521811Skarels flags |= value; 26621811Skarels ifr.ifr_flags = flags; 26714869Ssam if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 26814870Ssam Perror(vname); 26914869Ssam } 27014869Ssam 27126185Skarels setifmetric(val) 27226185Skarels char *val; 27326185Skarels { 27426185Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 27526185Skarels ifr.ifr_metric = atoi(val); 27626185Skarels if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 27726185Skarels perror("ioctl (set metric)"); 27826185Skarels } 27926185Skarels 28026185Skarels #define IFFBITS \ 28126185Skarels "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 28226185Skarels " 28326185Skarels 28422485Ssklower /* 28522485Ssklower * Print the status of the interface. If an address family was 28622485Ssklower * specified, show it and it only; otherwise, show them all. 28722485Ssklower */ 28814869Ssam status() 28914869Ssam { 29022485Ssklower register struct afswtch *p = afp; 29122485Ssklower short af = ifr.ifr_addr.sa_family; 29222485Ssklower 29326185Skarels printf("%s: ", name); 29426185Skarels printb("flags", flags, IFFBITS); 29526185Skarels if (metric) 29626185Skarels printf(" metric %d", metric); 29726185Skarels putchar('\n'); 29822485Ssklower if ((p = afp) != NULL) { 29922485Ssklower (*p->af_status)(); 30022485Ssklower return; 30122485Ssklower } 30222485Ssklower for (p = afs; p->af_name; p++) { 30322485Ssklower ifr.ifr_addr.sa_family = p->af_af; 30422485Ssklower (*p->af_status)(); 30522485Ssklower } 30622485Ssklower } 30722485Ssklower 30822485Ssklower in_status() 30922485Ssklower { 31014869Ssam struct sockaddr_in *sin; 31122485Ssklower char *inet_ntoa(); 31214869Ssam 313*27061Skarels if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 314*27061Skarels if (errno != EADDRNOTAVAIL) 315*27061Skarels Perror("ioctl (SIOCGIFNETMASK)"); 316*27061Skarels } else 317*27061Skarels netmask.sin_addr = 318*27061Skarels ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 319*27061Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32021811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 32121811Skarels if (errno == EADDRNOTAVAIL) 32221811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 32321811Skarels else 32421811Skarels Perror("ioctl (SIOCGIFADDR)"); 32521811Skarels } 32622485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32714869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 32826429Skarels printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 32917218Stef if (flags & IFF_POINTOPOINT) { 33021811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 33121811Skarels if (errno == EADDRNOTAVAIL) 33221811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 33321811Skarels else 33421811Skarels Perror("ioctl (SIOCGIFDSTADDR)"); 33521811Skarels } 33622485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 33717218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 33817218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 33917218Stef } 34021811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 34121811Skarels if (flags & IFF_BROADCAST) { 34221811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 34321811Skarels if (errno == EADDRNOTAVAIL) 34421811Skarels return; 34521811Skarels Perror("ioctl (SIOCGIFADDR)"); 34621811Skarels } 34722485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 34821811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 34926185Skarels printf("broadcast %s", inet_ntoa(sin->sin_addr)); 35021811Skarels } 35126185Skarels putchar('\n'); 35214869Ssam } 35314869Ssam 35422485Ssklower 35522485Ssklower xns_status() 35622485Ssklower { 35722485Ssklower struct sockaddr_ns *sns; 35822485Ssklower 35922485Ssklower close(s); 36022485Ssklower s = socket(AF_NS, SOCK_DGRAM, 0); 36122485Ssklower if (s < 0) { 36224248Ssklower if (errno == EAFNOSUPPORT) 36324248Ssklower return; 36422485Ssklower perror("ifconfig: socket"); 36522485Ssklower exit(1); 36622485Ssklower } 36722485Ssklower if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 36824248Ssklower if (errno == EADDRNOTAVAIL || errno==EAFNOSUPPORT) 36922485Ssklower return; 37022485Ssklower Perror("ioctl (SIOCGIFADDR)"); 37122485Ssklower } 37222485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 37322485Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_addr; 37426185Skarels printf("\tns %s ", ns_ntoa(sns->sns_addr)); 37526101Ssklower if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 37626101Ssklower if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 37726101Ssklower if (errno == EADDRNOTAVAIL) 37826101Ssklower bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 37926101Ssklower else 38026101Ssklower Perror("ioctl (SIOCGIFDSTADDR)"); 38126101Ssklower } 38226101Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 38326101Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 38426101Ssklower printf("--> %s ", ns_ntoa(sns->sns_addr)); 38526101Ssklower } 38622485Ssklower putchar('\n'); 38722485Ssklower } 38822485Ssklower 38914869Ssam Perror(cmd) 39014869Ssam char *cmd; 39114869Ssam { 39214869Ssam extern int errno; 39314869Ssam 39414869Ssam fprintf(stderr, "ifconfig: "); 39514869Ssam switch (errno) { 39614869Ssam 39714869Ssam case ENXIO: 39822485Ssklower fprintf(stderr, "%s: no such interface\n", cmd); 39914869Ssam break; 40014869Ssam 40114869Ssam case EPERM: 40216822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 40314869Ssam break; 40414869Ssam 40514869Ssam default: 40614869Ssam perror(cmd); 40714869Ssam } 40814869Ssam exit(1); 40914869Ssam } 41014869Ssam 41114869Ssam struct in_addr inet_makeaddr(); 41214869Ssam 41322485Ssklower in_getaddr(s, saddr) 41414869Ssam char *s; 41522485Ssklower struct sockaddr *saddr; 41614869Ssam { 41722485Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 41814869Ssam struct hostent *hp; 41914869Ssam struct netent *np; 42014869Ssam int val; 42114869Ssam 42221811Skarels sin->sin_family = AF_INET; 42321811Skarels val = inet_addr(s); 42421811Skarels if (val != -1) { 42521811Skarels sin->sin_addr.s_addr = val; 42621811Skarels return; 42721811Skarels } 42814869Ssam hp = gethostbyname(s); 42914869Ssam if (hp) { 43014869Ssam sin->sin_family = hp->h_addrtype; 43114869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 43214869Ssam return; 43314869Ssam } 43414869Ssam np = getnetbyname(s); 43514869Ssam if (np) { 43614869Ssam sin->sin_family = np->n_addrtype; 43714869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 43814869Ssam return; 43914869Ssam } 44014869Ssam fprintf(stderr, "%s: bad value\n", s); 44114869Ssam exit(1); 44214869Ssam } 44314869Ssam 44414869Ssam /* 44514869Ssam * Print a value a la the %b format of the kernel's printf 44614869Ssam */ 44714869Ssam printb(s, v, bits) 44814869Ssam char *s; 44914869Ssam register char *bits; 45014869Ssam register unsigned short v; 45114869Ssam { 45214869Ssam register int i, any = 0; 45314869Ssam register char c; 45414869Ssam 45514869Ssam if (bits && *bits == 8) 45614869Ssam printf("%s=%o", s, v); 45714869Ssam else 45814869Ssam printf("%s=%x", s, v); 45914869Ssam bits++; 46014869Ssam if (bits) { 46114869Ssam putchar('<'); 46214869Ssam while (i = *bits++) { 46314869Ssam if (v & (1 << (i-1))) { 46414869Ssam if (any) 46514869Ssam putchar(','); 46614869Ssam any = 1; 46714869Ssam for (; (c = *bits) > 32; bits++) 46814869Ssam putchar(c); 46914869Ssam } else 47014869Ssam for (; *bits > 32; bits++) 47114869Ssam ; 47214869Ssam } 47314869Ssam putchar('>'); 47414869Ssam } 47514869Ssam } 47622485Ssklower 47722485Ssklower xns_getaddr(addr, saddr) 47822485Ssklower char *addr; 47922485Ssklower struct sockaddr *saddr; 48022485Ssklower { 48126101Ssklower struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 48226101Ssklower struct ns_addr ns_addr(); 48322485Ssklower sns->sns_family = AF_NS; 48426101Ssklower sns->sns_addr = ns_addr(addr); 48522485Ssklower } 486