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

📄 ppp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
	av[0] = "dns";	av[1] = "wins";	sprint(ip, "%I", ppp->local);	t = csipinfo(ppp->net, "ip", ip, av, 2);	ndns = nwins = 0;	for(nt = t; nt != nil; nt = nt->entry){		if(strcmp(nt->attr, "dns") == 0){			if(ndns < 2)				parseip(ppp->dns[ndns++], nt->val);		} else if(strcmp(nt->attr, "wins") == 0){			if(nwins < 2)				parseip(ppp->wins[nwins++], nt->val);		}	}	if(t != nil)		ndbfree(t);}/* *  parse configuration request, sends an ack or reject packet * *	returns:	-1 if request was syntacticly incorrect *			 0 if packet was accepted *			 1 if packet was rejected */static intgetopts(PPP *ppp, Pstate *p, Block *b){	Lcpmsg *m, *repm;		Lcpopt *o;	uchar *cp, *ap;	ulong rejecting, nacking, flags, proto, chapproto;	ulong mtu, ctlmap, period;	ulong x;	Block *repb;	Comptype *ctype;	Ipaddr ipaddr;	rejecting = 0;	nacking = 0;	flags = 0;	/* defaults */	invalidate(ipaddr);	mtu = ppp->mtu;	ctlmap = 0xffffffff;	period = 0;	ctype = nil;	chapproto = 0;	m = (Lcpmsg*)b->rptr;	repb = alloclcp(Lconfack, m->id, BLEN(b), &repm);	/* copy options into ack packet */	memmove(repm->data, m->data, b->wptr - m->data);	repb->wptr += b->wptr - m->data;	/* look for options we don't recognize or like */	for(cp = m->data; cp < b->wptr; cp += o->len){		o = (Lcpopt*)cp;		if(cp + o->len > b->wptr || o->len==0){			freeb(repb);			netlog("ppp: bad option length %ux\n", o->type);			return -1;		}		switch(p->proto){		case Plcp:			switch(o->type){			case Oac:				flags |= Fac;				continue;			case Opc:				flags |= Fpc;				continue;			case Omtu:				mtu = nhgets(o->data);				continue;			case Omagic:				if(ppp->magic == nhgetl(o->data))					netlog("ppp: possible loop\n");				continue;			case Octlmap:				ctlmap = nhgetl(o->data);				continue;			case Oquality:				proto = nhgets(o->data);				if(proto != Plqm)					break;				x = nhgetl(o->data+2)*10;				period = (x+Period-1)/Period;				continue;			case Oauth:				proto = nhgets(o->data);				if(proto == Ppasswd && !server){					chapproto = APpasswd;					continue;				}				if(proto != Pchap)					break;				if(o->data[2] != APmd5 && o->data[2] != APmschap)					break;				chapproto = o->data[2];				continue;			}			break;		case Pccp:			if(nocompress)				break;			switch(o->type){			case Octhwack:				break;			/*				if(o->len == 2){					ctype = &cthwack;					continue;				}				if(!nacking){					nacking = 1;					repb->wptr = repm->data;					repm->code = Lconfnak;				}				puto(repb, Octhwack);				continue;			*/			case Ocmppc:				x = nhgetl(o->data);				// hack for Mac				// if(x == 0)				//	continue;				/* stop ppp loops */				if((x&0x41) == 0 || ppp->ctries++ > 5) {					/*					 * turn off requests as well - I don't think this					 * is needed in the standard					 */					p->optmask &= ~Fcmppc;					break;				}				if(rejecting)					continue;				if(x & 1) {					ctype = &cmppc;					ppp->sendencrypted = (o->data[3]&0x40) == 0x40;					continue;				}				if(!nacking){					nacking = 1;					repb->wptr = repm->data;					repm->code = Lconfnak;				}				*repb->wptr++ = Ocmppc;				*repb->wptr++ = 6;				*repb->wptr++ = 0;				*repb->wptr++ = 0;				*repb->wptr++ = 0;				*repb->wptr++ = 0x41;				continue;			}			break;		case Pipcp:			switch(o->type){			case Oipaddr:					v4tov6(ipaddr, o->data);				if(!validv4(ppp->remote))					continue;				if(!validv4(ipaddr) && !rejecting){					/* other side requesting an address */					if(!nacking){						nacking = 1;						repb->wptr = repm->data;						repm->code = Lconfnak;					}					putv4o(repb, Oipaddr, ppp->remote);				}				continue;			case Oipdns:				ap = ppp->dns[0];				goto ipinfo;			case Oipdns2:					ap = ppp->dns[1];				goto ipinfo;			case Oipwins:					ap = ppp->wins[0];				goto ipinfo;			case Oipwins2:				ap = ppp->wins[1];				goto ipinfo;			ipinfo:				if(!validv4(ap))					getipinfo(ppp);				if(!validv4(ap))					break;				v4tov6(ipaddr, o->data);				if(!validv4(ipaddr) && !rejecting){					/* other side requesting an address */					if(!nacking){						nacking = 1;						repb->wptr = repm->data;						repm->code = Lconfnak;					}					putv4o(repb, o->type, ap);				}				continue;			case Oipcompress:				/*				 * don't compress tcp header if we've negotiated data compression.				 * tcp header compression has very poor performance if there is an error.				 */				proto = nhgets(o->data);				if(noipcompress || proto != Pvjctcp || ppp->ctype != nil)					break;				if(compress_negotiate(ppp->ctcp, o->data+2) < 0)					break;				flags |= Fipcompress;				continue;			}			break;		}		/* come here if option is not recognized */		if(!rejecting){			rejecting = 1;			repb->wptr = repm->data;			repm->code = Lconfrej;		}		netlog("ppp: bad %ux option %d\n", p->proto, o->type);		memmove(repb->wptr, o, o->len);		repb->wptr += o->len;	}	/* permanent changes only after we know that we liked the packet */	if(!rejecting && !nacking){		switch(p->proto){		case Plcp:			ppp->period = period;			ppp->xctlmap = ctlmap;			if(mtu > Maxmtu)				mtu = Maxmtu;			if(mtu < Minmtu)				mtu = Minmtu;			ppp->mtu = mtu;			if(chapproto)				ppp->chap->proto = chapproto;						break;		case Pccp:			if(ppp->ctype != nil){				(*ppp->ctype->fini)(ppp->cstate);				ppp->cstate = nil;			}			ppp->ctype = ctype;			if(ctype)				ppp->cstate = (*ctype->init)(ppp);			break;		case Pipcp:			if(validv4(ipaddr) && ppp->remotefrozen == 0) 				ipmove(ppp->remote, ipaddr);			break;		}		p->flags = flags;	}	hnputs(repm->len, BLEN(repb));	printopts(p, repb, 1);	putframe(ppp, p->proto, repb);	freeb(repb);	return rejecting || nacking;}static voiddmppkt(char *s, uchar *a, int na){	int i;	if (debug < 3)		return;	fprint(2, "%s", s);	for(i = 0; i < na; i++)		fprint(2, " %.2ux", a[i]);	fprint(2, "\n");}static voiddropoption(Pstate *p, Lcpopt *o){	unsigned n = o->type;	switch(n){		case Oipdns:			p->optmask &= ~Fipdns;			break;		case Oipwins:			p->optmask &= ~Fipwins;			break;		case Oipdns2:			p->optmask &= ~Fipdns2;			break;		case Oipwins2:			p->optmask &= ~Fipwins2;			break;		default:			if(o->type < 8*sizeof(p->optmask))				p->optmask &= ~(1<<o->type);			break;	}}/* *  parse configuration rejection, just stop sending anything that they *  don't like (except for ipcp address nak). */static voidrejopts(PPP *ppp, Pstate *p, Block *b, int code){	Lcpmsg *m;	Lcpopt *o;	uchar newip[IPaddrlen];	/* just give up trying what the other side doesn't like */	m = (Lcpmsg*)b->rptr;	for(b->rptr = m->data; b->rptr < b->wptr; b->rptr += o->len){		o = (Lcpopt*)b->rptr;		if(b->rptr + o->len > b->wptr){			netlog("ppp: bad roption length %ux\n", o->type);			return;		}		if(code == Lconfrej){			dropoption(p, o);			netlog("ppp: %ux rejecting %d\n",					p->proto, o->type);			continue;		}		switch(p->proto){		case Plcp:			switch(o->type){			case Octlmap:				ppp->rctlmap = nhgetl(o->data);				break;			case Oauth:				/* don't allow client to request no auth */				/* could try different auth protocol here */				fprint(2, "ppp: can not reject CHAP\n");				exits("ppp: CHAP");				break;			default:				if(o->type < 8*sizeof(p->optmask))					p->optmask &= ~(1<<o->type);				break;			};			break;		case Pccp:			switch(o->type){			default:				dropoption(p, o);				break;			}			break;		case Pipcp:			switch(o->type){			case Oipaddr:syslog(0, "ppp", "rejected addr %I with %V", ppp->local, o->data);				/* if we're a server, don't let other end change our addr */				if(ppp->localfrozen){					dropoption(p, o);					break;				}				/* accept whatever server tells us */				if(!validv4(ppp->local)){					v4tov6(ppp->local, o->data);					dropoption(p, o);					break;				}				/* if he didn't like our addr, ask for a generic one */				v4tov6(newip, o->data);				if(!validv4(newip)){					invalidate(ppp->local);					break;				}				/* if he gives us something different, use it anyways */				v4tov6(ppp->local, o->data);				dropoption(p, o);				break;			case Oipdns:				if (!validv4(ppp->dns[0])){					v4tov6(ppp->dns[0], o->data);					dropoption(p, o);					break;				}				v4tov6(newip, o->data);				if(!validv4(newip)){					invalidate(ppp->dns[0]);					break;				}				v4tov6(ppp->dns[0], o->data);				dropoption(p, o);				break;			case Oipwins:				if (!validv4(ppp->wins[0])){					v4tov6(ppp->wins[0], o->data);					dropoption(p, o);					break;				}				v4tov6(newip, o->data);				if(!validv4(newip)){					invalidate(ppp->wins[0]);					break;				}				v4tov6(ppp->wins[0], o->data);				dropoption(p, o);				break;			case Oipdns2:				if (!validv4(ppp->dns[1])){					v4tov6(ppp->dns[1], o->data);					dropoption(p, o);					break;				}				v4tov6(newip, o->data);				if(!validv4(newip)){					invalidate(ppp->dns[1]);					break;				}				v4tov6(ppp->dns[1], o->data);				dropoption(p, o);				break;			case Oipwins2:				if (!validv4(ppp->wins[1])){					v4tov6(ppp->wins[1], o->data);					dropoption(p, o);					break;				}				v4tov6(newip, o->data);				if(!validv4(newip)){					invalidate(ppp->wins[1]);					break;				}				v4tov6(ppp->wins[1], o->data);				dropoption(p, o);				break;			default:				dropoption(p, o);				break;			}			break;		}	}}/* *  put a messages through the lcp or ipcp state machine.  They are *  very similar. */static voidrcv(PPP *ppp, Pstate *p, Block *b){	ulong len;	int err;	Lcpmsg *m;	int proto;	if(BLEN(b) < 4){		netlog("ppp: short lcp message\n");		freeb(b);		return;	}	m = (Lcpmsg*)b->rptr;	len = nhgets(m->len);	if(BLEN(b) < len){		netlog("ppp: short lcp message\n");		freeb(b);		return;	}	netlog("ppp: %ux rcv %d len %ld id %d/%d/%d\n",		p->proto, m->code, len, m->id, p->confid, p->id);	if(p->proto != Plcp && ppp->lcp->state != Sopened){		netlog("ppp: non-lcp with lcp not open\n");		freeb(b);		return;	}	qlock(ppp);	switch(m->code){	case Lconfreq:		printopts(p, b, 0);		err = getopts(ppp, p, b);		if(err < 0)			break;		if(m->id == p->rcvdconfid)			break;			/* don't change state for duplicates */		switch(p->state){		case Sackrcvd:			if(err)				break;			newstate(ppp, p, Sopened);			break;		case Sclosed:		case Sopened:			config(ppp, p, 1);			if(err == 0)				newstate(ppp, p, Sacksent);			else				newstate(ppp, p, Sreqsent);			break;		case Sreqsent:		case Sacksent:			if(err == 0)				newstate(ppp, p, Sacksent);			else				newstate(ppp, p, Sreqsent);			break;		}		break;	case Lconfack:		if(p->confid != m->id){			/* ignore if it isn't the message we're sending */			netlog("ppp: dropping confack\n");			break;		}		p->confid = -1;		/* ignore duplicates */		p->id++;		/* avoid sending duplicates */		netlog("ppp: recv confack\n");		switch(p->state){		case Sopened:		case Sackrcvd:			config(ppp, p, 1);			newstate(ppp, p, Sreqsent);			break;		case Sreqsent:			newstate(ppp, p, Sackrcvd);			break;		case Sacksent:			newstate(ppp, p, Sopened);			break;		}		break;	case Lconfrej:	case Lconfnak:		if(p->confid != m->id) {			/* ignore if it isn't the message we're sending */			netlog("ppp: dropping confrej or confnak\n");			break;		}		p->confid = -1;		/* ignore duplicates */		p->id++;		/* avoid sending duplicates */		switch(p->state){		case Sopened:		case Sackrcvd:			config(ppp, p, 1);			newstate(ppp, p, Sreqsent);			break;		case Sreqsent:		case Sacksent:			printopts(p, b, 0);			rejopts(ppp, p, b, m->code);			config(ppp, p, 1);			break;		}		break;	case Ltermreq:		m->code = Ltermack;		putframe(ppp, p->proto, b);		switch(p->state){		case Sackrcvd:		case Sacksent:			newstate(ppp, p, Sreqsent);			break;		case Sopened:			newstate(ppp, p, Sclosing);			break;		}		break;	case Ltermack:		if(p->termid != m->id)	/* ignore if it isn't the message we're sending */			break;		if(p->proto == Plcp)			ppp->ipcp->state = Sclosed;		switch(p->state){		case Sclosing:			newstate(ppp, p, Sclosed);			break;		case Sackrcvd:			newstate(ppp, p, Sreqsent);			break;		case Sopened:			config(ppp, p, 0);			newstate(ppp, p, Sreqsent);			break;		}		break;	case Lcoderej:		//newstate(ppp, p, Sclosed);		syslog(0, LOG, "code reject %d\n", m->data[0]);		break;	case Lprotorej:		proto = nhgets(m->data);		netlog("ppp: proto reject %ux\n", proto);		if(proto == Pccp)			newstate(ppp, ppp->ccp, Sclosed);		break;	case Lechoreq:		if(BLEN(b) < 8){			netlog("ppp: short lcp echo request\n");			freeb(b);			return;		}		m->code = Lechoack;		hnputl(m->data, ppp->magic);		putframe(ppp, p->proto, b);		break;	case Lechoack:		p->echoack = 1;		break;	case Ldiscard:		/* nothing to do */		break;	case Lresetreq:		if(p->proto != Pccp)			break;		ppp->stat.compreset++;		if(ppp->ctype != nil)			b = (*ppp->ctype->resetreq)(ppp->cstate, b);		if(b != nil) {			m = (Lcpmsg*)b->rptr;			m->code = Lresetack;			putframe(ppp, p->proto, b);		}		break;	case Lresetack:		if(p->proto != Pccp)			break;		if(ppp->unctype != nil)			(*ppp->unctype->resetack)(ppp->uncstate, b);		break;	}	qunlock(ppp);	freeb(b);}/* *  timer for protocol state machine */static voidptimer(PPP *ppp, Pstate *p){	if(p->state == Sopened || p->state == Sclosed)		return;	p->timeout--;	switch(p->state){	case Sclosing:		sendtermreq(ppp, p);		break;	case Sreqsent:	case Sacksent:		if(p->timeout <= 0)			newstate(ppp, p, Sclosed);		else {			config(ppp, p, 0);		}		break;	case Sackrcvd:		if(p->timeout <= 0)			newstate(ppp, p, Sclosed);		else {			config(ppp, p, 0);			newstate(ppp, p, Sreqsent);		}		break;	}}/* paptimer -- pap timer event handler * * If PAP authorization hasn't come through, resend an authreqst.  If * the maximum number of requests have been sent (~ 30 seconds), give * up. * */static voidauthtimer(PPP* ppp){	if(ppp->chap->proto != APpasswd)		return;	if(ppp->chap->id < 21)		putpaprequest(ppp);	else {		terminate(ppp, 0);		netlog("ppp: pap timed out--not authorized\n");	}}/* *  timer for ppp */static voidppptimer(PPP *ppp){	while(!dying){		sleep(Period);		qlock(ppp);		netlog("ppp: ppptimer\n");		ptimer(ppp, ppp->lcp);		if(ppp->lcp->state == Sopened) {			switch(ppp->phase){			case Pnet:				ptimer(ppp, ppp->ccp);				ptimer(ppp, ppp->ipcp);				break;			case Pauth:				authtimer(ppp);				break;

⌨️ 快捷键说明

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