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

📄 pptpd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <ip.h>#define	LOG	"pptpd"typedef struct Call	Call;typedef struct Event Event;#define	SDB	if(debug) fprint(2, #define EDB	);enum {	Magic	= 0x1a2b3c4d,	Nhash	= 17,	Nchan	= 10,		/* maximum number of channels */	Window	= 8,		/* 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 */};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,};struct Event {	QLock;	QLock waitlk;	int	wait;	int ready;};struct Call {	int	ref;	QLock	lk;	int	id;	int	serial;	int	pppfd;	int	closed;	int	pac;	/* server is acting as a PAC */	int	recvwindow;	/* recv windows */	int	sendwindow;	/* send windows */	int	delay;	int	sendaccm;	int	recvaccm;	uint	seq;		/* current seq number - for send */	uint	ack;		/* current acked mesg - for send */	uint	rseq;		/* highest recv seq number for in order packet  */	uint	rack;		/* highest ack sent */	Event	eack;		/* recved ack - for send */	ulong	tick;	uchar	remoteip[IPaddrlen];	/* remote ip address */	int	dhcpfd[2];	/* pipe to dhcpclient */	/* error stats */	struct {		int	crc;		int	frame;		int	hardware;		int	overrun;		int	timeout;		int	align;	} err;	struct {		int	send;		int	sendack;		int	recv;		int	recvack;		int	dropped;		int	missing;		int	sendwait;		int	sendtimeout;	} stat;	Call	*next;};struct {	QLock	lk;	int	start;	int	grefd;	int	grecfd;	uchar	local[IPaddrlen];	uchar	remote[IPaddrlen];	char	*tcpdir;	uchar	ipaddr[IPaddrlen];		/* starting ip addresss to allocate */	int	recvwindow;	char	*pppdir;	char	*pppexec;	double	rcvtime;	/* time at which last request was received */	int	echoid;		/* id of last echo request */	Call	*hash[Nhash];} srv;/* GRE flag bits */enum {	GRE_chksum	= (1<<15),	GRE_routing	= (1<<14),	GRE_key		= (1<<13),	GRE_seq		= (1<<12),	GRE_srcrt	= (1<<11),	GRE_recur	= (7<<8),	GRE_ack		= (1<<7),	GRE_ver		= 0x7,};/* GRE protocols */enum {	GRE_ppp		= 0x880b,};int	debug;double	drop;void	myfatal(char *fmt, ...);#define	PSHORT(p, v)		((p)[0]=((v)>>8), (p)[1]=(v))#define	PLONG(p, v)		(PSHORT(p, (v)>>16), PSHORT(p+2, (v)))#define	PSTRING(d,s,n)		strncpy((char*)(d), s, n)#define	GSHORT(p)		(((p)[0]<<8) | ((p)[1]<<0))#define	GLONG(p)		((GSHORT((p))<<16) | ((GSHORT((p)+2))<<0))#define	GSTRING(d,s,n)		strncpy(d, (char*)(s), n), d[(n)-1] = 0void	serve(void);int	sstart(uchar*, int);int	sstop(uchar*, int);int	secho(uchar*, int);int	scallout(uchar*, int);int	scallreq(uchar*, int);int	scallcon(uchar*, int);int	scallclear(uchar*, int);int	scalldis(uchar*, int);int	swaninfo(uchar*, int);int	slinkinfo(uchar*, int);Call	*callalloc(int id);void	callclose(Call*);void	callfree(Call*);Call	*calllookup(int id);void	gretimeout(void*);void	pppread(void*);void	srvinit(void);void	greinit(void);void	greread(void*);void	greack(Call *c);void	timeoutthread(void*);ulong	parseip(uchar *ato, char *from);int	argatoi(char *p);void	usage(void);int	ipaddralloc(Call *c);void esignal(Event *e);void ewait(Event *e);ulong	thread(void(*f)(void*), void *a);double realtime(void);void *emallocz(int size);int proc(char **argv, int fd0, int fd1, int fd2);voidmain(int argc, char *argv[]){	ARGBEGIN{	case 'd': debug++; break;	case 'p': srv.pppdir = ARGF(); break;	case 'P': srv.pppexec = ARGF(); break;	case 'w': srv.recvwindow = argatoi(ARGF()); break;	case 'D': drop = atof(ARGF()); break;	default:		usage();	}ARGEND	fmtinstall('I', eipfmt);	fmtinstall('E', eipfmt);	fmtinstall('V', eipfmt);	fmtinstall('M', eipfmt);	rfork(RFNOTEG|RFREND);	if(argc != 1)		usage();	srv.tcpdir = argv[0];	srvinit();	syslog(0, LOG, ": src=%I: pptp started: %d", srv.remote, getpid());	SDB  "\n\n\n%I: pptp started\n", srv.remote EDB	greinit();	thread(timeoutthread, 0);	serve();	syslog(0, LOG, ": src=%I: server exits", srv.remote);	exits(0);}voidusage(void){	fprint(2, "usage: pptpd [-dD] [-p ppp-net] [-w window] tcpdir\n");	exits("usage");}voidserve(void){	uchar buf[2000], *p;	int n, n2, len;	int magic;	int op, type;	n = 0;	for(;;) {		n2 = read(0, buf+n, sizeof(buf)-n);		if(n2 < 0)			myfatal("bad read on ctl channel: %r");		if(n2 == 0)			break;		n += n2;		p = buf;		for(;;) {			if(n < 12)				break;			qlock(&srv.lk);			srv.rcvtime = realtime();			qunlock(&srv.lk);			len = GSHORT(p);			type = GSHORT(p+2);			magic = GLONG(p+4);			op = GSHORT(p+8);			if(magic != Magic)				myfatal("bad magic number: got %x", magic);			if(type != 1)				myfatal("bad message type: %d", type);			switch(op) {			default:				myfatal("unknown control op: %d", op);			case Tstart:		/* start-control-connection-request */				n2 = sstart(p, n);				break;			case Tstop:				n2 = sstop(p, n);				if(n2 > 0)					return;				break;			case Techo:				n2 = secho(p, n);				break;			case Tcallout:				n2 = scallout(p, n);				break;			case Tcallreq:				n2 = scallreq(p, n);				break;			case Acallcon:				n2 = scallcon(p, n);				break;			case Tcallclear:				n2 = scallclear(p, n);				break;			case Acalldis:				n2 = scalldis(p, n);				break;			case Awaninfo:				n2 = swaninfo(p, n);				break;			case Alinkinfo:				n2 = slinkinfo(p, n);				break;			}				if(n2 == 0)				break;			if(n2 != len)				myfatal("op=%d: bad length: got %d expected %d", op, len, n2);			n -= n2;			p += n2;					}		/* move down partial message */		if(p != buf && n != 0)			memmove(buf, p, n);	}}intsstart(uchar *p, int n){	int ver, frame, bearer, maxchan, firm;	char host[64], vendor[64], *sysname;	uchar buf[156];	if(n < 156)		return 0;	ver = GSHORT(p+12);	frame = GLONG(p+16);	bearer = GLONG(p+20);	maxchan = GSHORT(p+24);	firm = GSHORT(p+26);	GSTRING(host, p+28, 64);	GSTRING(vendor, p+92, 64);	SDB "%I: start ver = %x f = %d b = %d maxchan = %d firm = %d host = %s vendor = %s\n",		srv.remote, ver, frame, bearer, maxchan, firm, host, vendor EDB	if(ver != Version)		myfatal("bad version: got %x expected %x", ver, Version);	if(srv.start)		myfatal("multiple start messages");	srv.start = 1;	sysname = getenv("sysname");	if(sysname == 0)		strcpy(host, "gnot");	else		strncpy(host, sysname, 64);	free(sysname);	memset(buf, 0, sizeof(buf));	PSHORT(buf+0, sizeof(buf));	/* length */	PSHORT(buf+2, 1);		/* message type */	PLONG(buf+4, Magic);		/* magic */	PSHORT(buf+8, Rstart);		/* op */	PSHORT(buf+12, Version);	/* version */	buf[14] = 1;			/* result = ok */	PLONG(buf+16, Syncframe|Asyncframe);	/* frameing */	PLONG(buf+20, Digital|Analog);	/* berear capabilities */	PSHORT(buf+24, Nchan);		/* max channels */	PSHORT(buf+26, 1);		/* driver version */	PSTRING(buf+28, host, 64);	/* host name */	PSTRING(buf+92, "plan 9", 64);	/* vendor */	if(write(1, buf, sizeof(buf)) < sizeof(buf))		myfatal("write failed: %r");	return 156;}intsstop(uchar *p, int n){	int reason;	uchar buf[16];	if(n < 16)		return 0;	reason = p[12];		SDB "%I: stop %d\n", srv.remote, reason EDB	memset(buf, 0, sizeof(buf));	PSHORT(buf+0, sizeof(buf));	/* length */	PSHORT(buf+2, 1);		/* message type */	PLONG(buf+4, Magic);		/* magic */	PSHORT(buf+8, Rstop);		/* op */	buf[12] = 1;			/* ok */	if(write(1, buf, sizeof(buf)) < sizeof(buf))		myfatal("write failed: %r");	return 16;}intsecho(uchar *p, int n){	int id;	uchar buf[20];	if(n < 16)		return 0;	id = GLONG(p+12);		SDB "%I: echo %d\n", srv.remote, id EDB	memset(buf, 0, sizeof(buf));	PSHORT(buf+0, sizeof(buf));	/* length */	PSHORT(buf+2, 1);		/* message type */	PLONG(buf+4, Magic);		/* magic */	PSHORT(buf+8, Recho);		/* op */	PLONG(buf+12, id);		/* id */	p[16] = 1;			/* ok */	if(write(1, buf, sizeof(buf)) < sizeof(buf))		myfatal("write failed: %r");	return 16;}intscallout(uchar *p, int n){	int id, serial;	int minbps, maxbps, bearer, frame;	int window, delay;	int nphone;	char phone[64], sub[64], buf[32];	Call *c;	if(n < 168)		return 0;	if(!srv.start)		myfatal("%I: did not recieve start message", srv.remote);		id = GSHORT(p+12);	serial = GSHORT(p+14);	minbps = GLONG(p+16);	maxbps = GLONG(p+20);	bearer = GLONG(p+24);	frame = GLONG(p+28);	window = GSHORT(p+32);	delay = GSHORT(p+34);	nphone = GSHORT(p+36);	GSTRING(phone, p+40, 64);	GSTRING(sub, p+104, 64);	SDB "%I: callout id = %d serial = %d bps=[%d,%d] b=%x f=%x win = %d delay = %d np=%d phone=%s sub=%s\n",		srv.remote, id, serial, minbps, maxbps, bearer, frame, window, delay, nphone, phone, sub EDB	c = callalloc(id);	c->sendwindow = window;	c->delay = delay;	c->pac = 1;	c->recvwindow = srv.recvwindow;	memset(buf, 0, sizeof(buf));	PSHORT(buf+0, sizeof(buf));	/* length */	PSHORT(buf+2, 1);		/* message type */	PLONG(buf+4, Magic);		/* magic */	PSHORT(buf+8, Rcallout);	/* op */	PSHORT(buf+12, id);		/* call id */	PSHORT(buf+14, id);		/* peer id */	buf[16] = 1;			/* ok */	PLONG(buf+20, 10000000);	/* speed */	PSHORT(buf+24, c->recvwindow);	/* window size */	PSHORT(buf+26, 0);		/* delay */	PLONG(buf+28, 0);		/* channel id */		if(write(1, buf, sizeof(buf)) < sizeof(buf))		myfatal("write failed: %r");	return 168;}intscallreq(uchar *p, int n){	USED(p);	USED(n);	myfatal("callreq: not done yet");	return 0;}intscallcon(uchar *p, int n){	USED(p);	USED(n);	myfatal("callcon: not done yet");	return 0;}intscallclear(uchar *p, int n){	Call *c;	int id;	uchar buf[148];	if(n < 16)		return 0;	id = GSHORT(p+12);		SDB "%I: callclear id=%d\n", srv.remote, id EDB		if(c = calllookup(id)) {		callclose(c);		callfree(c);	}	memset(buf, 0, sizeof(buf));	PSHORT(buf+0, sizeof(buf));	/* length */	PSHORT(buf+2, 1);		/* message type */	PLONG(buf+4, Magic);		/* magic */	PSHORT(buf+8, Acalldis);	/* op */	PSHORT(buf+12, id);		/* id */	buf[14] = 3;			/* reply to callclear */	if(write(1, buf, sizeof(buf)) < sizeof(buf))		myfatal("write failed: %r");	return 16;}intscalldis(uchar *p, int n){	Call *c;	int id, res;	if(n < 148)		return 0;	id = GSHORT(p+12);	res = p[14];	SDB "%I: calldis id=%d res=%d\n", srv.remote, id, res EDB	if(c = calllookup(id)) {		callclose(c);		callfree(c);	}	return 148;}intswaninfo(uchar *p, int n){	Call *c;	int id;	if(n < 40)		return 0;		id = GSHORT(p+12);	SDB "%I: waninfo id = %d\n", srv.remote, id EDB		c = calllookup(id);	if(c != 0) {		c->err.crc = GLONG(p+16);		c->err.frame = GLONG(p+20);		c->err.hardware = GLONG(p+24);		c->err.overrun = GLONG(p+28);		c->err.timeout = GLONG(p+32);		c->err.align = GLONG(p+36);		callfree(c);	}		return 40;}intslinkinfo(uchar *p, int n){	Call *c;	int id;	int sendaccm, recvaccm;	if(n < 24)		return 0;	id = GSHORT(p+12);	sendaccm = GLONG(p+16);	recvaccm = GLONG(p+20);	SDB "%I: linkinfo id=%d saccm=%ux raccm=%ux\n", srv.remote, id, sendaccm, recvaccm EDB	if(c = calllookup(id)) {		c->sendaccm = sendaccm;		c->recvaccm = recvaccm;		callfree(c);	}		return 24;}Call*callalloc(int id){	uint h;	Call *c;	char buf[300], *argv[30], local[20], remote[20], **p;	int fd, pfd[2], n;	h = id%Nhash;	qlock(&srv.lk);	for(c=srv.hash[h]; c; c=c->next)		if(c->id == id)			myfatal("callalloc: duplicate id: %d", id);	c = emallocz(sizeof(Call));	c->ref = 1;	c->id = id;	c->sendaccm = ~0;	c->recvaccm = ~0;	if(!ipaddralloc(c))		myfatal("callalloc: could not alloc remote ip address");	if(pipe(pfd) < 0)		myfatal("callalloc: pipe failed: %r");	sprint(buf, "%s/ipifc/clone", srv.pppdir);	fd = open(buf, OWRITE);	if(fd < 0)		myfatal("callalloc: could not open %s: %r", buf);	n = sprint(buf, "iprouting");	if(write(fd, buf, n) < n)		myfatal("callalloc: write to ifc failed: %r");	close(fd);	p = argv;	*p++ = srv.pppexec;	*p++ = "-SC";	*p++ = "-x";	*p++ = srv.pppdir;	if(debug)		*p++ = "-d";	sprint(local, "%I", srv.ipaddr);	*p++ = local;	sprint(remote, "%I", c->remoteip);	*p++ = remote;	*p = 0;

⌨️ 快捷键说明

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