⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipconfig.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	} else {		conf.hwatype = -1;		snprint((char*)conf.cid, sizeof(conf.cid), "plan9_%ld.%d", lrand(), getpid());		conf.cidlen = strlen((char*)conf.cid);	}}// bind ip into the namespacevoidlookforip(char *net){	char proto[64];	snprint(proto, sizeof(proto), "%s/ipifc", net);	if(access(proto, 0) == 0)		return;	sysfatal("no ip stack bound onto %s", net);}// send some ctls to a devicevoidcontroldevice(void){	char ctlfile[256];	int fd;	Ctl *cp;	if(firstctl == nil)		return;	if(strcmp(conf.type, "ether") == 0)		snprint(ctlfile, sizeof(ctlfile), "%s/clone", conf.dev);	else		return;	fd = open(ctlfile, ORDWR);	if(fd < 0)		sysfatal("can't open %s", ctlfile);	for(cp = firstctl; cp != nil; cp = cp->next){		if(write(fd, cp->ctl, strlen(cp->ctl)) < 0)			sysfatal("ctl message %s: %r", cp->ctl);		seek(fd, 0, 0);	}}// bind an ip stack to a device, leave the control channel openvoidbinddevice(void){	char buf[256];	if(myifc < 0){		// get a new ip interface		snprint(buf, sizeof(buf), "%s/ipifc/clone", conf.mpoint);		conf.cfd = open(buf, ORDWR);		if(conf.cfd < 0)			sysfatal("opening %s/ipifc/clone: %r", conf.mpoint);		// specify the medium as an ethernet, and bind the interface to it		if(fprint(conf.cfd, "bind %s %s", conf.type, conf.dev) < 0)			sysfatal("binding device: %r");	} else {		// open the old interface		snprint(buf, sizeof(buf), "%s/ipifc/%d/ctl", conf.mpoint, myifc);		conf.cfd = open(buf, ORDWR);		if(conf.cfd < 0)			sysfatal("opening %s/ipifc/%d/ctl: %r", conf.mpoint, myifc);	}}// add a logical interface to the ip stackintipconfig(void){	char buf[256];	int n;	if(!validip(conf.laddr))		return -1;	n = sprint(buf, "add");	n += snprint(buf+n, sizeof(buf)-n, " %I", conf.laddr);	if(!validip(conf.mask))		ipmove(conf.mask, defmask(conf.laddr));	n += snprint(buf+n, sizeof(buf)-n, " %I", conf.mask);	if(validip(conf.raddr)){		n += snprint(buf+n, sizeof(buf)-n, " %I", conf.raddr);		if(conf.mtu != 0)			n += snprint(buf+n, sizeof(buf)-n, " %d", conf.mtu);	}	if(write(conf.cfd, buf, n) < 0){		fprint(2, "ipconfig: write(%s): %r\n", buf);		return -1;	}	if(beprimary==1 && validip(conf.gaddr))		adddefroute(conf.mpoint, conf.gaddr);	return 0;}// remove a logical interface to the ip stackvoidipunconfig(void){	char buf[256];	int n;	if(!validip(conf.laddr))		return;	DEBUG("couldn't renew IP lease, releasing %I\n", conf.laddr);	n = sprint(buf, "remove");	n += snprint(buf+n, sizeof(buf)-n, " %I", conf.laddr);	if(!validip(conf.mask))		ipmove(conf.mask, defmask(conf.laddr));	n += snprint(buf+n, sizeof(buf)-n, " %I", conf.mask);	write(conf.cfd, buf, n);	ipmove(conf.laddr, IPnoaddr);	ipmove(conf.raddr, IPnoaddr);	ipmove(conf.mask, IPnoaddr);	// forget configuration info	if(beprimary==1)		writendb("", 0, 0);}voidding(void*, char *msg){	if(strstr(msg, "alarm"))		noted(NCONT);	noted(NDFLT);}voiddhcpquery(int needconfig, int startstate){	if(needconfig)		fprint(conf.cfd, "add %I %I", IPnoaddr, IPnoaddr);	conf.fd = openlisten();	if(conf.fd < 0){		conf.state = Sinit;		return;	}	notify(ding);	// try dhcp for 10 seconds	conf.xid = lrand();	conf.starttime = time(0);	conf.state = startstate;	switch(startstate){	case Sselecting:		conf.offered = 0;		dhcpsend(Discover);		break;	case Srenewing:		dhcpsend(Request);		break;	default:		sysfatal("internal error 0");	}	conf.resend = 0;	conf.timeout = time(0) + 4;	while(conf.state != Sbound){		dhcprecv();		if(dhcptimer() < 0)			break;		if(time(0) - conf.starttime > 10)			break;	}	close(conf.fd);	if(needconfig)		fprint(conf.cfd, "remove %I %I", IPnoaddr, IPnoaddr);}#define HOUR (60*60)voiddhcpwatch(int needconfig){	int secs, s;	ulong t;	if(nodhcpwatch)		return;	switch(rfork(RFPROC|RFFDG|RFNOWAIT|RFNOTEG)){	default:		return;	case 0:		break;	}	// keep trying to renew the lease	for(;;){		if(conf.lease == 0)			secs = 5;		else			secs = conf.lease>>1;		// avoid overflows		for(s = secs; s > 0; s -= t){			if(s > HOUR)				t = HOUR;			else				t = s;			sleep(t*1000);		}		if(conf.lease > 0){			// during boot, the starttime can be bogus so avoid			// spurious ipinconfig's			t = time(0) - conf.starttime;			if(t > (3*secs)/2)				t = secs;			if(t >= conf.lease){				conf.lease = 0;				if(!noconfig){					ipunconfig();					needconfig = 1;				}			} else				conf.lease -= t;		}		dhcpquery(needconfig, needconfig ? Sselecting : Srenewing);		if(needconfig && conf.state == Sbound){			if(ipconfig() < 0)				sysfatal("can't start ip: %r");			needconfig = 0;			// leave everything we've learned somewhere other procs can find it			if(beprimary==1){				putndb();				tweakservers();			}		}	}}intdhcptimer(void){	ulong now;	now = time(0);	if(now < conf.timeout)		return 0;	switch(conf.state) {	default:		sysfatal("dhcptimer: unknown state %d", conf.state);	case Sinit:		break;	case Sselecting:		dhcpsend(Discover);		conf.timeout = now + 4;		conf.resend++;		if(conf.resend>5)			goto err;		break;	case Srequesting:		dhcpsend(Request);		conf.timeout = now + 4;		conf.resend++;		if(conf.resend>5)			goto err;		break;	case Srenewing:		dhcpsend(Request);		conf.timeout = now + 1;		conf.resend++;		if(conf.resend>3) {			conf.state = Srebinding;			conf.resend = 0;		}		break;	case Srebinding:		dhcpsend(Request);		conf.timeout = now + 4;		conf.resend++;		if(conf.resend>5)			goto err;		break;	case Sbound:		break;	}	return 0;err:	conf.state = Sinit;	return -1;}voiddhcpsend(int type){	Bootp bp;	uchar *p;	int n;	uchar vendor[64];	OUdphdr *up = (OUdphdr*)bp.udphdr;	memset(&bp, 0, sizeof(bp));	hnputs(up->rport, 67);	bp.op = Bootrequest;	hnputl(bp.xid, conf.xid);	hnputs(bp.secs, time(0)-conf.starttime);	hnputs(bp.flags, 0);	memmove(bp.optmagic, optmagic, 4);	if(conf.hwatype >= 0 && conf.hwalen < sizeof(bp.chaddr)){		memmove(bp.chaddr, conf.hwa, conf.hwalen);		bp.hlen = conf.hwalen;		bp.htype = conf.hwatype;	}	p = bp.optdata;	p = optaddbyte(p, ODtype, type);	p = optadd(p, ODclientid, conf.cid, conf.cidlen);	switch(type) {	default:		sysfatal("dhcpsend: unknown message type: %d", type);	case Discover:		ipmove(up->raddr, IPv4bcast);	// broadcast		if(*conf.hostname && sendhostname)			p = optaddstr(p, OBhostname, conf.hostname);		if(plan9){			n = snprint((char*)vendor, sizeof(vendor), "plan9_%s", conf.cputype);			p = optaddvec(p, ODvendorclass, vendor, n);		}		p = optaddvec(p, ODparams, requested, nrequested);		if(validip(conf.laddr))			p = optaddaddr(p, ODipaddr, conf.laddr);		break;	case Request:		switch(conf.state){		case Srenewing:			ipmove(up->raddr, conf.server);			v6tov4(bp.ciaddr, conf.laddr);			break;		case Srebinding:			ipmove(up->raddr, IPv4bcast);	// broadcast			v6tov4(bp.ciaddr, conf.laddr);			break;		case Srequesting:			ipmove(up->raddr, IPv4bcast);	// broadcast			p = optaddaddr(p, ODipaddr, conf.laddr);			p = optaddaddr(p, ODserverid, conf.server);			break;		}		p = optaddulong(p, ODlease, conf.offered);		if(plan9){			n = snprint((char*)vendor, sizeof(vendor), "plan9_%s", conf.cputype);			p = optaddvec(p, ODvendorclass, vendor, n);		}		p = optaddvec(p, ODparams, requested, nrequested);		if(*conf.hostname && sendhostname)			p = optaddstr(p, OBhostname, conf.hostname);		break;		case Release:		ipmove(up->raddr, conf.server);		v6tov4(bp.ciaddr, conf.laddr);		p = optaddaddr(p, ODipaddr, conf.laddr);		p = optaddaddr(p, ODserverid, conf.server);		break;	}	*p++ = OBend;	n = p - (uchar*)&bp;	USED(n);	/*	 *  We use a maximum size DHCP packet to survive the	 *  All_Aboard NAT package from Internet Share.  It	 *  always replies to DHCP requests with a packet of the	 *  same size, so if the request is too short the reply	 *  is truncated.	 */	if(write(conf.fd, &bp, sizeof(bp)) != sizeof(bp))		fprint(2, "dhcpsend: write failed: %r\n");}voiddhcprecv(void){	uchar buf[8000];	Bootp *bp;	int i, n, type;	ulong lease;	char err[ERRMAX];	uchar vopts[256];	alarm(1000);	n = read(conf.fd, buf, sizeof(buf));	alarm(0);	if(n < 0){		errstr(err, sizeof err);		if(strstr(err, "interrupt") == nil)			fprint(2, "ipconfig: bad read: %s\n", err);		else			DEBUG("read timed out\n");		return;	}	bp = parsebootp(buf, n);	if(bp == 0) {		DEBUG("parsebootp failed: dropping packet\n");		return;	}	type = optgetbyte(bp->optdata, ODtype);	switch(type) {	default:		fprint(2, "%s: unknown type: %d\n", argv0, type);		break;	case Offer:		DEBUG("got offer from %V ", bp->siaddr);		if(conf.state != Sselecting){			DEBUG("\n");			break;		}		lease = optgetulong(bp->optdata, ODlease);		if(lease == 0){			/*			 *  The All_Aboard NAT package from Internet Share doesn't			 *  give a lease time, so we have to assume one.			 */			fprint(2, "%s: Offer with %lud lease, using %d\n", argv0, lease, MinLease);			lease = MinLease;		}		DEBUG("lease=%lud ", lease);		if(!optgetaddr(bp->optdata, ODserverid, conf.server)) {			fprint(2, "%s: Offer from server with invalid serverid\n", argv0);			break;		}		v4tov6(conf.laddr, bp->yiaddr);		memmove(conf.sname, bp->sname, sizeof(conf.sname));		conf.sname[sizeof(conf.sname)-1] = 0;		DEBUG("server=%I sname=%s\n", conf.server, conf.sname);		conf.offered = lease;		conf.state = Srequesting;		dhcpsend(Request);		conf.resend = 0;		conf.timeout = time(0) + 4;		break;	case Ack:		DEBUG("got ack from %V ", bp->siaddr);		if(conf.state != Srequesting)		if(conf.state != Srenewing)		if(conf.state != Srebinding)			break;		// ignore a bad lease		lease = optgetulong(bp->optdata, ODlease);		if(lease == 0){			/*			 *  The All_Aboard NAT package from Internet Share doesn't			 *  give a lease time, so we have to assume one.			 */			fprint(2, "%s: Ack with %lud lease, using %d\n", argv0, lease, MinLease);			lease = MinLease;		}		DEBUG("lease=%lud ", lease);		// address and mask		if(!validip(conf.laddr) || !Oflag)			v4tov6(conf.laddr, bp->yiaddr);		if(!validip(conf.mask) || !Oflag){			if(!optgetaddr(bp->optdata, OBmask, conf.mask))				ipmove(conf.mask, IPnoaddr);		}		DEBUG("ipaddr=%I ipmask=%M ", conf.laddr, conf.mask);		// get a router address either from the router option		// or from the router that forwarded the dhcp packet		if(!validip(conf.gaddr) || !Oflag){			if(optgetaddr(bp->optdata, OBrouter, conf.gaddr)){				DEBUG("ipgw=%I ", conf.gaddr);			} else {				if(memcmp(bp->giaddr, IPnoaddr+IPv4off, IPv4addrlen) != 0){					v4tov6(conf.gaddr, bp->giaddr);					DEBUG("giaddr=%I ", conf.gaddr);				}			}		}		else			DEBUG("ipgw=%I ", conf.gaddr);		// get dns servers		memset(conf.dns, 0, sizeof(conf.dns));		n = optgetaddrs(bp->optdata, OBdnserver, conf.dns,				sizeof(conf.dns)/IPaddrlen);		for(i = 0; i < n; i++)			DEBUG("dns=%I ", conf.dns+i*IPaddrlen);		// get ntp servers		memset(conf.ntp, 0, sizeof(conf.ntp));		n = optgetaddrs(bp->optdata, OBntpserver, conf.ntp,				sizeof(conf.ntp)/IPaddrlen);		for(i = 0; i < n; i++)			DEBUG("ntp=%I ", conf.ntp+i*IPaddrlen);		// get names		optgetstr(bp->optdata, OBhostname, conf.hostname, sizeof(conf.hostname));		optgetstr(bp->optdata, OBdomainname, conf.domainname, sizeof(conf.domainname));		// get anything else we asked for		getoptions(bp->optdata);		// get plan9 specific options		n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof(vopts)-1);		if(n > 0 && parseoptions(vopts, n) == 0){			if(validip(conf.fs) && Oflag)				n = 1;			else				n = optgetaddrs(vopts, OP9fs, conf.fs, 2);			for(i = 0; i < n; i++)				DEBUG("fs=%I ", conf.fs+i*IPaddrlen);			if(validip(conf.auth) && Oflag)				n = 1;			else				n = optgetaddrs(vopts, OP9auth, conf.auth, 2);			for(i = 0; i < n; i++)				DEBUG("auth=%I ", conf.auth+i*IPaddrlen);		}		conf.lease = lease;		conf.state = Sbound;		DEBUG("server=%I sname=%s\n", conf.server, conf.sname);		break;	case Nak:		conf.state = Sinit;		fprint(2, "%s: recved dhcpnak on %s\n", argv0, conf.mpoint);		break;	}}intopenlisten(){	int fd, cfd;	char data[128];	char devdir[40];	int n;	if(validip(conf.laddr)	&& (conf.state == Srenewing || conf.state == Srebinding))		sprint(data, "%s/udp!%I!68", conf.mpoint, conf.laddr);	else		sprint(data, "%s/udp!*!68", conf.mpoint);	for(n=0;;n++) {		cfd = announce(data, devdir);		if(cfd >= 0)			break;		if(!noconfig)			sysfatal("can't announce for dhcp: %r");		// might be another client - wait and try again		fprint(2, "%s: can't announce: %r\n", argv0);		sleep((nrand(10)+1)*1000);		if(n > 10)			return -1;	}	if(fprint(cfd, "headers") < 0)		sysfatal("can't set header mode: %r");	fprint(cfd, "oldheaders");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -