1297 lines · 25.0 KB · C
RawDownload
/* * ipconfig - configure parameters of an ip stack */#include <u.h>#include <libc.h>#include <bio.h>#include <ip.h>#include <ndb.h>#include "ipconfig.h"#include "../dhcp.h" #include <libsec.h> /* genrandom() */ Conf	conf;Ipifc*	myifc;int	beprimary = -1;int	noconfig;Ctl	*firstctl, **ctll = &firstctl; int	debug;int	dolog; int	plan9 = 1;int	Oflag;int	rflag;int	tflag;int	yflag; int	dodhcp;int	nodhcpwatch;int	sendhostname;char	*ndboptions;char	*ipnet; int	ipv6auto;int	dupl_disc = 1;		/* flag: V6 duplicate neighbor discovery */ int	dondbconfig;char	*dbfile; static char logfile[] = "ipconfig"; static void	openiproute(void);static void	binddevice(void);static void	controldevice(void);extern void	pppbinddev(void); static void	doadd(void);static void	dodel(void);static void	dounbind(void);static void	ndbconfig(void); static int	Ufmt(Fmt*);#pragma varargck type "U" char* voidusage(void){	fprint(2, "usage: %s [-6dDGnNOpPrtuXy][-b baud][-c ctl]* [-U duid] [-g gw]"		"[-h host][-i ipnet][-m mtu][-s dns]...\n"		"\t[-f dbfile][-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask "		"[raddr [fs [auth]]]]]\n", argv0);	exits("usage");} static voidinit(void){	srand(truerand()); 	fmtinstall('H', encodefmt);	fmtinstall('E', eipfmt);	fmtinstall('I', eipfmt);	fmtinstall('M', eipfmt);	fmtinstall('V', eipfmt);	fmtinstall('U', Ufmt);	fmtinstall('$', ndbvalfmt); 	nsec();			/* make sure time file is open before forking */ 	conf.cfd = -1;	conf.rfd = -1; 	setnetmtpt(conf.mpoint, sizeof conf.mpoint, nil);	conf.cputype = getenv("cputype");	if(conf.cputype == nil)		conf.cputype = "386"; 	v6paraminit(&conf); 	dhcpinit();} voidwarning(char *fmt, ...){	char buf[1024];	va_list arg; 	va_start(arg, fmt);	vseprint(buf, buf + sizeof buf, fmt, arg);	va_end(arg);	if (dolog)		syslog(0, logfile, "%s", buf);	else		fprint(2, "%s: %s\n", argv0, buf);} static voidparsenorm(int argc, char **argv){	switch(argc){	case 5:		 if (parseip(conf.auth, argv[4]) == -1)			usage();		/* fall through */	case 4:		 if (parseip(conf.fs, argv[3]) == -1)			usage();		/* fall through */	case 3:		 if (parseip(conf.raddr, argv[2]) == -1)			usage();		/* fall through */	case 2:		if (strcmp(argv[1], "0") != 0){			if (parseipandmask(conf.laddr, conf.mask, argv[0], argv[1]) == -1)				usage();			break;		}		/* fall through */	case 1:		 if (parseip(conf.laddr, argv[0]) == -1)			usage();		/* fall through */	case 0:		break;	default:		usage();	}} static char*finddev(char *dir, char *name, char *dev){	int fd, i, nd;	Dir *d; 	fd = open(dir, OREAD);	if(fd >= 0){		d = nil;		nd = dirreadall(fd, &d);		close(fd);		for(i=0; i<nd; i++){			if(strncmp(d[i].name, name, strlen(name)))				continue;			if(strstr(d[i].name, "ctl") != nil)				continue;	/* ignore ctl files */			dev = smprint("%s/%s", dir, d[i].name);			break;		}		free(d);	}	return dev;} /* look for an action */static intparseverb(char *name){	static char *verbs[] = {		[Vadd]		"add",		[Vdel]		"del",		[Vunbind]	"unbind",		[Vether]	"ether",		[Vgbe]		"gbe",		[Vppp]		"ppp",		[Vloopback]	"loopback",		[Vaddpref6]	"add6",		[Vra6]		"ra6",		[Vtorus]	"torus",		[Vtree]		"tree",		[Vpkt]		"pkt",		[Vnull]		"null",	};	int i; 	for(i = 0; i < nelem(verbs); i++)		if(verbs[i] != nil && strcmp(name, verbs[i]) == 0)			return i; 	if(strcmp(name, "remove")==0)		return Vdel; 	return -1;} static intparseargs(int argc, char **argv){	char *p;	int action, verb; 	/* default to any host name we already have */	if(*conf.hostname == 0){		p = getenv("sysname");		if(p == nil || *p == 0)			p = sysname();		if(p != nil)			utf2idn(p, conf.hostname, sizeof(conf.hostname));	} 	/* defaults */	conf.type = "ether";	conf.dev = nil;	action = Vadd; 	/* get optional medium and device */	if (argc > 0){		verb = parseverb(*argv);		switch(verb){		case Vether:		case Vgbe:		case Vloopback:		case Vpkt:		case Vppp:		case Vtorus:		case Vtree:		case Vnull:			conf.type = *argv++;			argc--;			if(argc > 0){				conf.dev = *argv++;				argc--;			} else if(verb == Vppp)				conf.dev = finddev("/dev", "eia", "/dev/eia0");			break;		}	}	if(conf.dev == nil){		if(!isether())			sysfatal("no device specified for medium %s", conf.type);		conf.dev = finddev(conf.mpoint, "ether", "/net/ether0");	} 	/* get optional verb */	if (argc > 0){		verb = parseverb(*argv);		switch(verb){		case Vether:		case Vgbe:		case Vppp:		case Vloopback:		case Vtorus:		case Vtree:		case Vpkt:		case Vnull:			sysfatal("medium %s already specified", conf.type);		case Vadd:		case Vdel:		case Vunbind:		case Vaddpref6:		case Vra6:			argv++;			argc--;			action = verb;			break;		}	} 	/* get verb-dependent arguments */	switch (action) {	case Vadd:	case Vdel:	case Vunbind:		parsenorm(argc, argv);		break;	case Vaddpref6:		parse6pref(argc, argv);		break;	case Vra6:		parse6ra(argc, argv);		break;	}	return action;} /* all interfaces on conf.mpoint stack */static Ipifc *allifcs; static Ipifc*findmyifc(void){	Ipifc *nifc; 	allifcs = readipifc(conf.mpoint, allifcs, -1);	for(nifc = allifcs; nifc != nil; nifc = nifc->next){		if(strcmp(nifc->dev, conf.dev) == 0){			myifc = readipifc(conf.mpoint, myifc, nifc->index);			return myifc;		}	}	return nil;} intmyip(Ipifc *ifc, uchar *ip){	for(; ifc != nil; ifc = ifc->next) {		if(iplocalonifc(ifc, ip) != nil)			return 1;	}	return 0;} intisether(void){	switch(parseverb(conf.type)){	case Vether:	case Vgbe:		return 1;	}	return 0;} /* create a client id */static voidmkclientid(void){	if(isether() && myetheraddr(conf.hwa, conf.dev) == 0){		conf.hwalen = 6;		conf.hwatype = 1;		conf.cid[0] = conf.hwatype;		memmove(&conf.cid[1], conf.hwa, conf.hwalen);		conf.cidlen = conf.hwalen+1;		if(conf.duidlen == 0){			/* DUID-LL */			conf.duid[0] = 0x00;			conf.duid[1] = 0x03;			conf.duid[2] = conf.hwatype >> 8;			conf.duid[3] = conf.hwatype;			memmove(conf.duid+4, conf.hwa, conf.hwalen);			conf.duidlen = conf.hwalen+4;		}	} else {		conf.hwatype = -1;		snprint((char*)conf.cid, sizeof conf.cid,			"plan9_%ld.%d", lrand(), getpid());		conf.cidlen = strlen((char*)conf.cid);		genrandom(conf.hwa, sizeof(conf.hwa));	}	ea2lla(conf.lladdr, conf.hwa);} voidmain(int argc, char **argv){	uchar ip[IPaddrlen];	int action;	Ctl *cp;	char *s; 	init();	ARGBEGIN {	case '6': 			/* IPv6 auto config */		ipv6auto = 1;		break;	case 'b':		conf.baud = EARGF(usage());		break;	case 'c':		cp = malloc(sizeof *cp);		if(cp == nil)			sysfatal("%r");		*ctll = cp;		ctll = &cp->next;		cp->next = nil;		cp->ctl = EARGF(usage());		break;	case 'd':		dodhcp = 1;		break;	case 'D':		debug = 1;		break;	case 'f':		dbfile = EARGF(usage());		break;	case 'g':		if (parseip(conf.gaddr, EARGF(usage())) == -1)			usage();		break;	case 'G':		plan9 = 0;		break;	case 'h':		if(utf2idn(EARGF(usage()), conf.hostname, sizeof(conf.hostname)) <= 0)			sysfatal("bad hostname");		sendhostname = 1;		break;	case 'i':		ipnet = EARGF(usage());		break;	case 'm':		conf.mtu = atoi(EARGF(usage()));		break;	case 'n':		noconfig = 1;		break;	case 'N':		dondbconfig = 1;		break;	case 'o':		if(addoption(EARGF(usage())) < 0)			usage();		break;	case 'O':		Oflag = 1;		break;	case 'p':		beprimary = 1;		break;	case 'P':		beprimary = 0;		break;	case 'r':		rflag = 1;		break;	case 's':		if(parseip(ip, EARGF(usage())) == -1)			usage();		addaddrs(conf.dns, sizeof(conf.dns), ip, sizeof(ip));		break;	case 't':		tflag = 1;		break;	case 'u':		/* IPv6: duplicate neighbour disc. off */		dupl_disc = 0;		break;	case 'U':		/* device unique id used for dhcpv6 */		s = EARGF(usage());		conf.duidlen = dec16(conf.duid, sizeof(conf.duid), s, strlen(s));		if(conf.duidlen <= 0)			usage();		break;	case 'x':		setnetmtpt(conf.mpoint, sizeof conf.mpoint, EARGF(usage()));		break;	case 'X':		nodhcpwatch = 1;		break;	case 'y':		yflag = 1;		break;	default:		usage();	} ARGEND; 	action = parseargs(argc, argv); 	if(beprimary == -1 && (ipv6auto || ISIPV6LINKLOCAL(conf.laddr) || parseverb(conf.type) == Vloopback))		beprimary = 0; 	openiproute();	if(findmyifc() == nil) {		switch(action){		default:			if(noconfig)				break;			/* bind new interface */			controldevice();			binddevice();			findmyifc();		case Vunbind:			break;		case Vdel:			/*			 * interface gone, just remove			 * default route and ndb entries.			 */			dodel();			exits(nil);		}		if(myifc == nil)			sysfatal("interface not found for: %s", conf.dev);	} else if(!noconfig) {		/* open old interface */		binddevice();	} 	switch(action){	case Vadd:		mkclientid();		if(dondbconfig){			dodhcp = 0;			beprimary = 0;			ndbconfig();			break;		}

Lines 1–500 of 1297.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t