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

📄 pptp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Point-to-point Tunneling Protocol (PPTP) * See RFC 2637, pptpd.c */#include <u.h>#include <libc.h>#include <bio.h>#include <ip.h>#include <thread.h>int	ack;int	alarmed;int	ctlechotime;int	ctlfd;int	ctlrcvtime;int	debug;int	grefd;uchar localip[IPaddrlen];int	localwin;char	*keyspec;int	now;char	*pppnetmntpt;int	pid;Channel *pidchan;int	pppfd;int	primary;int	rack;Channel	*rdchan;int	rdexpect;int	remid;uchar remoteip[IPaddrlen];int	remwin;int	rseq;int	seq;char	tcpdir[40];Channel *tickchan;int	topppfd;int	aread(int, int, void*, int);int	catchalarm(void*, char*);void	dumpctlpkt(uchar*);void	getaddrs(void);void	*emalloc(long);void	ewrite(int, void*, int);void	myfatal(char*, ...);#pragma varargck argpos myfatal 1int	pptp(char*);void	pushppp(int);void	recordack(int);int	schedack(int, uchar*, int);void	waitacks(void);voidusage(void){	fprint(2, "usage: ip/pptp [-Pd] [-s user:secret] [-x pppnetmntpt] [-w window] server\n");	exits("usage");}voidthreadmain(int argc, char **argv){	int fd;	ARGBEGIN{	case 'P':		primary = 1;		break;	case 'd':		debug++;		break;	case 'k':		keyspec = EARGF(usage());		break;	case 'w':		localwin = atoi(EARGF(usage()));		break;	case 'x':		pppnetmntpt = EARGF(usage());		break;	default:		usage();	}ARGEND	if(argc != 1)		usage();	fmtinstall('E', eipfmt);	fmtinstall('I', eipfmt);	rfork(RFNOTEG);	atnotify(catchalarm, 1);	fd = pptp(argv[0]);	pushppp(fd);	exits(nil);}intcatchalarm(void *a, char *msg){	USED(a);	if(strstr(msg, "alarm")){		alarmed = 1;		return 1;	}	if(debug)		fprint(2, "note rcved: %s\n", msg);	return 0;}enum {	Stack	= 8192,	PptpProto	= 0x0100,	Magic	= 0x1a2b3c4d,	Window	= 16,		/* default window size */	Timeout	= 60,		/* timeout in seconds for control channel */	Pktsize = 2000,		/* maximum packet size */	Tick	= 500,		/* tick length in milliseconds */	Sendtimeout = 4,	/* in ticks */	Servertimeout = 5*60*1000/Tick,	Echointerval = 60*1000/Tick,};enum {	Syncframe	= 0x1,	Asyncframe	= 0x2,	Analog		= 0x1,	Digital		= 0x2,	Version		= 0x100,};enum {	Tstart		= 1,	Rstart		= 2,	Tstop		= 3,	Rstop		= 4,	Techo		= 5,	Recho		= 6,	Tcallout	= 7,	Rcallout	= 8,	Tcallreq	= 9,	Rcallreq	= 10,	Acallcon	= 11,	Tcallclear	= 12,	Acalldis	= 13,	Awaninfo	= 14,	Alinkinfo	= 15,};voidrecho(uchar *in){	uchar out[20];	if(nhgets(in) < 16)		return;	memset(out, 0, sizeof out);	hnputs(out, sizeof out);	hnputs(out+2, 1);	hnputl(out+4, Magic);	hnputs(out+8, Recho);	memmove(out+12, in+12, 4);	out[16] = 1;	ewrite(ctlfd, out, sizeof out);}voidsendecho(void){	uchar out[16];	ctlechotime = now;		memset(out, 0, sizeof out);	hnputs(out, sizeof out);	hnputs(out+2, 1);	hnputl(out+4, Magic);	hnputs(out+8, Techo);	ewrite(ctlfd, out, sizeof out);}voidpptpctlproc(void*){	uchar pkt[1600], *p;	int len;	for(;;){		if(readn(ctlfd, pkt, 2) != 2)			myfatal("pptpread: %r");		len = nhgets(pkt);		if(len < 12)			myfatal("pptpread: bad length %d", len);		if(readn(ctlfd, pkt+2, len-2) != len-2)			myfatal("pptpread: %r");		if(nhgetl(pkt+4) != Magic)			myfatal("pptpread bad magic");		if(nhgets(pkt+2) != 1)			myfatal("pptpread bad message type");		if(debug)			dumpctlpkt(pkt);		ctlrcvtime = now;		switch(nhgets(pkt+8)){		case Tstart:		case Tstop:		case Tcallout:		case Tcallreq:		case Tcallclear:		case Acallcon:		case Acalldis:		case Awaninfo:			myfatal("unexpected msg type %d", nhgets(pkt+8));		case Techo:			recho(pkt);			break;		case Recho:			break;		case Rstart:		case Rstop:		case Rcallout:		case Rcallreq:			if(rdexpect != nhgets(pkt+8))				continue;			p = emalloc(len);			memmove(p, pkt, len);			sendp(rdchan, p);			break;		case Alinkinfo:			myfatal("cannot change ppp params on the fly");		}	}}enum {	Seqnum = 0x1000,	Acknum = 0x0080,	GrePPP = 0x880B,};voidgrereadproc(void*){	int datoff, flags, len, n, pass;	uchar pkt[1600];	uchar src[IPaddrlen], dst[IPaddrlen];	rfork(RFFDG);	close(pppfd);	sendul(pidchan, getpid());	while((n = read(grefd, pkt, sizeof pkt)) > 0){		if(n == sizeof pkt)			myfatal("gre pkt buffer too small");		if(n < 16){			if(debug)				fprint(2, "small pkt len %d ignored\n", n);			continue;		}		v4tov6(src, pkt);		v4tov6(dst, pkt+4);		if(ipcmp(src, remoteip) != 0 || ipcmp(dst, localip) != 0)			myfatal("%I: gre read bad address src=%I dst=%I",				remoteip, src, dst);		if(nhgets(pkt+10) != GrePPP)			myfatal("%I: gre read bad protocol 0x%x",				remoteip, nhgets(pkt+10));		flags = nhgets(pkt+8);		if((flags&0xEF7F) != 0x2001){			if(debug)				fprint(2, "bad flags in gre hdr 0x%x\n", flags);			continue;		}		datoff = 8+8;		pass = 0;		len = nhgets(pkt+8+4);		if(len > n-datoff){			fprint(2, "bad payload length %d > %d\n",				len, n-datoff);			continue;		}		if(flags&Seqnum)			datoff += 4;		if(flags&Acknum){			recordack(nhgetl(pkt+datoff));			datoff += 4;		}		if(flags&Seqnum)			pass = schedack(nhgetl(pkt+8+8), pkt+datoff, len);		if(debug)			fprint(2, "got gre callid %d len %d flag 0x%x pass %d seq %d rseq %d\n", nhgets(pkt+8+6),				len, flags, pass, nhgetl(pkt+8+8), rseq);	}	threadexits(nil);}voidpppreadproc(void*){	int n, myrseq;	uchar pkt[1600];	enum {		Hdr = 8+16,	};	rfork(RFFDG);	close(pppfd);	sendul(pidchan, getpid());	while((n = read(topppfd, pkt+Hdr, sizeof pkt-Hdr)) > 0){		if(n == sizeof pkt-Hdr)			myfatal("ppp pkt buffer too small");		v6tov4(pkt+0, localip);		v6tov4(pkt+4, remoteip);		hnputs(pkt+8, 0x2001 | Seqnum | Acknum);		hnputs(pkt+10, GrePPP);		hnputs(pkt+12, n);		hnputs(pkt+14, remid);		hnputl(pkt+16, ++seq);		myrseq = rseq;		hnputl(pkt+20, myrseq);		rack = myrseq;		if(debug)			fprint(2, "wrote gre callid %d len %d flag 0x%x seq %d rseq %d\n", nhgets(pkt+8+6),				n, nhgets(pkt+8), nhgetl(pkt+16), nhgetl(pkt+20));		if(write(grefd, pkt, n+Hdr) != n+Hdr)			myfatal("gre write: %r");		waitacks();	}	threadexits(nil);}voidsendack(void){	int myrseq;	uchar pkt[20];	v6tov4(pkt+0, localip);	v6tov4(pkt+4, remoteip);	hnputs(pkt+8, 0x2001 | Acknum);	hnputs(pkt+10, GrePPP);	hnputs(pkt+12, 0);	hnputs(pkt+14, remid);	myrseq = rseq;	rack = myrseq;	hnputs(pkt+16, myrseq);	if(write(grefd, pkt, sizeof pkt) != sizeof pkt)		myfatal("gre write: %r");}intschedack(int n, uchar *dat, int len){	static uchar sdat[1600];	static int srseq, slen;	if(n-rseq <= 0){		fprint(2, "skipping pkt %d len %d, have %d\n", n, len, rseq);		return 0;	}	/* missed one pkt, maybe a swap happened, save pkt */	if(n==rseq+2){		memmove(sdat, dat, len);		slen = len;		srseq = n;		return 0;	}	if(n-rseq > 1){		if(slen && srseq == n-1){				fprint(2, "reswapped pkts %d and %d\n", srseq, n);			write(topppfd, sdat, slen);			slen = 0;		}else			fprint(2, "missed pkts %d-%d, got %d len %d\n", rseq+1, n-1, n, len);	}	write(topppfd, dat, len);	rseq = n;	/* send ack if we haven't recently */	if((int)(rseq-rack) > (localwin>>1))		sendack();	return 1;}voidgretimeoutproc(void*){	for(;;){		sleep(Tick);		now++;		nbsendul(tickchan, now);		if(now - ctlrcvtime > Servertimeout)			myfatal("server timeout");		if(now - ctlechotime > Echointerval)			sendecho();	}}voidrecordack(int n){	ack = n;}voidwaitacks(void){/*	int start;	start = now;	while(seq-ack > remwin && now-start < Sendtimeout){		print("seq %d ack %d remwin %d now %d start %d\n",			seq, ack, remwin, now, start);		recvul(tickchan);	}*/}voidtstart(void){	char *name;	uchar pkt[200], *rpkt;

⌨️ 快捷键说明

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