File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / etc / ifconfig.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:27 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
Power 6/32 Unix version 1.21

#ifndef lint
static char sccsid[] = "@(#)ifconfig.c	4.5 (Berkeley) 11/2/83";
#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>
#include <strings.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 },
};

char	*malloc();
/*--------------------------------------------------------
  Changes:

	. reget the interface flag before setting it (in case
	  ioctl(SIOCSIFADDR) has already changed the flag.

	. add the interface to set the Ethernet station address.
	  If the interface address is not recognized symbolically
	  and it is not Internet numeric address and its
	  syntax is "Ex.x.x.x.x.x", then the address is Ethernet
	  station address. Also enhance the parsing of Ethernet address.

	. fix the format error in Perror().
	  
--------------------------------------------------------*/
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;
{
	register long val;

	val = getaddr(addr, (struct sockaddr_in *)&ifr.ifr_addr);
	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
	if (val != 2) { 
		if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
			Perror("ioctl (SIOCSIFADDR)");
		}
	    else {	/* Set Ethernet station address */
		if (ioctl(s, SIOCSETETADDR, (caddr_t)&ifr) < 0)
			Perror("ioctl (SIOCSETADDR)");
		}
}

setifflags(vname, value)
	char *vname;
	int value;
{
	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
		Perror("ioctl (SIOCGIFFLAGS)");
		exit(1);
	}
	flags = ifr.ifr_flags;

	if (value < 0) {
		value = -value;
		flags &= ~value;
	} else
		flags |= value;
	ifr.ifr_flags = flags;
	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\10NOARP"
	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", cmd);
		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;
	char *s1;
	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(1);
	}
	np = getnetbyname(s);
	if (np) {
		sin->sin_family = np->n_addrtype;
		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
		return(1);
	}
	sin->sin_family = AF_INET;
	val = inet_addr(s);
	if (val != -1) {
		sin->sin_addr.s_addr = val;
		return(1);
	}
	val = inet_network(s);
	if (val != -1) {
		sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
		return(1);
	}
	if ((s[0] == 'E') && (index(s,'.'))) { 
		char *nxtc;
		long lno, ix;

		/* Get Ethernet station address */
		s1 = malloc((unsigned)(strlen(s)+1));
		if (!s1) {
			fprintf(stderr,"%s: Ethernet address too long\n",s);
			exit(1);
		}
		strcpy(s1,s);	/* save original address for error message */

		/* Transform Ea.b.c.d.e.f to a.b.c.d.e.f. for ease of
		   parsing 
		*/
		strncpy(s,s+1,strlen(s)-1);
		s[strlen(s)-1]='.';
		for (ix=2; ix<8; ix++) {
			char	*t;

			nxtc = index(s,'.');
			if (!nxtc || nxtc==s) {
				fprintf(stderr,"%s: bad Ethernet address\n",s1);
				exit(1);
			}

			*nxtc++ = NULL;
			for (t=s;*t && t<nxtc; t++) {
			  if ( !(*t>='0' && *t<='9') &&
			       !(*t>='a' && *t<='f') &&
			       !(*t>='A' && *t<='F')) {
				fprintf(stderr,
				   "%s: bad1 Ethernet address\n",s1);
				exit(1);
			  }
			}
			sscanf(s,"%x",&lno);
			sin->sin_zero[ix]=(char)(~(lno & 0xff));
			s = nxtc;
		}
		if (*s) {
			fprintf(stderr,"%s: Ethernet address too long\n",s1);
			exit(1);
		}
#ifdef DEBUG
		printf("\nEthernet station address : ");
		printf("%x.%x.%x.%x.%x.%x\n",sin->sin_zero[2]&0xff,
			sin->sin_zero[3]&0xff,sin->sin_zero[4]&0xff,
			sin->sin_zero[5]&0xff,
			sin->sin_zero[6]&0xff,sin->sin_zero[7]&0xff);
#endif DEBUG
		return(2);
	}
	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('>');
	}
}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.