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

📄 dhcpd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* check for hard assignment */		if(rp->staticbinding){			if(memcmp(rp->ip, rp->ii.ipaddr, IPaddrlen) != 0){				warning(0, "!Request(%s via %I): %I not valid for %E",					rp->id, rp->gii.ipaddr, rp->ip, rp->bp->chaddr);				sendnak(rp, "not valid");			}			sendack(rp, rp->ii.ipaddr, (StaticLease > minlease ? StaticLease : minlease), 1);			return;		}		/* make sure the network makes sense */		if(!samenet(rp->ip, &rp->gii)){			warning(0, "!Request(%s via %I): bad forward of %I",				rp->id, rp->gii.ipaddr, rp->ip);			sendnak(rp, "wrong network");			return;		}		b = iptobinding(rp->ip, 0);		if(b == nil){			warning(0, "!Request(%s via %I): no binding for %I for",				rp->id, rp->gii.ipaddr, rp->ip);			return;		}		if(memcmp(rp->ip, b->ip, IPaddrlen) != 0 || now > b->lease){			warning(0, "!Request(%s via %I): %I not valid",				rp->id, rp->gii.ipaddr, rp->ip);			sendnak(rp, "not valid");			return;		}		b->offer = b->lease - now;		sendack(rp, b->ip, b->offer, 1);	} else if(validip(rp->ciaddr)){		/*		 *  checking address - RENEWING or REBINDING		 *		 *  these states are indistinguishable in our action.  The only		 *  difference is how close to lease expiration the client is.		 *  If it is really close, it broadcasts the request hoping that		 *  some server will answer.		 */		/* check for hard assignment */		if(rp->staticbinding){			if(ipcmp(rp->ciaddr, rp->ii.ipaddr) != 0){				warning(0, "!Request(%s via %I): %I not valid",					rp->id, rp->gii.ipaddr, rp->ciaddr);				sendnak(rp, "not valid");			}			sendack(rp, rp->ii.ipaddr, (StaticLease > minlease ? StaticLease : minlease), 1);			return;		}		/* make sure the network makes sense */		if(!samenet(rp->ciaddr, &rp->gii)){			warning(0, "!Request(%s via %I): bad forward of %I",				rp->id, rp->gii.ipaddr, rp->ip);			sendnak(rp, "wrong network");			return;		}		b = iptobinding(rp->ciaddr, 0);		if(b == nil){			warning(0, "!Request(%s via %I): no binding for %I",				rp->id, rp->gii.ipaddr, rp->ciaddr);			return;		}		if(ipcmp(rp->ciaddr, b->ip) != 0){			warning(0, "!Request(%I via %s): %I not valid",				rp->id, rp->gii.ipaddr, rp->ciaddr);			sendnak(rp, "invalid ip address");			return;		}		mkoffer(b, rp->id, rp->leasetime);		if(commitbinding(b) < 0){			warning(0, "!Request(%s via %I): can't commit %I",				rp->id, rp->gii.ipaddr, b->ip);			sendnak(rp, "can't commit binding");			return;		}		sendack(rp, b->ip, b->offer, 1);	}}voidrcvdecline(Req *rp){	Binding *b;	char buf[64];	if(rp->staticbinding)		return;	b = idtooffer(rp->id, &rp->gii);	if(b == nil){		warning(0, "!Decline(%s via %I): no binding",			rp->id, rp->gii.ipaddr);		return;	}	/* mark ip address as in use */	snprint(buf, sizeof(buf), "declined by %s", rp->id);	mkoffer(b, buf, 0x7fffffff);	commitbinding(b);}voidrcvrelease(Req *rp){	Binding *b;	if(rp->staticbinding)		return;	b = idtobinding(rp->id, &rp->gii, 0);	if(b == nil){		warning(0, "!Release(%s via %I): no binding",			rp->id, rp->gii.ipaddr);		return;	}	if(strcmp(rp->id, b->boundto) != 0){		warning(0, "!Release(%s via %I): invalid release of %I",			rp->id, rp->gii.ipaddr, rp->ip);		return;	}	warning(0, "Release(%s via %I): releasing %I", b->boundto, rp->gii.ipaddr, b->ip);	if(releasebinding(b, rp->id) < 0)		warning(0, "release: couldn't release");}voidrcvinform(Req *rp){	Binding *b;	if(rp->staticbinding){		sendack(rp, rp->ii.ipaddr, 0, 0);		return;	}	b = iptobinding(rp->ciaddr, 0);	if(b == nil){		warning(0, "!Inform(%s via %I): no binding for %I",			rp->id, rp->gii.ipaddr, rp->ip);		return;	}	sendack(rp, b->ip, 0, 0);}intsetsiaddr(uchar *siaddr, uchar *saddr, uchar *laddr){	if(ipcmp(saddr, IPnoaddr) != 0){		v6tov4(siaddr, saddr);		return 0;	} else {		v6tov4(siaddr, laddr);		return 1;	}}intismuted(Req *rp){	return mute || (mutestat && rp->staticbinding);}voidsendoffer(Req *rp, uchar *ip, int offer){	int n;	ushort flags;	Bootp *bp;	OUdphdr *up;	bp = rp->bp;	up = rp->up;	/*	 *  set destination	 */	flags = nhgets(bp->flags);	if(validip(rp->giaddr)){		ipmove(up->raddr, rp->giaddr);		hnputs(up->rport, 67);	} else if(flags & Fbroadcast){		ipmove(up->raddr, IPv4bcast);		hnputs(up->rport, 68);	} else {		ipmove(up->raddr, ip);		if(bp->htype == 1)			arpenter(up->raddr, bp->chaddr);		hnputs(up->rport, 68);	}	/*	 *  fill in standard bootp part	 */	bp->op = Bootreply;	bp->hops = 0;	hnputs(bp->secs, 0);	memset(bp->ciaddr, 0, sizeof(bp->ciaddr));	v6tov4(bp->giaddr, rp->giaddr);	v6tov4(bp->yiaddr, ip);	setsiaddr(bp->siaddr, rp->ii.tftp, up->laddr);	strncpy(bp->sname, mysysname, sizeof(bp->sname));	strncpy(bp->file, rp->ii.bootf, sizeof(bp->file));	/*	 *  set options	 */	byteopt(rp, ODtype, Offer);	longopt(rp, ODlease, offer);	addropt(rp, ODserverid, up->laddr);	miscoptions(rp, ip);	termopt(rp);	logdhcpout(rp, "Offer");	/*	 *  send	 */	n = rp->p - rp->buf;	if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)		warning(0, "offer: write failed: %r");}voidsendack(Req *rp, uchar *ip, int offer, int sendlease){	int n;	ushort flags;	Bootp *bp;	OUdphdr *up;	bp = rp->bp;	up = rp->up;	/*	 *  set destination	 */	flags = nhgets(bp->flags);	if(validip(rp->giaddr)){		ipmove(up->raddr, rp->giaddr);		hnputs(up->rport, 67);	} else if(flags & Fbroadcast){		ipmove(up->raddr, IPv4bcast);		hnputs(up->rport, 68);	} else {		ipmove(up->raddr, ip);		if(bp->htype == 1)			arpenter(up->raddr, bp->chaddr);		hnputs(up->rport, 68);	}	/*	 *  fill in standard bootp part	 */	bp->op = Bootreply;	bp->hops = 0;	hnputs(bp->secs, 0);	v6tov4(bp->giaddr, rp->giaddr);	v6tov4(bp->yiaddr, ip);	setsiaddr(bp->siaddr, rp->ii.tftp, up->laddr);	strncpy(bp->sname, mysysname, sizeof(bp->sname));	strncpy(bp->file, rp->ii.bootf, sizeof(bp->file));	/*	 *  set options	 */	byteopt(rp, ODtype, Ack);	if(sendlease){		longopt(rp, ODlease, offer);	}	addropt(rp, ODserverid, up->laddr);	miscoptions(rp, ip);	termopt(rp);	logdhcpout(rp, "Ack");	/*	 *  send	 */	n = rp->p - rp->buf;	if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)		warning(0, "ack: write failed: %r");}voidsendnak(Req *rp, char *msg){	int n;	Bootp *bp;	OUdphdr *up;	bp = rp->bp;	up = rp->up;	/*	 *  set destination (always broadcast)	 */	if(validip(rp->giaddr)){		ipmove(up->raddr, rp->giaddr);		hnputs(up->rport, 67);	} else {		ipmove(up->raddr, IPv4bcast);		hnputs(up->rport, 68);	}	/*	 *  fill in standard bootp part	 */	bp->op = Bootreply;	bp->hops = 0;	hnputs(bp->secs, 0);	v6tov4(bp->giaddr, rp->giaddr);	memset(bp->ciaddr, 0, sizeof(bp->ciaddr));	memset(bp->yiaddr, 0, sizeof(bp->yiaddr));	memset(bp->siaddr, 0, sizeof(bp->siaddr));	/*	 *  set options	 */	byteopt(rp, ODtype, Nak);	addropt(rp, ODserverid, up->laddr);	if(msg)		stringopt(rp, ODmessage, msg);	if(strncmp(rp->id, "id", 2) == 0)		hexopt(rp, ODclientid, rp->id+2);	termopt(rp);	logdhcpout(rp, "Nak");	/*	 *  send nak	 */	n = rp->p - rp->buf;	if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)		warning(0, "nak: write failed: %r");}voidbootp(Req *rp){	int n;	Bootp *bp;	OUdphdr *up;	ushort flags;	Iplifc *lifc;	Info *iip;	warning(0, "bootp %s %I->%I from %s via %I, file %s",		rp->genrequest ? "generic" : (rp->p9request ? "p9" : ""),		rp->up->raddr, rp->up->laddr,		rp->id, rp->gii.ipaddr,		rp->bp->file);	if(nobootp)		return;	bp = rp->bp;	up = rp->up;	iip = &rp->ii;	if(rp->staticbinding == 0){		warning(0, "bootp from unknown %s via %I", rp->id, rp->gii.ipaddr);		return;	}	/* ignore if not for us */	if(*bp->sname){		if(strcmp(bp->sname, mysysname) != 0){			bp->sname[20] = 0;			warning(0, "bootp for server %s", bp->sname);			return;		}	} else		slowdelay(rp);	/* ignore if we don't know what file to load */	if(*bp->file == 0){		if(rp->genrequest && *iip->bootf2)	/* if not plan 9 and we have an alternate file... */			strncpy(bp->file, iip->bootf2, sizeof(bp->file));		else if(*iip->bootf)			strncpy(bp->file, iip->bootf, sizeof(bp->file));		else if(*bp->sname)		/* if we were asked, respond no matter what */			bp->file[0] = '\0';		else {			warning(0, "no bootfile for %I", iip->ipaddr);			return;		}	}	/* ignore if the file is unreadable */	if((!rp->genrequest) && bp->file[0] && access(bp->file, 4) < 0){		warning(0, "inaccessible bootfile1 %s", bp->file);		return;	}	bp->op = Bootreply;	v6tov4(bp->yiaddr, iip->ipaddr);	if(rp->p9request){		warning(0, "p9bootp: %I", iip->ipaddr);		memmove(bp->optmagic, plan9opt, 4);		if(iip->gwip == 0)			v4tov6(iip->gwip, bp->giaddr);		rp->p += sprint((char*)rp->p, "%V %I %I %I", iip->ipmask+IPv4off, iip->fsip,				iip->auip, iip->gwip);		sprint(optbuf, "%s", (char*)(bp->optmagic));	} else if(rp->genrequest){		warning(0, "genericbootp: %I", iip->ipaddr);		memmove(bp->optmagic, genericopt, 4);		miscoptions(rp, iip->ipaddr);		termopt(rp);	} else if(iip->vendor[0] != 0) {		warning(0, "bootp vendor field: %s", iip->vendor);		memset(rp->p, 0, 128-4);		rp->p += sprint((char*)bp->optmagic, "%s", iip->vendor);	} else {		memset(rp->p, 0, 128-4);		rp->p += 128-4;	}	/*	 *  set destination	 */	flags = nhgets(bp->flags);	if(validip(rp->giaddr)){		ipmove(up->raddr, rp->giaddr);		hnputs(up->rport, 67);	} else if(flags & Fbroadcast){		ipmove(up->raddr, IPv4bcast);		hnputs(up->rport, 68);	} else {		v4tov6(up->raddr, bp->yiaddr);		if(bp->htype == 1)			arpenter(up->raddr, bp->chaddr);		hnputs(up->rport, 68);	}	/*	 *  select best local address if destination is directly connected	 */	lifc = findlifc(up->raddr);	if(lifc)		ipmove(up->laddr, lifc->ip);	/*	 *  our identity	 */	strncpy(bp->sname, mysysname, sizeof(bp->sname));	/*	 *  set tftp server	 */	setsiaddr(bp->siaddr, iip->tftp, up->laddr);	if(rp->genrequest && *iip->bootf2)		setsiaddr(bp->siaddr, iip->tftp2, up->laddr);	/*	 * RFC 1048 says that we must pad vendor field with	 * zeros until we have a 64 byte field.	 */	n = rp->p - rp->bp->optdata;	if(n < 64-4) {		memset(rp->p, 0, (64-4)-n);		rp->p += (64-4)-n;	}	/*	 *  send	 */	n = rp->p - rp->buf;	if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)		warning(0, "bootp: write failed: %r");	warning(0, "bootp via %I: file %s xid(%ux)flag(%ux)ci(%V)gi(%V)yi(%V)si(%V) %s",			up->raddr, bp->file, nhgetl(bp->xid), nhgets(bp->flags),			bp->ciaddr, bp->giaddr, bp->yiaddr, bp->siaddr,			optbuf);}voidparseoptions(Req *rp){	int n, c, code;	uchar *o, *p;	p = rp->p;	while(p < rp->e){		code = *p++;		if(code == 255)			break;		if(code == 0)			continue;		/* ignore anything that's too long */		n = *p++;		o = p;		p += n;		if(p > rp->e)			return;		switch(code){		case ODipaddr:	/* requested ip address */			if(n == IPv4addrlen)				v4tov6(rp->ip, o);			break;		case ODlease:	/* requested lease time */			rp->leasetime = nhgetl(o);			if(rp->leasetime > MaxLease || rp->leasetime < 0)				rp->leasetime = MaxLease;			break;		case ODtype:			c = *o;			if(c < 10 && c > 0)				rp->dhcptype = c;			break;		case ODserverid:			if(n == IPv4addrlen)				v4tov6(rp->server, o);			break;		case ODmessage:			if(n > sizeof rp->msg-1)				n = sizeof rp->msg-1;			memmove(rp->msg, o, n);			rp->msg[n] = 0;			break;		case ODmaxmsg:			c = nhgets(o);			c -= 28;			c += OUdphdrsize;			if(c > 0)				rp->max = rp->buf + c;			break;		case ODclientid:			if(n <= 1)				break;

⌨️ 快捷键说明

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