Add support for changing the IFF_DEBUG bit
[unix-history] / usr / src / sbin / ifconfig / ifconfig.c
#ifndef lint
static char sccsid[] = "@(#)ifconfig.c 4.4 (Berkeley) %G%";
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <netdb.h>
struct ifreq ifr;
struct sockaddr_in sin = { AF_INET };
char name[30];
int flags;
int s;
int setifflags(), setifaddr();
struct cmd {
char *c_name;
int c_parameter;
int (*c_func)();
} cmds[] = {
{ "up", IFF_UP, setifflags } ,
{ "down", -IFF_UP, setifflags },
{ "trailers", -IFF_NOTRAILERS,setifflags },
{ "-trailers", IFF_NOTRAILERS, setifflags },
{ "arp", IFF_NOARP, setifflags },
{ "-arp", -IFF_NOARP, setifflags },
{ "debug", IFF_DEBUG, setifflags },
{ "-debug", -IFF_DEBUG, setifflags },
#ifdef notdef
#define EN_SWABIPS 0x100
{ "swabips", EN_SWABIPS, setifflags },
{ "-swabips", -EN_SWABIPS, setifflags },
#endif
{ 0, 0, setifaddr },
};
main(argc, argv)
int argc;
char *argv[];
{
if (argc < 2) {
fprintf(stderr, "usage: ifconfig interface %s %s %s\n",
"[ address ] [ up ] [ down ]",
"[ trailers | -trailers ]",
"[ arp | -arp ]");
exit(1);
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("ifconfig: socket");
exit(1);
}
argc--, argv++;
strcpy(name, *argv);
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
Perror("ioctl (SIOCGIFFLAGS)");
exit(1);
}
flags = ifr.ifr_flags;
argc--, argv++;
if (argc == 0) {
status();
exit(0);
}
while (argc > 0) {
register struct cmd *p;
for (p = cmds; p->c_name; p++)
if (strcmp(*argv, p->c_name) == 0)
break;
if (p->c_func)
(*p->c_func)(*argv, p->c_parameter);
argc--, argv++;
}
exit(0);
}
/*ARGSUSED*/
setifaddr(addr, param)
char *addr;
int param;
{
getaddr(addr, (struct sockaddr_in *)&ifr.ifr_addr);
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
Perror("ioctl (SIOCSIFADDR)");
}
setifflags(vname, value)
char *vname;
int value;
{
if (value < 0) {
value = -value;
ifr.ifr_flags = (flags &~ value);
} else
ifr.ifr_flags |= value;
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
Perror(vname);
}
status()
{
struct sockaddr_in *sin;
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0)
Perror("ioctl (SIOCGIFADDR)");
sin = (struct sockaddr_in *)&ifr.ifr_addr;
printf("%s: %s ", name, inet_ntoa(sin->sin_addr));
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING"
printb("flags", flags, IFFBITS); putchar('\n');
}
Perror(cmd)
char *cmd;
{
extern int errno;
fprintf(stderr, "ifconfig: ");
switch (errno) {
case ENXIO:
fprintf(stderr, "%s: ", cmd);
fprintf(stderr, "no such interface\n");
break;
case EPERM:
fprintf(stderr, "%s: permission denied\n");
break;
default:
perror(cmd);
}
exit(1);
}
struct in_addr inet_makeaddr();
getaddr(s, sin)
char *s;
struct sockaddr_in *sin;
{
struct hostent *hp;
struct netent *np;
int val;
hp = gethostbyname(s);
if (hp) {
sin->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
return;
}
np = getnetbyname(s);
if (np) {
sin->sin_family = np->n_addrtype;
sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
return;
}
sin->sin_family = AF_INET;
val = inet_addr(s);
if (val != -1) {
sin->sin_addr.s_addr = val;
return;
}
val = inet_network(s);
if (val != -1) {
sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
return;
}
fprintf(stderr, "%s: bad value\n", s);
exit(1);
}
/*
* Print a value a la the %b format of the kernel's printf
*/
printb(s, v, bits)
char *s;
register char *bits;
register unsigned short v;
{
register int i, any = 0;
register char c;
if (bits && *bits == 8)
printf("%s=%o", s, v);
else
printf("%s=%x", s, v);
bits++;
if (bits) {
putchar('<');
while (i = *bits++) {
if (v & (1 << (i-1))) {
if (any)
putchar(',');
any = 1;
for (; (c = *bits) > 32; bits++)
putchar(c);
} else
for (; *bits > 32; bits++)
;
}
putchar('>');
}
}