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*30692Smckusick static char sccsid[] = "@(#)ifconfig.c 4.19 (Berkeley) 03/29/87"; 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; 10827061Skarels 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 } 16827061Skarels 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) { 29928468Skarels (*p->af_status)(1); 30028468Skarels } else for (p = afs; p->af_name; p++) { 30122485Ssklower ifr.ifr_addr.sa_family = p->af_af; 30228468Skarels (*p->af_status)(0); 30322485Ssklower } 30422485Ssklower } 30522485Ssklower 30628468Skarels in_status(force) 30728468Skarels int force; 30822485Ssklower { 30914869Ssam struct sockaddr_in *sin; 31022485Ssklower char *inet_ntoa(); 31114869Ssam 31227061Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 31321811Skarels if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 31428468Skarels if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 31528468Skarels if (!force) 31628468Skarels return; 31721811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 31828468Skarels } else 31928468Skarels perror("ioctl (SIOCGIFADDR)"); 32021811Skarels } 32114869Ssam sin = (struct sockaddr_in *)&ifr.ifr_addr; 32226429Skarels printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 32328468Skarels strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 32428468Skarels if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 32528468Skarels if (errno != EADDRNOTAVAIL) 32628468Skarels perror("ioctl (SIOCGIFNETMASK)"); 32728468Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 32828468Skarels } else 32928468Skarels netmask.sin_addr = 33028468Skarels ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 33117218Stef if (flags & IFF_POINTOPOINT) { 33221811Skarels if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 33321811Skarels if (errno == EADDRNOTAVAIL) 33421811Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 33521811Skarels else 33628468Skarels perror("ioctl (SIOCGIFDSTADDR)"); 33721811Skarels } 33822485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 33917218Stef sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 34017218Stef printf("--> %s ", inet_ntoa(sin->sin_addr)); 34117218Stef } 34221811Skarels printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 34321811Skarels if (flags & IFF_BROADCAST) { 34421811Skarels if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 34521811Skarels if (errno == EADDRNOTAVAIL) 34628468Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 34728468Skarels else 34828468Skarels perror("ioctl (SIOCGIFADDR)"); 34921811Skarels } 35022485Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 35121811Skarels sin = (struct sockaddr_in *)&ifr.ifr_addr; 35228468Skarels if (sin->sin_addr.s_addr != 0) 35328468Skarels printf("broadcast %s", inet_ntoa(sin->sin_addr)); 35421811Skarels } 35526185Skarels putchar('\n'); 35614869Ssam } 35714869Ssam 35822485Ssklower 35928468Skarels xns_status(force) 36028468Skarels int force; 36122485Ssklower { 36222485Ssklower struct sockaddr_ns *sns; 36322485Ssklower 36422485Ssklower close(s); 36522485Ssklower s = socket(AF_NS, SOCK_DGRAM, 0); 36622485Ssklower if (s < 0) { 367*30692Smckusick if (errno == EPROTONOSUPPORT) 36824248Ssklower return; 36922485Ssklower perror("ifconfig: socket"); 37022485Ssklower exit(1); 37122485Ssklower } 37222485Ssklower if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 37328468Skarels if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 37428468Skarels if (!force) 37528468Skarels return; 37628468Skarels bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 37728468Skarels } else 37828468Skarels perror("ioctl (SIOCGIFADDR)"); 37922485Ssklower } 38022485Ssklower strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 38122485Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_addr; 38226185Skarels printf("\tns %s ", ns_ntoa(sns->sns_addr)); 38326101Ssklower if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 38426101Ssklower if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 38526101Ssklower if (errno == EADDRNOTAVAIL) 38626101Ssklower bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 38726101Ssklower else 38826101Ssklower Perror("ioctl (SIOCGIFDSTADDR)"); 38926101Ssklower } 39026101Ssklower strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 39126101Ssklower sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 39226101Ssklower printf("--> %s ", ns_ntoa(sns->sns_addr)); 39326101Ssklower } 39422485Ssklower putchar('\n'); 39522485Ssklower } 39622485Ssklower 39714869Ssam Perror(cmd) 39814869Ssam char *cmd; 39914869Ssam { 40014869Ssam extern int errno; 40114869Ssam 40214869Ssam fprintf(stderr, "ifconfig: "); 40314869Ssam switch (errno) { 40414869Ssam 40514869Ssam case ENXIO: 40622485Ssklower fprintf(stderr, "%s: no such interface\n", cmd); 40714869Ssam break; 40814869Ssam 40914869Ssam case EPERM: 41016822Slepreau fprintf(stderr, "%s: permission denied\n", cmd); 41114869Ssam break; 41214869Ssam 41314869Ssam default: 41414869Ssam perror(cmd); 41514869Ssam } 41614869Ssam exit(1); 41714869Ssam } 41814869Ssam 41914869Ssam struct in_addr inet_makeaddr(); 42014869Ssam 42122485Ssklower in_getaddr(s, saddr) 42214869Ssam char *s; 42322485Ssklower struct sockaddr *saddr; 42414869Ssam { 42522485Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 42614869Ssam struct hostent *hp; 42714869Ssam struct netent *np; 42814869Ssam int val; 42914869Ssam 43021811Skarels sin->sin_family = AF_INET; 43121811Skarels val = inet_addr(s); 43221811Skarels if (val != -1) { 43321811Skarels sin->sin_addr.s_addr = val; 43421811Skarels return; 43521811Skarels } 43614869Ssam hp = gethostbyname(s); 43714869Ssam if (hp) { 43814869Ssam sin->sin_family = hp->h_addrtype; 43914869Ssam bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 44014869Ssam return; 44114869Ssam } 44214869Ssam np = getnetbyname(s); 44314869Ssam if (np) { 44414869Ssam sin->sin_family = np->n_addrtype; 44514869Ssam sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 44614869Ssam return; 44714869Ssam } 44814869Ssam fprintf(stderr, "%s: bad value\n", s); 44914869Ssam exit(1); 45014869Ssam } 45114869Ssam 45214869Ssam /* 45314869Ssam * Print a value a la the %b format of the kernel's printf 45414869Ssam */ 45514869Ssam printb(s, v, bits) 45614869Ssam char *s; 45714869Ssam register char *bits; 45814869Ssam register unsigned short v; 45914869Ssam { 46014869Ssam register int i, any = 0; 46114869Ssam register char c; 46214869Ssam 46314869Ssam if (bits && *bits == 8) 46414869Ssam printf("%s=%o", s, v); 46514869Ssam else 46614869Ssam printf("%s=%x", s, v); 46714869Ssam bits++; 46814869Ssam if (bits) { 46914869Ssam putchar('<'); 47014869Ssam while (i = *bits++) { 47114869Ssam if (v & (1 << (i-1))) { 47214869Ssam if (any) 47314869Ssam putchar(','); 47414869Ssam any = 1; 47514869Ssam for (; (c = *bits) > 32; bits++) 47614869Ssam putchar(c); 47714869Ssam } else 47814869Ssam for (; *bits > 32; bits++) 47914869Ssam ; 48014869Ssam } 48114869Ssam putchar('>'); 48214869Ssam } 48314869Ssam } 48422485Ssklower 48522485Ssklower xns_getaddr(addr, saddr) 48622485Ssklower char *addr; 48722485Ssklower struct sockaddr *saddr; 48822485Ssklower { 48926101Ssklower struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 49026101Ssklower struct ns_addr ns_addr(); 49122485Ssklower sns->sns_family = AF_NS; 49226101Ssklower sns->sns_addr = ns_addr(addr); 49322485Ssklower } 494