xref: /csrg-svn/sbin/ifconfig/ifconfig.c (revision 21811)
1*21811Skarels /*
2*21811Skarels  * Copyright (c) 1983 Regents of the University of California.
3*21811Skarels  * All rights reserved.  The Berkeley software License Agreement
4*21811Skarels  * specifies the terms and conditions for redistribution.
5*21811Skarels  */
6*21811Skarels 
714869Ssam #ifndef lint
8*21811Skarels char copyright[] =
9*21811Skarels "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10*21811Skarels  All rights reserved.\n";
11*21811Skarels #endif not lint
1214869Ssam 
13*21811Skarels #ifndef lint
14*21811Skarels static char sccsid[] = "@(#)ifconfig.c	4.11 (Berkeley) 06/03/85";
15*21811Skarels #endif not lint
16*21811Skarels 
17*21811Skarels 
1814869Ssam #include <sys/types.h>
1914869Ssam #include <sys/socket.h>
2014869Ssam #include <sys/ioctl.h>
2114869Ssam 
2214869Ssam #include <netinet/in.h>
2314869Ssam #include <net/if.h>
2414869Ssam 
2514869Ssam #include <stdio.h>
2614869Ssam #include <errno.h>
2714869Ssam #include <ctype.h>
2814869Ssam #include <netdb.h>
2914869Ssam 
3014869Ssam struct	ifreq ifr;
3114869Ssam struct	sockaddr_in sin = { AF_INET };
32*21811Skarels struct	sockaddr_in broadaddr;
33*21811Skarels struct	sockaddr_in netmask = { AF_INET };
3414869Ssam char	name[30];
35*21811Skarels int	flags;
3616329Skarels int	setaddr;
37*21811Skarels int	setmask;
38*21811Skarels int	setbroadaddr;
3914869Ssam int	s;
40*21811Skarels extern	int errno;
4114869Ssam 
42*21811Skarels int	setifflags(), setifaddr(), setifdstaddr(), setifnetmask();
43*21811Skarels int	setifbroadaddr();
4414869Ssam 
45*21811Skarels #define	NEXTARG		0xffffff
46*21811Skarels 
4714869Ssam struct	cmd {
4814869Ssam 	char	*c_name;
49*21811Skarels 	int	c_parameter;		/* NEXTARG means next argv */
5014869Ssam 	int	(*c_func)();
5114869Ssam } cmds[] = {
5214869Ssam 	{ "up",		IFF_UP,		setifflags } ,
5314869Ssam 	{ "down",	-IFF_UP,	setifflags },
5414869Ssam 	{ "trailers",	-IFF_NOTRAILERS,setifflags },
5514869Ssam 	{ "-trailers",	IFF_NOTRAILERS,	setifflags },
5615359Skarels 	{ "arp",	-IFF_NOARP,	setifflags },
5715359Skarels 	{ "-arp",	IFF_NOARP,	setifflags },
58*21811Skarels #ifdef IFF_LOCAL
5916329Skarels 	{ "local",	IFF_LOCAL,	setifflags },
6016329Skarels 	{ "-local",	-IFF_LOCAL,	setifflags },
61*21811Skarels #endif
6215286Sleres 	{ "debug",	IFF_DEBUG,	setifflags },
6315286Sleres 	{ "-debug",	-IFF_DEBUG,	setifflags },
6415004Ssam #ifdef notdef
65*21811Skarels #define	EN_SWABIPS	0x1000
6615004Ssam 	{ "swabips",	EN_SWABIPS,	setifflags },
6715004Ssam 	{ "-swabips",	-EN_SWABIPS,	setifflags },
6815004Ssam #endif
69*21811Skarels 	{ "netmask",	NEXTARG,	setifnetmask },
70*21811Skarels 	{ "broadcast",	NEXTARG,	setifbroadaddr },
7114869Ssam 	{ 0,		0,		setifaddr },
7217218Stef 	{ 0,		0,		setifdstaddr },
7314869Ssam };
7414869Ssam 
7514869Ssam main(argc, argv)
7614869Ssam 	int argc;
7714869Ssam 	char *argv[];
7814869Ssam {
7914869Ssam 
8014869Ssam 	if (argc < 2) {
8114869Ssam 		fprintf(stderr, "usage: ifconfig interface %s %s %s\n",
8217218Stef 		    "[ address [ dest_addr ] ] [ up ] [ down ]",
83*21811Skarels 		    "[ netmask mask ]",
8414869Ssam 		    "[ trailers | -trailers ]",
8514869Ssam 		    "[ arp | -arp ]");
8614869Ssam 		exit(1);
8714869Ssam 	}
8814869Ssam 	s = socket(AF_INET, SOCK_DGRAM, 0);
8914869Ssam 	if (s < 0) {
9014869Ssam 		perror("ifconfig: socket");
9114869Ssam 		exit(1);
9214869Ssam 	}
9314869Ssam 	argc--, argv++;
9414869Ssam 	strcpy(name, *argv);
9514869Ssam 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
9614869Ssam 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
9714869Ssam 		Perror("ioctl (SIOCGIFFLAGS)");
9814869Ssam 		exit(1);
9914869Ssam 	}
100*21811Skarels 	flags = ifr.ifr_flags;
101*21811Skarels 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
102*21811Skarels 	if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
103*21811Skarels 		if (errno != EADDRNOTAVAIL)
104*21811Skarels 			Perror("ioctl (SIOCGIFNETMASK)");
105*21811Skarels 	} else
106*21811Skarels 		netmask.sin_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
10714869Ssam 	argc--, argv++;
10814869Ssam 	if (argc == 0) {
10914869Ssam 		status();
11014869Ssam 		exit(0);
11114869Ssam 	}
11214869Ssam 	while (argc > 0) {
11314869Ssam 		register struct cmd *p;
11414869Ssam 
11514869Ssam 		for (p = cmds; p->c_name; p++)
11614869Ssam 			if (strcmp(*argv, p->c_name) == 0)
11714869Ssam 				break;
11817218Stef 		if (p->c_name == 0 && setaddr)
11917218Stef 			p++;	/* got src, do dst */
120*21811Skarels 		if (p->c_func) {
121*21811Skarels 			if (p->c_parameter == NEXTARG) {
122*21811Skarels 				(*p->c_func)(argv[1]);
123*21811Skarels 				argc--, argv++;
124*21811Skarels 			} else
125*21811Skarels 				(*p->c_func)(*argv, p->c_parameter);
126*21811Skarels 		}
12714869Ssam 		argc--, argv++;
12814869Ssam 	}
129*21811Skarels 	if (setmask || setaddr) {
130*21811Skarels 		/*
131*21811Skarels 		 * If setting the address and not the mask,
132*21811Skarels 		 * clear any existing mask and the kernel will then
133*21811Skarels 		 * assign the default.  If setting both,
134*21811Skarels 		 * set the mask first, so the address will be
135*21811Skarels 		 * interpreted correctly.
136*21811Skarels 		 */
137*21811Skarels 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
138*21811Skarels 		ifr.ifr_addr = *(struct sockaddr *)&netmask;
139*21811Skarels 		if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0)
140*21811Skarels 			Perror("ioctl (SIOCSIFNETMASK)");
141*21811Skarels 	}
14216329Skarels 	if (setaddr) {
14316329Skarels 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
14416329Skarels 		ifr.ifr_addr = *(struct sockaddr *) &sin;
14516329Skarels 		if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
14616329Skarels 			Perror("ioctl (SIOCSIFADDR)");
14716329Skarels 	}
148*21811Skarels 	if (setbroadaddr) {
149*21811Skarels 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
150*21811Skarels 		ifr.ifr_addr = *(struct sockaddr *)&broadaddr;
151*21811Skarels 		if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0)
152*21811Skarels 			Perror("ioctl (SIOCSIFBRDADDR)");
153*21811Skarels 	}
15414869Ssam 	exit(0);
15514869Ssam }
15614869Ssam 
15714869Ssam /*ARGSUSED*/
15814869Ssam setifaddr(addr, param)
15914869Ssam 	char *addr;
16014869Ssam 	int param;
16114869Ssam {
16214869Ssam 
16316329Skarels 	getaddr(addr, &sin);
16416329Skarels 	/*
16516329Skarels 	 * Delay the ioctl to set the interface addr until flags are all set.
16616329Skarels 	 * The address interpretation may depend on the flags,
16716329Skarels 	 * and the flags may change when the address is set.
16815390Skarels 	 */
16916329Skarels 	setaddr++;
17014869Ssam }
17114869Ssam 
172*21811Skarels setifnetmask(addr)
173*21811Skarels 	char *addr;
174*21811Skarels {
175*21811Skarels 
176*21811Skarels 	getaddr(addr, &netmask);
177*21811Skarels 	setmask++;
178*21811Skarels }
179*21811Skarels 
180*21811Skarels setifbroadaddr(addr)
181*21811Skarels 	char *addr;
182*21811Skarels {
183*21811Skarels 	getaddr(addr, &broadaddr);
184*21811Skarels 	setbroadaddr++;
185*21811Skarels }
186*21811Skarels 
18717218Stef /*ARGSUSED*/
18817218Stef setifdstaddr(addr, param)
18917218Stef 	char *addr;
19017218Stef 	int param;
19117218Stef {
19217218Stef 
19317218Stef 	getaddr(addr, (struct sockaddr_in *)&ifr.ifr_dstaddr);
19417218Stef 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
19517218Stef 	if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0)
19617218Stef 		Perror("ioctl (SIOCSIFDSTADDR)");
19717218Stef }
19817218Stef 
19914870Ssam setifflags(vname, value)
20014870Ssam 	char *vname;
20114869Ssam 	int value;
20214869Ssam {
20314869Ssam 
20414869Ssam 	if (value < 0) {
20514869Ssam 		value = -value;
206*21811Skarels 		flags &= ~value;
20714869Ssam 	} else
208*21811Skarels 		flags |= value;
20914869Ssam 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
210*21811Skarels 	ifr.ifr_flags = flags;
21114869Ssam 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
21214870Ssam 		Perror(vname);
21314869Ssam }
21414869Ssam 
21514869Ssam status()
21614869Ssam {
21714869Ssam 	struct sockaddr_in *sin;
21814869Ssam 
21914869Ssam 	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
220*21811Skarels 	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
221*21811Skarels 		if (errno == EADDRNOTAVAIL)
222*21811Skarels 			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
223*21811Skarels 		else
224*21811Skarels 			Perror("ioctl (SIOCGIFADDR)");
225*21811Skarels 	}
22614869Ssam 	sin = (struct sockaddr_in *)&ifr.ifr_addr;
22714869Ssam 	printf("%s: %s ", name, inet_ntoa(sin->sin_addr));
22817218Stef 	if (flags & IFF_POINTOPOINT) {
22917218Stef 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
230*21811Skarels 		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
231*21811Skarels 			if (errno == EADDRNOTAVAIL)
232*21811Skarels 			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
233*21811Skarels 			else
234*21811Skarels 			    Perror("ioctl (SIOCGIFDSTADDR)");
235*21811Skarels 		}
23617218Stef 		sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
23717218Stef 		printf("--> %s ", inet_ntoa(sin->sin_addr));
23817218Stef 	}
239*21811Skarels 	printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
24014869Ssam #define	IFFBITS \
24116329Skarels "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
24216329Skarels \11LOCAL"
24314869Ssam 	printb("flags", flags, IFFBITS); putchar('\n');
244*21811Skarels 	if (flags & IFF_BROADCAST) {
245*21811Skarels 		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
246*21811Skarels 		if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
247*21811Skarels 			if (errno == EADDRNOTAVAIL)
248*21811Skarels 				return;
249*21811Skarels 			Perror("ioctl (SIOCGIFADDR)");
250*21811Skarels 		}
251*21811Skarels 		sin = (struct sockaddr_in *)&ifr.ifr_addr;
252*21811Skarels 		printf("broadcast: %s\n", inet_ntoa(sin->sin_addr));
253*21811Skarels 	}
25414869Ssam }
25514869Ssam 
25614869Ssam Perror(cmd)
25714869Ssam 	char *cmd;
25814869Ssam {
25914869Ssam 	extern int errno;
26014869Ssam 
26114869Ssam 	fprintf(stderr, "ifconfig: ");
26214869Ssam 	switch (errno) {
26314869Ssam 
26414869Ssam 	case ENXIO:
26514869Ssam 		fprintf(stderr, "%s: ", cmd);
26614869Ssam 		fprintf(stderr, "no such interface\n");
26714869Ssam 		break;
26814869Ssam 
26914869Ssam 	case EPERM:
27016822Slepreau 		fprintf(stderr, "%s: permission denied\n", cmd);
27114869Ssam 		break;
27214869Ssam 
27314869Ssam 	default:
27414869Ssam 		perror(cmd);
27514869Ssam 	}
27614869Ssam 	exit(1);
27714869Ssam }
27814869Ssam 
27914869Ssam struct	in_addr inet_makeaddr();
28014869Ssam 
28114869Ssam getaddr(s, sin)
28214869Ssam 	char *s;
28314869Ssam 	struct sockaddr_in *sin;
28414869Ssam {
28514869Ssam 	struct hostent *hp;
28614869Ssam 	struct netent *np;
28714869Ssam 	int val;
28814869Ssam 
289*21811Skarels 	sin->sin_family = AF_INET;
290*21811Skarels 	val = inet_addr(s);
291*21811Skarels 	if (val != -1) {
292*21811Skarels 		sin->sin_addr.s_addr = val;
293*21811Skarels 		return;
294*21811Skarels 	}
29514869Ssam 	hp = gethostbyname(s);
29614869Ssam 	if (hp) {
29714869Ssam 		sin->sin_family = hp->h_addrtype;
29814869Ssam 		bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
29914869Ssam 		return;
30014869Ssam 	}
30114869Ssam 	np = getnetbyname(s);
30214869Ssam 	if (np) {
30314869Ssam 		sin->sin_family = np->n_addrtype;
30414869Ssam 		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
30514869Ssam 		return;
30614869Ssam 	}
30714869Ssam 	fprintf(stderr, "%s: bad value\n", s);
30814869Ssam 	exit(1);
30914869Ssam }
31014869Ssam 
31114869Ssam /*
31214869Ssam  * Print a value a la the %b format of the kernel's printf
31314869Ssam  */
31414869Ssam printb(s, v, bits)
31514869Ssam 	char *s;
31614869Ssam 	register char *bits;
31714869Ssam 	register unsigned short v;
31814869Ssam {
31914869Ssam 	register int i, any = 0;
32014869Ssam 	register char c;
32114869Ssam 
32214869Ssam 	if (bits && *bits == 8)
32314869Ssam 		printf("%s=%o", s, v);
32414869Ssam 	else
32514869Ssam 		printf("%s=%x", s, v);
32614869Ssam 	bits++;
32714869Ssam 	if (bits) {
32814869Ssam 		putchar('<');
32914869Ssam 		while (i = *bits++) {
33014869Ssam 			if (v & (1 << (i-1))) {
33114869Ssam 				if (any)
33214869Ssam 					putchar(',');
33314869Ssam 				any = 1;
33414869Ssam 				for (; (c = *bits) > 32; bits++)
33514869Ssam 					putchar(c);
33614869Ssam 			} else
33714869Ssam 				for (; *bits > 32; bits++)
33814869Ssam 					;
33914869Ssam 		}
34014869Ssam 		putchar('>');
34114869Ssam 	}
34214869Ssam }
343