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

📄 ppp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
			}		}		/* link quality measurement */		if(ppp->period && --(ppp->timeout) <= 0){			ppp->timeout = ppp->period;			putlqm(ppp);		}		qunlock(ppp);	}}static voidsetdefroute(char *net, Ipaddr gate){	int fd;	char path[128];	snprint(path, sizeof path, "%s/iproute", net);	fd = open(path, ORDWR);	if(fd < 0)		return;	fprint(fd, "add 0 0 %I", gate);	close(fd);}enum{	Mofd=	32,};struct{	Lock;	int	fd[Mofd];	int	cfd[Mofd];	int	n;} old;static char*ipopen(PPP *ppp){	static int ipinprocpid;	int n, cfd, fd;	char path[128];	char buf[128];	if(ipinprocpid <= 0){		snprint(path, sizeof path, "%s/ipifc/clone", ppp->net);		cfd = open(path, ORDWR);		if(cfd < 0)			return "can't open ip interface";		n = read(cfd, buf, sizeof(buf) - 1);		if(n <= 0){			close(cfd);			return "can't open ip interface";		}		buf[n] = 0;		netlog("ppp: setting up IP interface local %I remote %I (valid %d)\n",			ppp->local, ppp->remote, validv4(ppp->remote));		if(!validv4(ppp->remote))			ipmove(ppp->remote, ppp->local);		snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);		fd = open(path, ORDWR);		if(fd < 0){			close(cfd);			return "can't open ip interface";		}		if(fprint(cfd, "bind pkt") < 0)			return "binding pkt to ip interface";		if(fprint(cfd, "add %I 255.255.255.255 %I %lud proxy", ppp->local,			ppp->remote, ppp->mtu-10) < 0){			close(cfd);			return "can't set addresses";		}		if(primary)			setdefroute(ppp->net, ppp->remote);		ppp->ipfd = fd;		ppp->ipcfd = cfd;		/* signal main() that ip is configured */		rendezvous((void*)Rmagic, 0);		switch(ipinprocpid = rfork(RFPROC|RFMEM|RFNOWAIT)){		case -1:			sysfatal("forking ipinproc");		case 0:			ipinproc(ppp);			terminate(ppp, 1);			_exits(0);		}	} else {		/* we may have changed addresses */		if(ipcmp(ppp->local, ppp->curlocal) != 0 ||		   ipcmp(ppp->remote, ppp->curremote) != 0){			snprint(buf, sizeof buf, "remove %I 255.255.255.255 %I",			    ppp->curlocal, ppp->curremote);			if(fprint(ppp->ipcfd, "%s", buf) < 0)				syslog(0, "ppp", "can't %s: %r", buf);			snprint(buf, sizeof buf, "add %I 255.255.255.255 %I %lud proxy",			    ppp->local, ppp->remote, ppp->mtu-10);			if(fprint(ppp->ipcfd, "%s", buf) < 0)				syslog(0, "ppp", "can't %s: %r", buf);		}		syslog(0, "ppp", "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,		   ppp->local, ppp->remote);	}	ipmove(ppp->curlocal, ppp->local);	ipmove(ppp->curremote, ppp->remote);	return nil;}/* return next input IP packet */Block*pppread(PPP *ppp){	Block *b, *reply;	int proto, len;	Lcpmsg *m;	while(!dying){		b = getframe(ppp, &proto);		if(b == nil)			return nil;Again:		switch(proto){		case Plcp:			rcv(ppp, ppp->lcp, b);			break;		case Pccp:			rcv(ppp, ppp->ccp, b);			break;		case Pipcp:			rcv(ppp, ppp->ipcp, b);			break;		case Pip:			if(ppp->ipcp->state == Sopened)				return b;			netlog("ppp: IP recved: link not up\n");			freeb(b);			break;		case Plqm:			getlqm(ppp, b);			break;		case Pchap:			getchap(ppp, b);			break;		case Ppasswd:			getpap(ppp, b);			break;		case Pvjctcp:		case Pvjutcp:			if(ppp->ipcp->state != Sopened){				netlog("ppp: VJ tcp recved: link not up\n");				freeb(b);				break;			}			ppp->stat.vjin++;			b = tcpuncompress(ppp->ctcp, b, proto);			if(b != nil)				return b;			ppp->stat.vjfail++;			break;		case Pcdata:			ppp->stat.uncomp++;			if(ppp->ccp->state != Sopened){				netlog("ppp: compressed data recved: link not up\n");				freeb(b);				break;			}			if(ppp->unctype == nil) {				netlog("ppp: compressed data recved: no compression\n");				freeb(b);				break;			}			len = BLEN(b);			b = (*ppp->unctype->uncompress)(ppp, b, &proto, &reply);			if(reply != nil){				/* send resetreq */				ppp->stat.uncompreset++;				putframe(ppp, Pccp, reply);				freeb(reply);			}			if(b == nil)				break;			ppp->stat.uncompin += len;			ppp->stat.uncompout += BLEN(b);/* netlog("ppp: uncompressed frame %ux %d %d (%d uchars)\n", proto, b->rptr[0], b->rptr[1], BLEN(b)); /* */			goto Again;			default:			syslog(0, LOG, "unknown proto %ux", proto);			if(ppp->lcp->state == Sopened){				/* reject the protocol */				b->rptr -= 6;				m = (Lcpmsg*)b->rptr;				m->code = Lprotorej;				m->id = ++ppp->lcp->id;				hnputs(m->data, proto);				hnputs(m->len, BLEN(b));				putframe(ppp, Plcp, b);			}			freeb(b);			break;		}	}	return nil;}/* transmit an IP packet */intpppwrite(PPP *ppp, Block *b){	int proto;	int len;	qlock(ppp);	/* can't send ip packets till we're established */	if(ppp->ipcp->state != Sopened) {		qunlock(ppp);		syslog(0, LOG, "IP write: link not up");		len = blen(b);		freeb(b);		return len;	}	proto = Pip;	ppp->stat.ipsend++;	if(ppp->ipcp->flags & Fipcompress){		b = compress(ppp->ctcp, b, &proto);		if(b == nil){			qunlock(ppp);			return 0;		}		if(proto != Pip)			ppp->stat.vjout++;	}	if(ppp->ctype != nil) {		len = blen(b);		b = (*ppp->ctype->compress)(ppp, proto, b, &proto);		if(proto == Pcdata) {			ppp->stat.comp++;			ppp->stat.compin += len;			ppp->stat.compout += blen(b);		}	} 	if(putframe(ppp, proto, b) < 0) {		qunlock(ppp);		freeb(b);		return -1;	}	qunlock(ppp);	len = blen(b);	freeb(b);	return len;}static voidterminate(PPP *ppp, int kill){	close(ppp->ipfd);	ppp->ipfd = -1;	close(ppp->ipcfd);	ppp->ipcfd = -1;	close(ppp->mediain);	close(ppp->mediaout);	ppp->mediain = -1;	ppp->mediaout = -1;	dying = 1;	if(kill)		postnote(PNGROUP, getpid(), "die");}typedef struct Iphdr Iphdr;struct Iphdr{	uchar	vihl;		/* Version and header length */	uchar	tos;		/* Type of service */	uchar	length[2];	/* packet length */	uchar	id[2];		/* Identification */	uchar	frag[2];	/* Fragment information */	uchar	ttl;		/* Time to live */	uchar	proto;		/* Protocol */	uchar	cksum[2];	/* Header checksum */	uchar	src[4];		/* Ip source (uchar ordering unimportant) */	uchar	dst[4];		/* Ip destination (uchar ordering unimportant) */};static voidipinproc(PPP *ppp){	Block *b;	int m, n;	Iphdr *ip;	while(!dying){		b = allocb(Buflen);		n = read(ppp->ipfd, b->wptr, b->lim-b->wptr);		if(n < 0)			break;		/* trim packet if there's padding (e.g. from ether) */		ip = (Iphdr*)b->rptr;		m = nhgets(ip->length);		if(m < n && m > 0)			n = m;		b->wptr += n;		if(pppwrite(ppp, b) < 0)			break;	}}static voidcatchdie(void*, char *msg){	if(strstr(msg, "die") != nil)		noted(NCONT);	else		noted(NDFLT);}static voidhexdump(uchar *a, int na){	int i;	char buf[80];	fprint(2, "dump %p %d\n", a, na);	buf[0] = '\0';	for(i=0; i<na; i++){		sprint(buf+strlen(buf), " %.2ux", a[i]);		if(i%16 == 7)			sprint(buf+strlen(buf), " --");		if(i%16==15){			sprint(buf+strlen(buf), "\n");			write(2, buf, strlen(buf));			buf[0] = '\0';		}	}	if(i%16){		sprint(buf+strlen(buf), "\n");		write(2, buf, strlen(buf));	}}static voidmediainproc(PPP *ppp){	Block *b;	Ipaddr remote;	notify(catchdie);	while(!dying){		b = pppread(ppp);		if(b == nil){			syslog(0, LOG, "pppread return nil");			break;		}		ppp->stat.iprecv++;		if(ppp->ipcp->state != Sopened) {			ppp->stat.iprecvnotup++;			freeb(b);			continue;		}		if(server) {			v4tov6(remote, b->rptr+12);			if(ipcmp(remote, ppp->remote) != 0) {				ppp->stat.iprecvbadsrc++;				freeb(b);				continue;			}		}		if(debug > 1){			netlog("ip write pkt %p %d\n", b->rptr, blen(b));			hexdump(b->rptr, blen(b));		}		if(write(ppp->ipfd, b->rptr, blen(b)) < 0) {			syslog(0, LOG, "error writing to pktifc");			freeb(b);			break;		}		freeb(b);	}	netlog(": remote=%I: ppp shutting down\n", ppp->remote);	syslog(0, LOG, ": remote=%I: ppp shutting down", ppp->remote);	syslog(0, LOG, "\t\tppp send = %lud/%lud recv= %lud/%lud",		ppp->out.packets, ppp->out.uchars,		ppp->in.packets, ppp->in.uchars);	syslog(0, LOG, "\t\tip send=%lud", ppp->stat.ipsend);	syslog(0, LOG, "\t\tip recv=%lud notup=%lud badsrc=%lud",		ppp->stat.iprecv, ppp->stat.iprecvnotup, ppp->stat.iprecvbadsrc);	syslog(0, LOG, "\t\tcompress=%lud in=%lud out=%lud reset=%lud",		ppp->stat.comp, ppp->stat.compin, ppp->stat.compout, ppp->stat.compreset);	syslog(0, LOG, "\t\tuncompress=%lud in=%lud out=%lud reset=%lud",		ppp->stat.uncomp, ppp->stat.uncompin, ppp->stat.uncompout,		ppp->stat.uncompreset);	syslog(0, LOG, "\t\tvjin=%lud vjout=%lud vjfail=%lud", 		ppp->stat.vjin, ppp->stat.vjout, ppp->stat.vjfail);}/* *  link quality management */static voidgetlqm(PPP *ppp, Block *b){	Qualpkt *p;	p = (Qualpkt*)b->rptr;	if(BLEN(b) == sizeof(Qualpkt)){		ppp->in.reports++;		ppp->pout.reports = nhgetl(p->peeroutreports);		ppp->pout.packets = nhgetl(p->peeroutpackets);		ppp->pout.uchars = nhgetl(p->peeroutuchars);		ppp->pin.reports = nhgetl(p->peerinreports);		ppp->pin.packets = nhgetl(p->peerinpackets);		ppp->pin.discards = nhgetl(p->peerindiscards);		ppp->pin.errors = nhgetl(p->peerinerrors);		ppp->pin.uchars = nhgetl(p->peerinuchars);		/* save our numbers at time of reception */		memmove(&ppp->sin, &ppp->in, sizeof(Qualstats));	}	freeb(b);	if(ppp->period == 0)		putlqm(ppp);}static voidputlqm(PPP *ppp){	Qualpkt *p;	Block *b;	b = allocb(sizeof(Qualpkt));	b->wptr += sizeof(Qualpkt);	p = (Qualpkt*)b->rptr;	hnputl(p->magic, 0);	/* heresay (what he last told us) */	hnputl(p->lastoutreports, ppp->pout.reports);	hnputl(p->lastoutpackets, ppp->pout.packets);	hnputl(p->lastoutuchars, ppp->pout.uchars);	/* our numbers at time of last reception */	hnputl(p->peerinreports, ppp->sin.reports);	hnputl(p->peerinpackets, ppp->sin.packets);	hnputl(p->peerindiscards, ppp->sin.discards);	hnputl(p->peerinerrors, ppp->sin.errors);	hnputl(p->peerinuchars, ppp->sin.uchars);	/* our numbers now */	hnputl(p->peeroutreports, ppp->out.reports+1);	hnputl(p->peeroutpackets, ppp->out.packets+1);	hnputl(p->peeroutuchars, ppp->out.uchars+53/*hack*/);	putframe(ppp, Plqm, b);	freeb(b);	ppp->out.reports++;}/* * init challenge response dialog */static voidchapinit(PPP *ppp){	Block *b;	Lcpmsg *m;	Chap *c;	int len;	char *aproto;	getauth(ppp);	c = ppp->chap;	c->id++;	switch(c->proto){	default:		abort();	case APmd5:		aproto = "chap";		break;	case APmschap:		aproto = "mschap";		break;	}	if((c->cs = auth_challenge("proto=%q role=server", aproto)) == nil)		sysfatal("auth_challenge: %r");	syslog(0, LOG, ": remote=%I: sending %d byte challenge", ppp->remote, c->cs->nchal);	len = 4 + 1 + c->cs->nchal + strlen(ppp->chapname);	b = alloclcp(Cchallenge, c->id, len, &m);	*b->wptr++ = c->cs->nchal;	memmove(b->wptr, c->cs->chal, c->cs->nchal);	b->wptr += c->cs->nchal;	memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));	b->wptr += strlen(ppp->chapname);	hnputs(m->len, len);	putframe(ppp, Pchap, b);	freeb(b);	c->state = Cchalsent;}/* * BUG factotum should do this */enum {	MShashlen = 16,	MSresplen = 24,	MSchallen = 8,};voiddesencrypt(uchar data[8], uchar key[7]){	ulong ekey[32];	key_setup(key, ekey);	block_cipher(ekey, data, 0);}voidnthash(uchar hash[MShashlen], char *passwd){	uchar buf[512];	int i;		for(i=0; *passwd && i<sizeof(buf); passwd++) {		buf[i++] = *passwd;		buf[i++] = 0;	}	memset(hash, 0, 16);	md4(buf, i, hash, 0);}voidmschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen]){	int i;	uchar buf[21];		memset(buf, 0, sizeof(buf));	memcpy(buf, hash, MShashlen);	for(i=0; i<3; i++) {		memmove(resp+i*MSchallen, chal, MSchallen);		desencrypt(resp+i*MSchallen, buf+i*7);	}}/* *  challenge response dialog */extern	int	_asrdresp(int, uchar*, int);static voidgetchap(PPP *ppp, Block *b){	AuthInfo *ai;	Lcpmsg *m;	int len, vlen, i, id, n, nresp;	char md5buf[512], code;	Chap *c;	Chapreply cr;	MSchapreply mscr;	char uid[PATH];	uchar digest[16], *p, *resp, sdigest[SHA1dlen];	uchar mshash[MShashlen], mshash2[MShashlen];	DigestState *s;	uchar msresp[2*MSresplen+1];	m = (Lcpmsg*)b->rptr;	len = nhgets(m->len);	if(BLEN(b) < len){		syslog(0, LOG, "short chap message");		freeb(b);		return;	}	qlock(ppp);	switch(m->code){	case Cchallenge:		getauth(ppp);		vlen = m->data[0];		if(vlen > len - 5) {			netlog("PPP: chap: bad challenge len\n");			break;		}		id = m->id;		switch(ppp->chap->proto){		default:			abort();		case APmd5:			md5buf[0] = m->id;			strcpy(md5buf+1, ppp->secret);			n = strlen(ppp->secret) + 1;			memmove(md5buf+n, m->data+1, vlen);			n += vlen;			md5((uchar*)md5buf, n, digest, nil);			resp = digest;			nresp = 16;			break;		case APmschap:			nthash(mshash, ppp->secret);			memset(msresp, 0, sizeof msresp);			mschalresp(msresp+MSresplen, mshash, m->data+1);			resp = msresp;			nresp = sizeof msresp;			nthash(mshash, ppp->secret);			md4(mshash, 16, mshash2, 0);			s = sha1(mshash2, 16, 0, 0);			sha1(mshash2, 16, 0, s);			sha1(m->data+1, 8, sdigest, s);			memmove(ppp->key, sdigest, 16);			break;		}		len = 4 + 1 + nresp + strlen(ppp->chapname);		freeb(b);		b = alloclcp(Cresponse, id, len, &m);		*b->wptr++ = nresp;		memmove(b->wptr, resp, nresp);		b->wptr += nresp;		memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));		b->wptr += strlen(ppp->chapname);		hnputs(m->len, len);		netlog("PPP: sending response len %d\n", len);		putframe(ppp, Pchap, b);		break;	case Cresponse:		c = ppp->chap;		vlen = m->data[0];		if(m->id != c->id) {			netlog("PPP: chap: bad response id\n");			break;		}		switch(c->proto) {		default:			sysfatal("unknown chap protocol: %d", c->proto);		case APmd5:			if(vlen > len - 5 || vlen != 16) {				netlog("PPP: chap: bad response len\n");				break;			}			cr.id = m->id;			memmove(cr.resp, m->data+1, 16);			memset(uid, 0, sizeof(uid));			n = len-5-vlen;			if(n >= PATH)				n = PATH-1;			memmove(uid, m->data+1+vlen, n);			c->cs->user = uid;			c->cs->resp = &cr;			c->cs->nresp = sizeof cr;			break;		case APmschap:			if(vlen > len - 5 || vlen != 49) {				netlog("PPP: chap: bad response len\n");				break;			}			memset(&mscr, 0, sizeof(mscr));			memmove(mscr.LMresp, m->data+1, 24);			memmove(mscr.NTresp, m->data+24+1, 24);			n = len-5-vlen;			p = m->data+1+vlen;			/* remove domain name */			for(i=0; i<n; i++) {				if(p[i] == '\\') {					p += i+1;					n -= i+1;					break;				}			}			if(n >= PATH)				n = PATH-1;			memset(uid, 0, sizeof(uid));			memmove(uid, p, n);			c->cs->user = uid;			c->cs->resp = &mscr;			c->cs->nresp = sizeof mscr;			break;		} 		syslog(0, LOG, ": remote=%I vlen %d proto %d response user %s nresp %d", ppp->remote, vlen, c->proto, c->cs->user, c->cs->nresp);		if((ai = auth_response(c->cs)) == nil || auth_chuid(ai, nil) < 0){			c->state = Cunauth;			code = Cfailure;			syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", ppp->remote, uid);		}else{			c->state = Cauthok;			code = Csuccess;			syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", ppp->remote, uid, ai->nsecret);			if(c->proto == APmschap){				if(ai->nsecret != sizeof(ppp->key))					sysfatal("could not get the encryption key");				memmove(ppp->key, ai->secret, sizeof(ppp->key));			}		}		auth_freeAI(ai);		auth_freechal(c->cs);		c->cs = nil;		freeb(b);		/* send reply */		len = 4;		b = alloclcp(code, c->id, len, &m);		hnputs(m->len, len);		putframe(ppp, Pchap, b);

⌨️ 快捷键说明

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