xref: /csrg-svn/sbin/ifconfig/ifconfig.c (revision 26101)
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