xref: /plan9/sys/src/cmd/ip/ppp/ppp.c (revision 4f81ea256c7fac55da779894b772fbf5203568fa)
1 /*
2  * ppp - point-to-point protocol, rfc1331
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <auth.h>
7 #include <bio.h>
8 #include <ip.h>
9 #include <libsec.h>
10 #include <ndb.h>
11 #include "ppp.h"
12 
13 #define PATH 128
14 
15 static	int	baud;
16 static	int	nocompress;
17 static 	int	pppframing = 1;
18 static	int	noipcompress;
19 static	int	server;
20 static	int noauth;
21 static	int	nip;		/* number of ip interfaces */
22 static	int	dying;		/* flag to signal to all threads its time to go */
23 static	int	primary;	/* this is the primary IP interface */
24 static	char	*chatfile;
25 
26 int	debug;
27 char*	LOG = "ppp";
28 char*	keyspec = "";
29 
30 enum
31 {
32 	Rmagic=	0x12345
33 };
34 
35 /*
36  * Calculate FCS - rfc 1331
37  */
38 ushort fcstab[256] =
39 {
40       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
41       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
42       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
43       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
44       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
45       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
46       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
47       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
48       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
49       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
50       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
51       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
52       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
53       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
54       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
55       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
56       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
57       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
58       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
59       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
60       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
61       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
62       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
63       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
64       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
65       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
66       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
67       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
68       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
69       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
70       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
71       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
72 };
73 
74 static char *snames[] =
75 {
76 	"Sclosed",
77 	"Sclosing",
78 	"Sreqsent",
79 	"Sackrcvd",
80 	"Sacksent",
81 	"Sopened",
82 };
83 
84 static	void		authtimer(PPP*);
85 static	void		chapinit(PPP*);
86 static	void		config(PPP*, Pstate*, int);
87 static	uchar*		escapeuchar(PPP*, ulong, uchar*, ushort*);
88 static	void		getchap(PPP*, Block*);
89 static	Block*		getframe(PPP*, int*);
90 static	void		getlqm(PPP*, Block*);
91 static	int		getopts(PPP*, Pstate*, Block*);
92 static	void		getpap(PPP*, Block*);
93 static	void		init(PPP*);
94 static	void		invalidate(Ipaddr);
95 static	void		ipinproc(PPP*);
96 static	char*		ipopen(PPP*);
97 static	void		mediainproc(PPP*);
98 static	void		newstate(PPP*, Pstate*, int);
99 static	int		nipifcs(char*);
100 static	void		papinit(PPP*);
101 static	void		pinit(PPP*, Pstate*);
102 static	void		ppptimer(PPP*);
103 static	void		printopts(Pstate*, Block*, int);
104 static	void		ptimer(PPP*, Pstate*);
105 static	int		putframe(PPP*, int, Block*);
106 static	void		putlqm(PPP*);
107 static	void		putndb(PPP*, char*);
108 static	void		putpaprequest(PPP*);
109 static	void		rcv(PPP*, Pstate*, Block*);
110 static	void		rejopts(PPP*, Pstate*, Block*, int);
111 static	void		sendechoreq(PPP*, Pstate*);
112 static	void		sendtermreq(PPP*, Pstate*);
113 static	void		setphase(PPP*, int);
114 static	void		terminate(PPP*, int);
115 static	int		validv4(Ipaddr);
116 static  void		dmppkt(char *s, uchar *a, int na);
117 static	void		getauth(PPP*);
118 
119 void
pppopen(PPP * ppp,int mediain,int mediaout,char * net,Ipaddr ipaddr,Ipaddr remip,int mtu,int framing)120 pppopen(PPP *ppp, int mediain, int mediaout, char *net,
121 	Ipaddr ipaddr, Ipaddr remip,
122 	int mtu, int framing)
123 {
124 	ppp->ipfd = -1;
125 	ppp->ipcfd = -1;
126 	invalidate(ppp->remote);
127 	invalidate(ppp->local);
128 	invalidate(ppp->curremote);
129 	invalidate(ppp->curlocal);
130 	invalidate(ppp->dns[0]);
131 	invalidate(ppp->dns[1]);
132 	invalidate(ppp->wins[0]);
133 	invalidate(ppp->wins[1]);
134 
135 	ppp->mediain = mediain;
136 	ppp->mediaout = mediaout;
137 	if(validv4(remip)){
138 		ipmove(ppp->remote, remip);
139 		ppp->remotefrozen = 1;
140 	}
141 	if(validv4(ipaddr)){
142 		ipmove(ppp->local, ipaddr);
143 		ppp->localfrozen = 1;
144 	}
145 	ppp->mtu = Defmtu;
146 	ppp->mru = mtu;
147 	ppp->framing = framing;
148 	ppp->net = net;
149 
150 	init(ppp);
151 	switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
152 	case -1:
153 		sysfatal("forking mediainproc");
154 	case 0:
155 		mediainproc(ppp);
156 		terminate(ppp, 1);
157 		_exits(0);
158 	}
159 }
160 
161 static void
init(PPP * ppp)162 init(PPP* ppp)
163 {
164 	if(ppp->inbuf == nil){
165 		ppp->inbuf = allocb(4096);
166 		if(ppp->inbuf == nil)
167 			abort();
168 
169 		ppp->outbuf = allocb(4096);
170 		if(ppp->outbuf == nil)
171 			abort();
172 
173 		ppp->lcp = mallocz(sizeof(*ppp->lcp), 1);
174 		if(ppp->lcp == nil)
175 			abort();
176 		ppp->lcp->proto = Plcp;
177 		ppp->lcp->state = Sclosed;
178 
179 		ppp->ccp = mallocz(sizeof(*ppp->ccp), 1);
180 		if(ppp->ccp == nil)
181 			abort();
182 		ppp->ccp->proto = Pccp;
183 		ppp->ccp->state = Sclosed;
184 
185 		ppp->ipcp = mallocz(sizeof(*ppp->ipcp), 1);
186 		if(ppp->ipcp == nil)
187 			abort();
188 		ppp->ipcp->proto = Pipcp;
189 		ppp->ipcp->state = Sclosed;
190 
191 		ppp->chap = mallocz(sizeof(*ppp->chap), 1);
192 		if(ppp->chap == nil)
193 			abort();
194 		ppp->chap->proto = APmschap;
195 		ppp->chap->state = Cunauth;
196 		auth_freechal(ppp->chap->cs);
197 		ppp->chap->cs = nil;
198 
199 		switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
200 		case -1:
201 			sysfatal("forking ppptimer");
202 		case 0:
203 			ppptimer(ppp);
204 			_exits(0);
205 		}
206 	}
207 
208 	ppp->ctcp = compress_init(ppp->ctcp);
209 	pinit(ppp, ppp->lcp);
210 	setphase(ppp, Plink);
211 }
212 
213 static void
setphase(PPP * ppp,int phase)214 setphase(PPP *ppp, int phase)
215 {
216 	int oldphase;
217 
218 	oldphase = ppp->phase;
219 
220 	ppp->phase = phase;
221 	switch(phase){
222 	default:
223 		sysfatal("ppp: unknown phase %d", phase);
224 	case Pdead:
225 		/* restart or exit? */
226 		pinit(ppp, ppp->lcp);
227 		setphase(ppp, Plink);
228 		break;
229 	case Plink:
230 		/* link down */
231 		switch(oldphase) {
232 		case Pauth:
233 			auth_freechal(ppp->chap->cs);
234 			ppp->chap->cs = nil;
235 			ppp->chap->state = Cunauth;
236 			break;
237 		case Pnet:
238 			auth_freechal(ppp->chap->cs);
239 			ppp->chap->cs = nil;
240 			ppp->chap->state = Cunauth;
241 			newstate(ppp, ppp->ccp, Sclosed);
242 			newstate(ppp, ppp->ipcp, Sclosed);
243 		}
244 		break;
245 	case Pauth:
246 		if(server)
247 			chapinit(ppp);
248 		else if(ppp->chap->proto == APpasswd)
249 			papinit(ppp);
250 		else
251 			setphase(ppp, Pnet);
252 		break;
253 	case Pnet:
254 		pinit(ppp, ppp->ccp);
255 		pinit(ppp, ppp->ipcp);
256 		break;
257 	case Pterm:
258 		/* what? */
259 		break;
260 	}
261 }
262 
263 static void
pinit(PPP * ppp,Pstate * p)264 pinit(PPP *ppp, Pstate *p)
265 {
266 	p->timeout = 0;
267 
268 	switch(p->proto){
269 	case Plcp:
270 		ppp->magic = truerand();
271 		ppp->xctlmap = 0xffffffff;
272 		ppp->period = 0;
273 		p->optmask = 0xffffffff;
274 		if(!server)
275 			p->optmask &=  ~(Fauth|Fmtu);
276 		ppp->rctlmap = 0;
277 		ppp->ipcp->state = Sclosed;
278 		ppp->ipcp->optmask = 0xffffffff;
279 
280 		p->echotimeout = 0;
281 
282 		/* quality goo */
283 		ppp->timeout = 0;
284 		memset(&ppp->in, 0, sizeof(ppp->in));
285 		memset(&ppp->out, 0, sizeof(ppp->out));
286 		memset(&ppp->pin, 0, sizeof(ppp->pin));
287 		memset(&ppp->pout, 0, sizeof(ppp->pout));
288 		memset(&ppp->sin, 0, sizeof(ppp->sin));
289 		break;
290 	case Pccp:
291 		if(nocompress)
292 			p->optmask = 0;
293 		else
294 			p->optmask = Fcmppc;
295 
296 		if(ppp->ctype != nil)
297 			(*ppp->ctype->fini)(ppp->cstate);
298 		ppp->ctype = nil;
299 		ppp->ctries = 0;
300 		ppp->cstate = nil;
301 
302 		if(ppp->unctype)
303 			(*ppp->unctype->fini)(ppp->uncstate);
304 		ppp->unctype = nil;
305 		ppp->uncstate = nil;
306 		break;
307 	case Pipcp:
308 		p->optmask = 0xffffffff;
309 		ppp->ctcp = compress_init(ppp->ctcp);
310 		break;
311 	}
312 	p->confid = p->rcvdconfid = -1;
313 	config(ppp, p, 1);
314 	newstate(ppp, p, Sreqsent);
315 }
316 
317 /*
318  *  change protocol to a new state.
319  */
320 static void
newstate(PPP * ppp,Pstate * p,int state)321 newstate(PPP *ppp, Pstate *p, int state)
322 {
323 	char *err;
324 
325 	netlog("ppp: %ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld\n",
326 		p->proto, snames[p->state], snames[state], ppp->rctlmap,
327 		ppp->xctlmap, p->flags,
328 		ppp->mtu, ppp->mru);
329 	syslog(0, "ppp", "%ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld",
330 		p->proto, snames[p->state], snames[state], ppp->rctlmap,
331 		ppp->xctlmap, p->flags,
332 		ppp->mtu, ppp->mru);
333 
334 	if(p->proto == Plcp) {
335 		if(state == Sopened)
336 			setphase(ppp, noauth? Pnet : Pauth);
337 		else if(state == Sclosed)
338 			setphase(ppp, Pdead);
339 		else if(p->state == Sopened)
340 			setphase(ppp, Plink);
341 	}
342 
343 	if(p->proto == Pccp && state == Sopened) {
344 		if(ppp->unctype)
345 			(*ppp->unctype->fini)(ppp->uncstate);
346 		ppp->unctype = nil;
347 		ppp->uncstate = nil;
348 		if(p->optmask & Fcmppc) {
349 			ppp->unctype = &uncmppc;
350 			ppp->uncstate = (*uncmppc.init)(ppp);
351 		}
352 		if(p->optmask & Fcthwack){
353 			ppp->unctype = &uncthwack;
354 			ppp->uncstate = (*uncthwack.init)(ppp);
355 		}
356 	}
357 
358 	if(p->proto == Pipcp && state == Sopened) {
359 		if(server && !noauth && ppp->chap->state != Cauthok)
360 			abort();
361 
362 		err = ipopen(ppp);
363 		if(err != nil)
364 			sysfatal("%s", err);
365 	}
366 
367 	p->state = state;
368 }
369 
370 /* returns (protocol, information) */
371 static Block*
getframe(PPP * ppp,int * protop)372 getframe(PPP *ppp, int *protop)
373 {
374 	uchar *p, *from, *to;
375 	int n, len, proto;
376 	ulong c;
377 	ushort fcs;
378 	Block *buf, *b;
379 
380 	*protop = 0;
381 	if(ppp->framing == 0) {
382 		/* assume data is already framed */
383 		b = allocb(2000);
384 		len = b->lim - b->wptr;
385 		n = read(ppp->mediain, b->wptr, len);
386  		dmppkt("RX", b->wptr, n);
387 		if(n <= 0 || n == len){
388 			freeb(b);
389 
390 			return nil;
391 		}
392 		b->wptr += n;
393 
394 		/* should probably copy to another block if small */
395 
396 		if(pppframing && b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
397 			b->rptr += 2;
398 		proto = *b->rptr++;
399 		if((proto & 0x1) == 0)
400 			proto = (proto<<8) | *b->rptr++;
401 
402 		if(b->rptr >= b->wptr){
403 			freeb(b);
404 			return nil;
405 		}
406 
407 		ppp->in.uchars += n;
408 		ppp->in.packets++;
409 		*protop = proto;
410 		netlog("getframe 0x%x\n", proto);
411 		return b;
412 	}
413 
414 	buf = ppp->inbuf;
415 	for(;;){
416 		/* read till we hit a frame uchar or run out of room */
417 		for(p = buf->rptr; buf->wptr < buf->lim;){
418 			for(; p < buf->wptr; p++)
419 				if(*p == HDLC_frame)
420 					break;
421 			if(p != buf->wptr)
422 				break;
423 
424 			len = buf->lim - buf->wptr;
425 			n = read(ppp->mediain, buf->wptr, len);
426 			if(n <= 0){
427 				syslog(0, LOG, "medium read returns %d: %r", n);
428 				buf->wptr = buf->rptr;
429 				return nil;
430 			}
431  			dmppkt("RX", buf->wptr, n);
432 			buf->wptr += n;
433 		}
434 
435 		/* copy into block, undoing escapes, and caculating fcs */
436 		fcs = PPP_initfcs;
437 		b = allocb(p - buf->rptr);
438 		to = b->wptr;
439 		for(from = buf->rptr; from != p;){
440 			c = *from++;
441 			if(c == HDLC_esc){
442 				if(from == p)
443 					break;
444 				c = *from++ ^ 0x20;
445 			} else if((c < 0x20) && (ppp->rctlmap & (1 << c)))
446 				continue;
447 			*to++ = c;
448 			fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
449 		}
450 
451 		/* copy down what's left in buffer */
452 		p++;
453 		memmove(buf->rptr, p, buf->wptr - p);
454 		n = p - buf->rptr;
455 		buf->wptr -= n;
456 		b->wptr = to - 2;
457 
458 		/* return to caller if checksum matches */
459 		if(fcs == PPP_goodfcs){
460 			if(b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
461 				b->rptr += 2;
462 			proto = *b->rptr++;
463 			if((proto & 0x1) == 0)
464 				proto = (proto<<8) | *b->rptr++;
465 			if(b->rptr < b->wptr){
466 				ppp->in.uchars += n;
467 				ppp->in.packets++;
468 				*protop = proto;
469 				netlog("getframe 0x%x\n", proto);
470 				return b;
471 			}
472 		} else if(BLEN(b) > 0){
473 			if(ppp->ctcp)
474 				compress_error(ppp->ctcp);
475 			ppp->in.discards++;
476 			netlog("ppp: discard len %ld/%ld cksum %ux (%ux %ux %ux %ux)\n",
477 				BLEN(b), BLEN(buf), fcs, b->rptr[0],
478 				b->rptr[1], b->rptr[2], b->rptr[3]);
479 		}
480 
481 		freeb(b);
482 	}
483 }
484 
485 /* send a PPP frame */
486 static int
putframe(PPP * ppp,int proto,Block * b)487 putframe(PPP *ppp, int proto, Block *b)
488 {
489 	Block *buf;
490 	uchar *to, *from;
491 	ushort fcs;
492 	ulong ctlmap;
493 	uchar c;
494 	Block *bp;
495 
496 	ppp->out.packets++;
497 
498 	if(proto == Plcp)
499 		ctlmap = 0xffffffff;
500 	else
501 		ctlmap = ppp->xctlmap;
502 
503 	/* make sure we have head room */
504 	if(b->rptr - b->base < 4){
505 		b = padb(b, 4);
506 		b->rptr += 4;
507 	}
508 
509 	netlog("ppp: putframe 0x%ux %ld\n", proto, b->wptr-b->rptr);
510 
511 	/* add in the protocol and address, we'd better have left room */
512 	from = b->rptr;
513 	*--from = proto;
514 	if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp)
515 		*--from = proto>>8;
516 	if(pppframing && (!(ppp->lcp->flags&Fac) || proto == Plcp)){
517 		*--from = PPP_ctl;
518 		*--from = PPP_addr;
519 	}
520 
521 	qlock(&ppp->outlock);
522 	buf = ppp->outbuf;
523 
524 	if(ppp->framing == 0) {
525 		to = buf->rptr;
526 		for(bp = b; bp; bp = bp->next){
527 			if(bp != b)
528 				from = bp->rptr;
529 			memmove(to, from, bp->wptr-from);
530 			to += bp->wptr-from;
531 		}
532 	} else {
533 		/* escape and checksum the body */
534 		fcs = PPP_initfcs;
535 		to = buf->rptr;
536 
537 		/* add frame marker */
538 		*to++ = HDLC_frame;
539 
540 		for(bp = b; bp; bp = bp->next){
541 			if(bp != b)
542 				from = bp->rptr;
543 			for(; from < bp->wptr; from++){
544 				c = *from;
545 				if(c == HDLC_frame || c == HDLC_esc
546 				   || (c < 0x20 && ((1<<c) & ctlmap))){
547 					*to++ = HDLC_esc;
548 					*to++ = c ^ 0x20;
549 				} else
550 					*to++ = c;
551 				fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
552 			}
553 		}
554 
555 		/* add on and escape the checksum */
556 		fcs = ~fcs;
557 		c = fcs;
558 		if(c == HDLC_frame || c == HDLC_esc
559 		   || (c < 0x20 && ((1<<c) & ctlmap))){
560 			*to++ = HDLC_esc;
561 			*to++ = c ^ 0x20;
562 		} else
563 			*to++ = c;
564 		c = fcs>>8;
565 		if(c == HDLC_frame || c == HDLC_esc
566 		   || (c < 0x20 && ((1<<c) & ctlmap))){
567 			*to++ = HDLC_esc;
568 			*to++ = c ^ 0x20;
569 		} else
570 			*to++ = c;
571 
572 		/* add frame marker */
573 		*to++ = HDLC_frame;
574 	}
575 
576 	/* send */
577 	buf->wptr = to;
578  	dmppkt("TX", buf->rptr, BLEN(buf));
579 	if(write(ppp->mediaout, buf->rptr, BLEN(buf)) < 0){
580 		qunlock(&ppp->outlock);
581 		return -1;
582 	}
583 	ppp->out.uchars += BLEN(buf);
584 
585 	qunlock(&ppp->outlock);
586 	return 0;
587 }
588 
589 Block*
alloclcp(int code,int id,int len,Lcpmsg ** mp)590 alloclcp(int code, int id, int len, Lcpmsg **mp)
591 {
592 	Block *b;
593 	Lcpmsg *m;
594 
595 	/*
596 	 *  leave room for header
597 	 */
598 	b = allocb(len);
599 
600 	m = (Lcpmsg*)b->wptr;
601 	m->code = code;
602 	m->id = id;
603 	b->wptr += 4;
604 
605 	*mp = m;
606 	return b;
607 }
608 
609 
610 static void
putlo(Block * b,int type,ulong val)611 putlo(Block *b, int type, ulong val)
612 {
613 	*b->wptr++ = type;
614 	*b->wptr++ = 6;
615 	hnputl(b->wptr, val);
616 	b->wptr += 4;
617 }
618 
619 static void
putv4o(Block * b,int type,Ipaddr val)620 putv4o(Block *b, int type, Ipaddr val)
621 {
622 	*b->wptr++ = type;
623 	*b->wptr++ = 6;
624 	v6tov4(b->wptr, val);
625 	b->wptr += 4;
626 }
627 
628 static void
putso(Block * b,int type,ulong val)629 putso(Block *b, int type, ulong val)
630 {
631 	*b->wptr++ = type;
632 	*b->wptr++ = 4;
633 	hnputs(b->wptr, val);
634 	b->wptr += 2;
635 }
636 
637 static void
puto(Block * b,int type)638 puto(Block *b, int type)
639 {
640 	*b->wptr++ = type;
641 	*b->wptr++ = 2;
642 }
643 
644 /*
645  *  send configuration request
646  */
647 static void
config(PPP * ppp,Pstate * p,int newid)648 config(PPP *ppp, Pstate *p, int newid)
649 {
650 	Block *b;
651 	Lcpmsg *m;
652 	int id;
653 
654 	if(newid){
655 		id = p->id++;
656 		p->confid = id;
657 		p->timeout = Timeout;
658 	} else
659 		id = p->confid;
660 	b = alloclcp(Lconfreq, id, 256, &m);
661 	USED(m);
662 
663 	switch(p->proto){
664 	case Plcp:
665 		if(p->optmask & Fctlmap)
666 			putlo(b, Octlmap, 0);	/* we don't want anything escaped */
667 		if(p->optmask & Fmagic)
668 			putlo(b, Omagic, ppp->magic);
669 		if(p->optmask & Fmtu)
670 			putso(b, Omtu, ppp->mru);
671 		if(p->optmask & Fauth) {
672 			*b->wptr++ = Oauth;
673 			*b->wptr++ = 5;
674 			hnputs(b->wptr, Pchap);
675 			b->wptr += 2;
676 			*b->wptr++ = ppp->chap->proto;
677 		}
678 		if(p->optmask & Fpc)
679 			puto(b, Opc);
680 		if(p->optmask & Fac)
681 			puto(b, Oac);
682 		break;
683 	case Pccp:
684 		if(p->optmask & Fcthwack)
685 			puto(b, Octhwack);
686 		else if(p->optmask & Fcmppc) {
687 			*b->wptr++ = Ocmppc;
688 			*b->wptr++ = 6;
689 			*b->wptr++ = 0;
690 			*b->wptr++ = 0;
691 			*b->wptr++ = 0;
692 			*b->wptr++ = 0x41;
693 		}
694 		break;
695 	case Pipcp:
696 		if(p->optmask & Fipaddr)
697 {syslog(0, "ppp", "requesting %I", ppp->local);
698 			putv4o(b, Oipaddr, ppp->local);
699 }
700 		if(primary && (p->optmask & Fipdns))
701 			putv4o(b, Oipdns, ppp->dns[0]);
702 		if(primary && (p->optmask & Fipdns2))
703 			putv4o(b, Oipdns2, ppp->dns[1]);
704 		if(primary && (p->optmask & Fipwins))
705 			putv4o(b, Oipwins, ppp->wins[0]);
706 		if(primary && (p->optmask & Fipwins2))
707 			putv4o(b, Oipwins2, ppp->wins[1]);
708 		/*
709 		 * don't ask for header compression while data compression is still pending.
710 		 * perhaps we should restart ipcp negotiation if compression negotiation fails.
711 		 */
712 		if(!noipcompress && !ppp->ccp->optmask && (p->optmask & Fipcompress)) {
713 			*b->wptr++ = Oipcompress;
714 			*b->wptr++ = 6;
715 			hnputs(b->wptr, Pvjctcp);
716 			b->wptr += 2;
717 			*b->wptr++ = MAX_STATES-1;
718 			*b->wptr++ = 1;
719 		}
720 		break;
721 	}
722 	hnputs(m->len, BLEN(b));
723 	printopts(p, b, 1);
724 	putframe(ppp, p->proto, b);
725 	freeb(b);
726 }
727 
728 static void
getipinfo(PPP * ppp)729 getipinfo(PPP *ppp)
730 {
731 	char *av[3];
732 	int ndns, nwins;
733 	char ip[64];
734 	Ndbtuple *t, *nt;
735 
736 	if(!validv4(ppp->local))
737 		return;
738 
739 	av[0] = "dns";
740 	av[1] = "wins";
741 	sprint(ip, "%I", ppp->local);
742 	t = csipinfo(ppp->net, "ip", ip, av, 2);
743 	ndns = nwins = 0;
744 	for(nt = t; nt != nil; nt = nt->entry){
745 		if(strcmp(nt->attr, "dns") == 0){
746 			if(ndns < 2)
747 				parseip(ppp->dns[ndns++], nt->val);
748 		} else if(strcmp(nt->attr, "wins") == 0){
749 			if(nwins < 2)
750 				parseip(ppp->wins[nwins++], nt->val);
751 		}
752 	}
753 	if(t != nil)
754 		ndbfree(t);
755 }
756 
757 /*
758  *  parse configuration request, sends an ack or reject packet
759  *
760  *	returns:	-1 if request was syntacticly incorrect
761  *			 0 if packet was accepted
762  *			 1 if packet was rejected
763  */
764 static int
getopts(PPP * ppp,Pstate * p,Block * b)765 getopts(PPP *ppp, Pstate *p, Block *b)
766 {
767 	Lcpmsg *m, *repm;
768 	Lcpopt *o;
769 	uchar *cp, *ap;
770 	ulong rejecting, nacking, flags, proto, chapproto;
771 	ulong mtu, ctlmap, period;
772 	ulong x;
773 	Block *repb;
774 	Comptype *ctype;
775 	Ipaddr ipaddr;
776 
777 	rejecting = 0;
778 	nacking = 0;
779 	flags = 0;
780 
781 	/* defaults */
782 	invalidate(ipaddr);
783 	mtu = ppp->mtu;
784 	ctlmap = 0xffffffff;
785 	period = 0;
786 	ctype = nil;
787 	chapproto = 0;
788 
789 	m = (Lcpmsg*)b->rptr;
790 	repb = alloclcp(Lconfack, m->id, BLEN(b), &repm);
791 
792 	/* copy options into ack packet */
793 	memmove(repm->data, m->data, b->wptr - m->data);
794 	repb->wptr += b->wptr - m->data;
795 
796 	/* look for options we don't recognize or like */
797 	for(cp = m->data; cp < b->wptr; cp += o->len){
798 		o = (Lcpopt*)cp;
799 		if(cp + o->len > b->wptr || o->len==0){
800 			freeb(repb);
801 			netlog("ppp: bad option length %ux\n", o->type);
802 			return -1;
803 		}
804 
805 		switch(p->proto){
806 		case Plcp:
807 			switch(o->type){
808 			case Oac:
809 				flags |= Fac;
810 				continue;
811 			case Opc:
812 				flags |= Fpc;
813 				continue;
814 			case Omtu:
815 				mtu = nhgets(o->data);
816 				continue;
817 			case Omagic:
818 				if(ppp->magic == nhgetl(o->data))
819 					netlog("ppp: possible loop\n");
820 				continue;
821 			case Octlmap:
822 				ctlmap = nhgetl(o->data);
823 				continue;
824 			case Oquality:
825 				proto = nhgets(o->data);
826 				if(proto != Plqm)
827 					break;
828 				x = nhgetl(o->data+2)*10;
829 				period = (x+Period-1)/Period;
830 				continue;
831 			case Oauth:
832 				proto = nhgets(o->data);
833 				if(proto == Ppasswd && !server){
834 					chapproto = APpasswd;
835 					continue;
836 				}
837 				if(proto != Pchap)
838 					break;
839 				if(o->data[2] != APmd5 && o->data[2] != APmschap)
840 					break;
841 				chapproto = o->data[2];
842 				continue;
843 			}
844 			break;
845 		case Pccp:
846 			if(nocompress)
847 				break;
848 			switch(o->type){
849 			case Octhwack:
850 				break;
851 			/*
852 				if(o->len == 2){
853 					ctype = &cthwack;
854 					continue;
855 				}
856 				if(!nacking){
857 					nacking = 1;
858 					repb->wptr = repm->data;
859 					repm->code = Lconfnak;
860 				}
861 				puto(repb, Octhwack);
862 				continue;
863 			*/
864 			case Ocmppc:
865 				x = nhgetl(o->data);
866 
867 				// hack for Mac
868 				// if(x == 0)
869 				//	continue;
870 
871 				/* stop ppp loops */
872 				if((x&0x41) == 0 || ppp->ctries++ > 5) {
873 					/*
874 					 * turn off requests as well - I don't think this
875 					 * is needed in the standard
876 					 */
877 					p->optmask &= ~Fcmppc;
878 					break;
879 				}
880 				if(rejecting)
881 					continue;
882 				if(x & 1) {
883 					ctype = &cmppc;
884 					ppp->sendencrypted = (o->data[3]&0x40) == 0x40;
885 					continue;
886 				}
887 				if(!nacking){
888 					nacking = 1;
889 					repb->wptr = repm->data;
890 					repm->code = Lconfnak;
891 				}
892 				*repb->wptr++ = Ocmppc;
893 				*repb->wptr++ = 6;
894 				*repb->wptr++ = 0;
895 				*repb->wptr++ = 0;
896 				*repb->wptr++ = 0;
897 				*repb->wptr++ = 0x41;
898 				continue;
899 			}
900 			break;
901 		case Pipcp:
902 			switch(o->type){
903 			case Oipaddr:
904 				v4tov6(ipaddr, o->data);
905 				if(!validv4(ppp->remote))
906 					continue;
907 				if(!validv4(ipaddr) && !rejecting){
908 					/* other side requesting an address */
909 					if(!nacking){
910 						nacking = 1;
911 						repb->wptr = repm->data;
912 						repm->code = Lconfnak;
913 					}
914 					putv4o(repb, Oipaddr, ppp->remote);
915 				}
916 				continue;
917 			case Oipdns:
918 				ap = ppp->dns[0];
919 				goto ipinfo;
920 			case Oipdns2:
921 				ap = ppp->dns[1];
922 				goto ipinfo;
923 			case Oipwins:
924 				ap = ppp->wins[0];
925 				goto ipinfo;
926 			case Oipwins2:
927 				ap = ppp->wins[1];
928 				goto ipinfo;
929 			ipinfo:
930 				if(!validv4(ap))
931 					getipinfo(ppp);
932 				if(!validv4(ap))
933 					break;
934 				v4tov6(ipaddr, o->data);
935 				if(!validv4(ipaddr) && !rejecting){
936 					/* other side requesting an address */
937 					if(!nacking){
938 						nacking = 1;
939 						repb->wptr = repm->data;
940 						repm->code = Lconfnak;
941 					}
942 					putv4o(repb, o->type, ap);
943 				}
944 				continue;
945 			case Oipcompress:
946 				/*
947 				 * don't compress tcp header if we've negotiated data compression.
948 				 * tcp header compression has very poor performance if there is an error.
949 				 */
950 				proto = nhgets(o->data);
951 				if(noipcompress || proto != Pvjctcp || ppp->ctype != nil)
952 					break;
953 				if(compress_negotiate(ppp->ctcp, o->data+2) < 0)
954 					break;
955 				flags |= Fipcompress;
956 				continue;
957 			}
958 			break;
959 		}
960 
961 		/* come here if option is not recognized */
962 		if(!rejecting){
963 			rejecting = 1;
964 			repb->wptr = repm->data;
965 			repm->code = Lconfrej;
966 		}
967 		netlog("ppp: bad %ux option %d\n", p->proto, o->type);
968 		memmove(repb->wptr, o, o->len);
969 		repb->wptr += o->len;
970 	}
971 
972 	/* permanent changes only after we know that we liked the packet */
973 	if(!rejecting && !nacking){
974 		switch(p->proto){
975 		case Plcp:
976 			ppp->period = period;
977 			ppp->xctlmap = ctlmap;
978 			if(mtu > Maxmtu)
979 				mtu = Maxmtu;
980 			if(mtu < Minmtu)
981 				mtu = Minmtu;
982 			ppp->mtu = mtu;
983 			if(chapproto)
984 				ppp->chap->proto = chapproto;
985 
986 			break;
987 		case Pccp:
988 			if(ppp->ctype != nil){
989 				(*ppp->ctype->fini)(ppp->cstate);
990 				ppp->cstate = nil;
991 			}
992 			ppp->ctype = ctype;
993 			if(ctype)
994 				ppp->cstate = (*ctype->init)(ppp);
995 			break;
996 		case Pipcp:
997 			if(validv4(ipaddr) && ppp->remotefrozen == 0)
998  				ipmove(ppp->remote, ipaddr);
999 			break;
1000 		}
1001 		p->flags = flags;
1002 	}
1003 
1004 	hnputs(repm->len, BLEN(repb));
1005 	printopts(p, repb, 1);
1006 	putframe(ppp, p->proto, repb);
1007 	freeb(repb);
1008 
1009 	return rejecting || nacking;
1010 }
1011 static void
dmppkt(char * s,uchar * a,int na)1012 dmppkt(char *s, uchar *a, int na)
1013 {
1014 	int i;
1015 
1016 	if (debug < 3)
1017 		return;
1018 
1019 	fprint(2, "%s", s);
1020 	for(i = 0; i < na; i++)
1021 		fprint(2, " %.2ux", a[i]);
1022 	fprint(2, "\n");
1023 }
1024 
1025 static void
dropoption(Pstate * p,Lcpopt * o)1026 dropoption(Pstate *p, Lcpopt *o)
1027 {
1028 	unsigned n = o->type;
1029 
1030 	switch(n){
1031 	case Oipaddr:
1032 		break;
1033 	case Oipdns:
1034 		p->optmask &= ~Fipdns;
1035 		break;
1036 	case Oipwins:
1037 		p->optmask &= ~Fipwins;
1038 		break;
1039 	case Oipdns2:
1040 		p->optmask &= ~Fipdns2;
1041 		break;
1042 	case Oipwins2:
1043 		p->optmask &= ~Fipwins2;
1044 		break;
1045 	default:
1046 		if(o->type < 8*sizeof(p->optmask))
1047 			p->optmask &= ~(1<<o->type);
1048 		break;
1049 	}
1050 }
1051 
1052 /*
1053  *  parse configuration rejection, just stop sending anything that they
1054  *  don't like (except for ipcp address nak).
1055  */
1056 static void
rejopts(PPP * ppp,Pstate * p,Block * b,int code)1057 rejopts(PPP *ppp, Pstate *p, Block *b, int code)
1058 {
1059 	Lcpmsg *m;
1060 	Lcpopt *o;
1061 	uchar newip[IPaddrlen];
1062 
1063 	/* just give up trying what the other side doesn't like */
1064 	m = (Lcpmsg*)b->rptr;
1065 	for(b->rptr = m->data; b->rptr < b->wptr; b->rptr += o->len){
1066 		o = (Lcpopt*)b->rptr;
1067 		if(b->rptr + o->len > b->wptr){
1068 			netlog("ppp: bad roption length %ux\n", o->type);
1069 			return;
1070 		}
1071 
1072 		if(code == Lconfrej){
1073 			dropoption(p, o);
1074 			netlog("ppp: %ux rejecting %d\n",
1075 					p->proto, o->type);
1076 			continue;
1077 		}
1078 
1079 		switch(p->proto){
1080 		case Plcp:
1081 			switch(o->type){
1082 			case Octlmap:
1083 				ppp->rctlmap = nhgetl(o->data);
1084 				break;
1085 			case Oauth:
1086 				/* don't allow client to request no auth */
1087 				/* could try different auth protocol here */
1088 				fprint(2, "ppp: can not reject CHAP\n");
1089 				exits("ppp: CHAP");
1090 				break;
1091 			default:
1092 				if(o->type < 8*sizeof(p->optmask))
1093 					p->optmask &= ~(1<<o->type);
1094 				break;
1095 			};
1096 			break;
1097 		case Pccp:
1098 			switch(o->type){
1099 			default:
1100 				dropoption(p, o);
1101 				break;
1102 			}
1103 			break;
1104 		case Pipcp:
1105 			switch(o->type){
1106 			case Oipaddr:
1107 syslog(0, "ppp", "rejected addr %I with %V", ppp->local, o->data);
1108 				/* if we're a server, don't let other end change our addr */
1109 				if(ppp->localfrozen){
1110 					dropoption(p, o);
1111 					break;
1112 				}
1113 
1114 				/* accept whatever server tells us */
1115 				if(!validv4(ppp->local)){
1116 					v4tov6(ppp->local, o->data);
1117 					dropoption(p, o);
1118 					break;
1119 				}
1120 
1121 				/* if he didn't like our addr, ask for a generic one */
1122 				v4tov6(newip, o->data);
1123 				if(!validv4(newip)){
1124 					invalidate(ppp->local);
1125 					break;
1126 				}
1127 
1128 				/* if he gives us something different, use it anyways */
1129 				v4tov6(ppp->local, o->data);
1130 				dropoption(p, o);
1131 				break;
1132 			case Oipdns:
1133 				if (!validv4(ppp->dns[0])){
1134 					v4tov6(ppp->dns[0], o->data);
1135 					dropoption(p, o);
1136 					break;
1137 				}
1138 				v4tov6(newip, o->data);
1139 				if(!validv4(newip)){
1140 					invalidate(ppp->dns[0]);
1141 					break;
1142 				}
1143 				v4tov6(ppp->dns[0], o->data);
1144 				dropoption(p, o);
1145 				break;
1146 			case Oipwins:
1147 				if (!validv4(ppp->wins[0])){
1148 					v4tov6(ppp->wins[0], o->data);
1149 					dropoption(p, o);
1150 					break;
1151 				}
1152 				v4tov6(newip, o->data);
1153 				if(!validv4(newip)){
1154 					invalidate(ppp->wins[0]);
1155 					break;
1156 				}
1157 				v4tov6(ppp->wins[0], o->data);
1158 				dropoption(p, o);
1159 				break;
1160 			case Oipdns2:
1161 				if (!validv4(ppp->dns[1])){
1162 					v4tov6(ppp->dns[1], o->data);
1163 					dropoption(p, o);
1164 					break;
1165 				}
1166 				v4tov6(newip, o->data);
1167 				if(!validv4(newip)){
1168 					invalidate(ppp->dns[1]);
1169 					break;
1170 				}
1171 				v4tov6(ppp->dns[1], o->data);
1172 				dropoption(p, o);
1173 				break;
1174 			case Oipwins2:
1175 				if (!validv4(ppp->wins[1])){
1176 					v4tov6(ppp->wins[1], o->data);
1177 					dropoption(p, o);
1178 					break;
1179 				}
1180 				v4tov6(newip, o->data);
1181 				if(!validv4(newip)){
1182 					invalidate(ppp->wins[1]);
1183 					break;
1184 				}
1185 				v4tov6(ppp->wins[1], o->data);
1186 				dropoption(p, o);
1187 				break;
1188 			default:
1189 				dropoption(p, o);
1190 				break;
1191 			}
1192 			break;
1193 		}
1194 	}
1195 }
1196 
1197 
1198 /*
1199  *  put a messages through the lcp or ipcp state machine.  They are
1200  *  very similar.
1201  */
1202 static void
rcv(PPP * ppp,Pstate * p,Block * b)1203 rcv(PPP *ppp, Pstate *p, Block *b)
1204 {
1205 	ulong len;
1206 	int err;
1207 	Lcpmsg *m;
1208 	int proto;
1209 
1210 	if(BLEN(b) < 4){
1211 		netlog("ppp: short lcp message\n");
1212 		freeb(b);
1213 		return;
1214 	}
1215 	m = (Lcpmsg*)b->rptr;
1216 	len = nhgets(m->len);
1217 	if(BLEN(b) < len){
1218 		netlog("ppp: short lcp message\n");
1219 		freeb(b);
1220 		return;
1221 	}
1222 
1223 	netlog("ppp: %ux rcv %d len %ld id %d/%d/%d\n",
1224 		p->proto, m->code, len, m->id, p->confid, p->id);
1225 
1226 	if(p->proto != Plcp && ppp->lcp->state != Sopened){
1227 		netlog("ppp: non-lcp with lcp not open\n");
1228 		freeb(b);
1229 		return;
1230 	}
1231 
1232 	qlock(ppp);
1233 	switch(m->code){
1234 	case Lconfreq:
1235 		printopts(p, b, 0);
1236 		err = getopts(ppp, p, b);
1237 		if(err < 0)
1238 			break;
1239 
1240 		if(m->id == p->rcvdconfid)
1241 			break;			/* don't change state for duplicates */
1242 
1243 		switch(p->state){
1244 		case Sackrcvd:
1245 			if(err)
1246 				break;
1247 			newstate(ppp, p, Sopened);
1248 			break;
1249 		case Sclosed:
1250 		case Sopened:
1251 			config(ppp, p, 1);
1252 			if(err == 0)
1253 				newstate(ppp, p, Sacksent);
1254 			else
1255 				newstate(ppp, p, Sreqsent);
1256 			break;
1257 		case Sreqsent:
1258 		case Sacksent:
1259 			if(err == 0)
1260 				newstate(ppp, p, Sacksent);
1261 			else
1262 				newstate(ppp, p, Sreqsent);
1263 			break;
1264 		}
1265 		break;
1266 	case Lconfack:
1267 		if(p->confid != m->id){
1268 			/* ignore if it isn't the message we're sending */
1269 			netlog("ppp: dropping confack\n");
1270 			break;
1271 		}
1272 		p->confid = -1;		/* ignore duplicates */
1273 		p->id++;		/* avoid sending duplicates */
1274 
1275 		netlog("ppp: recv confack\n");
1276 		switch(p->state){
1277 		case Sopened:
1278 		case Sackrcvd:
1279 			config(ppp, p, 1);
1280 			newstate(ppp, p, Sreqsent);
1281 			break;
1282 		case Sreqsent:
1283 			newstate(ppp, p, Sackrcvd);
1284 			break;
1285 		case Sacksent:
1286 			newstate(ppp, p, Sopened);
1287 			break;
1288 		}
1289 		break;
1290 	case Lconfrej:
1291 	case Lconfnak:
1292 		if(p->confid != m->id) {
1293 			/* ignore if it isn't the message we're sending */
1294 			netlog("ppp: dropping confrej or confnak\n");
1295 			break;
1296 		}
1297 		p->confid = -1;		/* ignore duplicates */
1298 		p->id++;		/* avoid sending duplicates */
1299 
1300 		switch(p->state){
1301 		case Sopened:
1302 		case Sackrcvd:
1303 			config(ppp, p, 1);
1304 			newstate(ppp, p, Sreqsent);
1305 			break;
1306 		case Sreqsent:
1307 		case Sacksent:
1308 			printopts(p, b, 0);
1309 			rejopts(ppp, p, b, m->code);
1310 			config(ppp, p, 1);
1311 			break;
1312 		}
1313 		break;
1314 	case Ltermreq:
1315 		m->code = Ltermack;
1316 		putframe(ppp, p->proto, b);
1317 
1318 		switch(p->state){
1319 		case Sackrcvd:
1320 		case Sacksent:
1321 			newstate(ppp, p, Sreqsent);
1322 			break;
1323 		case Sopened:
1324 			newstate(ppp, p, Sclosing);
1325 			break;
1326 		}
1327 		break;
1328 	case Ltermack:
1329 		if(p->termid != m->id)	/* ignore if it isn't the message we're sending */
1330 			break;
1331 
1332 		if(p->proto == Plcp)
1333 			ppp->ipcp->state = Sclosed;
1334 		switch(p->state){
1335 		case Sclosing:
1336 			newstate(ppp, p, Sclosed);
1337 			break;
1338 		case Sackrcvd:
1339 			newstate(ppp, p, Sreqsent);
1340 			break;
1341 		case Sopened:
1342 			config(ppp, p, 0);
1343 			newstate(ppp, p, Sreqsent);
1344 			break;
1345 		}
1346 		break;
1347 	case Lcoderej:
1348 		//newstate(ppp, p, Sclosed);
1349 		syslog(0, LOG, "code reject %d\n", m->data[0]);
1350 		break;
1351 	case Lprotorej:
1352 		proto = nhgets(m->data);
1353 		netlog("ppp: proto reject %ux\n", proto);
1354 		if(proto == Pccp)
1355 			newstate(ppp, ppp->ccp, Sclosed);
1356 		break;
1357 	case Lechoreq:
1358 		if(BLEN(b) < 8){
1359 			netlog("ppp: short lcp echo request\n");
1360 			freeb(b);
1361 			return;
1362 		}
1363 		m->code = Lechoack;
1364 		hnputl(m->data, ppp->magic);
1365 		putframe(ppp, p->proto, b);
1366 		break;
1367 	case Lechoack:
1368 		p->echoack = 1;
1369 		break;
1370 	case Ldiscard:
1371 		/* nothing to do */
1372 		break;
1373 	case Lresetreq:
1374 		if(p->proto != Pccp)
1375 			break;
1376 		ppp->stat.compreset++;
1377 		if(ppp->ctype != nil)
1378 			b = (*ppp->ctype->resetreq)(ppp->cstate, b);
1379 		if(b != nil) {
1380 			m = (Lcpmsg*)b->rptr;
1381 			m->code = Lresetack;
1382 			putframe(ppp, p->proto, b);
1383 		}
1384 		break;
1385 	case Lresetack:
1386 		if(p->proto != Pccp)
1387 			break;
1388 		if(ppp->unctype != nil)
1389 			(*ppp->unctype->resetack)(ppp->uncstate, b);
1390 		break;
1391 	}
1392 
1393 	qunlock(ppp);
1394 	freeb(b);
1395 }
1396 
1397 /*
1398  *  timer for protocol state machine
1399  */
1400 static void
ptimer(PPP * ppp,Pstate * p)1401 ptimer(PPP *ppp, Pstate *p)
1402 {
1403 	if(p->state == Sopened || p->state == Sclosed)
1404 		return;
1405 
1406 	p->timeout--;
1407 	switch(p->state){
1408 	case Sclosing:
1409 		sendtermreq(ppp, p);
1410 		break;
1411 	case Sreqsent:
1412 	case Sacksent:
1413 		if(p->timeout <= 0)
1414 			newstate(ppp, p, Sclosed);
1415 		else {
1416 			config(ppp, p, 0);
1417 		}
1418 		break;
1419 	case Sackrcvd:
1420 		if(p->timeout <= 0)
1421 			newstate(ppp, p, Sclosed);
1422 		else {
1423 			config(ppp, p, 0);
1424 			newstate(ppp, p, Sreqsent);
1425 		}
1426 		break;
1427 	}
1428 }
1429 
1430 /* paptimer -- pap timer event handler
1431  *
1432  * If PAP authorization hasn't come through, resend an authreqst.  If
1433  * the maximum number of requests have been sent (~ 30 seconds), give
1434  * up.
1435  *
1436  */
1437 static void
authtimer(PPP * ppp)1438 authtimer(PPP* ppp)
1439 {
1440 	if(ppp->chap->proto != APpasswd)
1441 		return;
1442 
1443 	if(ppp->chap->id < 21)
1444 		putpaprequest(ppp);
1445 	else {
1446 		terminate(ppp, 0);
1447 		netlog("ppp: pap timed out--not authorized\n");
1448 	}
1449 }
1450 
1451 
1452 /*
1453  *  timer for ppp
1454  */
1455 static void
ppptimer(PPP * ppp)1456 ppptimer(PPP *ppp)
1457 {
1458 	while(!dying){
1459 		sleep(Period);
1460 		qlock(ppp);
1461 
1462 		netlog("ppp: ppptimer\n");
1463 		ptimer(ppp, ppp->lcp);
1464 		if(ppp->lcp->state == Sopened) {
1465 			switch(ppp->phase){
1466 			case Pnet:
1467 				ptimer(ppp, ppp->ccp);
1468 				ptimer(ppp, ppp->ipcp);
1469 				break;
1470 			case Pauth:
1471 				authtimer(ppp);
1472 				break;
1473 			}
1474 		}
1475 
1476 		/* link quality measurement */
1477 		if(ppp->period && --(ppp->timeout) <= 0){
1478 			ppp->timeout = ppp->period;
1479 			putlqm(ppp);
1480 		}
1481 
1482 		qunlock(ppp);
1483 	}
1484 }
1485 
1486 static void
setdefroute(char * net,Ipaddr gate)1487 setdefroute(char *net, Ipaddr gate)
1488 {
1489 	int fd;
1490 	char path[128];
1491 
1492 	snprint(path, sizeof path, "%s/iproute", net);
1493 	fd = open(path, ORDWR);
1494 	if(fd < 0)
1495 		return;
1496 	fprint(fd, "add 0 0 %I", gate);
1497 	close(fd);
1498 }
1499 
1500 enum
1501 {
1502 	Mofd=	32,
1503 };
1504 struct
1505 {
1506 	Lock;
1507 
1508 	int	fd[Mofd];
1509 	int	cfd[Mofd];
1510 	int	n;
1511 } old;
1512 
1513 static char*
ipopen(PPP * ppp)1514 ipopen(PPP *ppp)
1515 {
1516 	static int ipinprocpid;
1517 	int n, cfd, fd;
1518 	char path[128];
1519 	char buf[128];
1520 
1521 	if(ipinprocpid <= 0){
1522 		snprint(path, sizeof path, "%s/ipifc/clone", ppp->net);
1523 		cfd = open(path, ORDWR);
1524 		if(cfd < 0)
1525 			return "can't open ip interface";
1526 
1527 		n = read(cfd, buf, sizeof(buf) - 1);
1528 		if(n <= 0){
1529 			close(cfd);
1530 			return "can't open ip interface";
1531 		}
1532 		buf[n] = 0;
1533 
1534 		netlog("ppp: setting up IP interface local %I remote %I (valid %d)\n",
1535 			ppp->local, ppp->remote, validv4(ppp->remote));
1536 		if(!validv4(ppp->remote))
1537 			ipmove(ppp->remote, ppp->local);
1538 
1539 		snprint(path, sizeof path, "%s/ipifc/%s/data", ppp->net, buf);
1540 		fd = open(path, ORDWR);
1541 		if(fd < 0){
1542 			close(cfd);
1543 			return "can't open ip interface";
1544 		}
1545 
1546 		if(fprint(cfd, "bind pkt") < 0)
1547 			return "binding pkt to ip interface";
1548 		if(fprint(cfd, "add %I 255.255.255.255 %I %lud proxy", ppp->local,
1549 			ppp->remote, ppp->mtu-10) < 0){
1550 			close(cfd);
1551 			return "can't set addresses";
1552 		}
1553 		if(primary)
1554 			setdefroute(ppp->net, ppp->remote);
1555 		ppp->ipfd = fd;
1556 		ppp->ipcfd = cfd;
1557 
1558 		/* signal main() that ip is configured */
1559 		rendezvous((void*)Rmagic, 0);
1560 
1561 		switch(ipinprocpid = rfork(RFPROC|RFMEM|RFNOWAIT)){
1562 		case -1:
1563 			sysfatal("forking ipinproc");
1564 		case 0:
1565 			ipinproc(ppp);
1566 			terminate(ppp, 1);
1567 			_exits(0);
1568 		}
1569 	} else {
1570 		/* we may have changed addresses */
1571 		if(ipcmp(ppp->local, ppp->curlocal) != 0 ||
1572 		   ipcmp(ppp->remote, ppp->curremote) != 0){
1573 			snprint(buf, sizeof buf, "remove %I 255.255.255.255 %I",
1574 			    ppp->curlocal, ppp->curremote);
1575 			if(fprint(ppp->ipcfd, "%s", buf) < 0)
1576 				syslog(0, "ppp", "can't %s: %r", buf);
1577 			snprint(buf, sizeof buf, "add %I 255.255.255.255 %I %lud proxy",
1578 			    ppp->local, ppp->remote, ppp->mtu-10);
1579 			if(fprint(ppp->ipcfd, "%s", buf) < 0)
1580 				syslog(0, "ppp", "can't %s: %r", buf);
1581 		}
1582 		syslog(0, "ppp", "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,
1583 		   ppp->local, ppp->remote);
1584 	}
1585 	ipmove(ppp->curlocal, ppp->local);
1586 	ipmove(ppp->curremote, ppp->remote);
1587 
1588 	return nil;
1589 }
1590 
1591 /* return next input IP packet */
1592 Block*
pppread(PPP * ppp)1593 pppread(PPP *ppp)
1594 {
1595 	Block *b, *reply;
1596 	int proto, len;
1597 	Lcpmsg *m;
1598 
1599 	while(!dying){
1600 		b = getframe(ppp, &proto);
1601 		if(b == nil)
1602 			return nil;
1603 
1604 Again:
1605 		switch(proto){
1606 		case Plcp:
1607 			rcv(ppp, ppp->lcp, b);
1608 			break;
1609 		case Pccp:
1610 			rcv(ppp, ppp->ccp, b);
1611 			break;
1612 		case Pipcp:
1613 			rcv(ppp, ppp->ipcp, b);
1614 			break;
1615 		case Pip:
1616 			if(ppp->ipcp->state == Sopened)
1617 				return b;
1618 			netlog("ppp: IP recved: link not up\n");
1619 			freeb(b);
1620 			break;
1621 		case Plqm:
1622 			getlqm(ppp, b);
1623 			break;
1624 		case Pchap:
1625 			getchap(ppp, b);
1626 			break;
1627 		case Ppasswd:
1628 			getpap(ppp, b);
1629 			break;
1630 		case Pvjctcp:
1631 		case Pvjutcp:
1632 			if(ppp->ipcp->state != Sopened){
1633 				netlog("ppp: VJ tcp recved: link not up\n");
1634 				freeb(b);
1635 				break;
1636 			}
1637 			ppp->stat.vjin++;
1638 			b = tcpuncompress(ppp->ctcp, b, proto);
1639 			if(b != nil)
1640 				return b;
1641 			ppp->stat.vjfail++;
1642 			break;
1643 		case Pcdata:
1644 			ppp->stat.uncomp++;
1645 			if(ppp->ccp->state != Sopened){
1646 				netlog("ppp: compressed data recved: link not up\n");
1647 				freeb(b);
1648 				break;
1649 			}
1650 			if(ppp->unctype == nil) {
1651 				netlog("ppp: compressed data recved: no compression\n");
1652 				freeb(b);
1653 				break;
1654 			}
1655 			len = BLEN(b);
1656 			b = (*ppp->unctype->uncompress)(ppp, b, &proto, &reply);
1657 			if(reply != nil){
1658 				/* send resetreq */
1659 				ppp->stat.uncompreset++;
1660 				putframe(ppp, Pccp, reply);
1661 				freeb(reply);
1662 			}
1663 			if(b == nil)
1664 				break;
1665 			ppp->stat.uncompin += len;
1666 			ppp->stat.uncompout += BLEN(b);
1667 /* netlog("ppp: uncompressed frame %ux %d %d (%d uchars)\n", proto, b->rptr[0], b->rptr[1], BLEN(b)); /* */
1668 			goto Again;
1669 		default:
1670 			syslog(0, LOG, "unknown proto %ux", proto);
1671 			if(ppp->lcp->state == Sopened){
1672 				/* reject the protocol */
1673 				b->rptr -= 6;
1674 				m = (Lcpmsg*)b->rptr;
1675 				m->code = Lprotorej;
1676 				m->id = ++ppp->lcp->id;
1677 				hnputs(m->data, proto);
1678 				hnputs(m->len, BLEN(b));
1679 				putframe(ppp, Plcp, b);
1680 			}
1681 			freeb(b);
1682 			break;
1683 		}
1684 	}
1685 	return nil;
1686 }
1687 
1688 /* transmit an IP packet */
1689 int
pppwrite(PPP * ppp,Block * b)1690 pppwrite(PPP *ppp, Block *b)
1691 {
1692 	int proto;
1693 	int len;
1694 
1695 	qlock(ppp);
1696 	/* can't send ip packets till we're established */
1697 	if(ppp->ipcp->state != Sopened) {
1698 		qunlock(ppp);
1699 		syslog(0, LOG, "IP write: link not up");
1700 		len = blen(b);
1701 		freeb(b);
1702 		return len;
1703 	}
1704 
1705 	proto = Pip;
1706 	ppp->stat.ipsend++;
1707 
1708 	if(ppp->ipcp->flags & Fipcompress){
1709 		b = compress(ppp->ctcp, b, &proto);
1710 		if(b == nil){
1711 			qunlock(ppp);
1712 			return 0;
1713 		}
1714 		if(proto != Pip)
1715 			ppp->stat.vjout++;
1716 	}
1717 
1718 	if(ppp->ctype != nil) {
1719 		len = blen(b);
1720 		b = (*ppp->ctype->compress)(ppp, proto, b, &proto);
1721 		if(proto == Pcdata) {
1722 			ppp->stat.comp++;
1723 			ppp->stat.compin += len;
1724 			ppp->stat.compout += blen(b);
1725 		}
1726 	}
1727 
1728 	if(putframe(ppp, proto, b) < 0) {
1729 		qunlock(ppp);
1730 		freeb(b);
1731 		return -1;
1732 	}
1733 	qunlock(ppp);
1734 
1735 	len = blen(b);
1736 	freeb(b);
1737 	return len;
1738 }
1739 
1740 static void
terminate(PPP * ppp,int kill)1741 terminate(PPP *ppp, int kill)
1742 {
1743 	close(ppp->ipfd);
1744 	ppp->ipfd = -1;
1745 	close(ppp->ipcfd);
1746 	ppp->ipcfd = -1;
1747 	close(ppp->mediain);
1748 	close(ppp->mediaout);
1749 	ppp->mediain = -1;
1750 	ppp->mediaout = -1;
1751 	dying = 1;
1752 
1753 	if(kill)
1754 		postnote(PNGROUP, getpid(), "die");
1755 }
1756 
1757 typedef struct Iphdr Iphdr;
1758 struct Iphdr
1759 {
1760 	uchar	vihl;		/* Version and header length */
1761 	uchar	tos;		/* Type of service */
1762 	uchar	length[2];	/* packet length */
1763 	uchar	id[2];		/* Identification */
1764 	uchar	frag[2];	/* Fragment information */
1765 	uchar	ttl;		/* Time to live */
1766 	uchar	proto;		/* Protocol */
1767 	uchar	cksum[2];	/* Header checksum */
1768 	uchar	src[4];		/* Ip source (uchar ordering unimportant) */
1769 	uchar	dst[4];		/* Ip destination (uchar ordering unimportant) */
1770 };
1771 
1772 static void
ipinproc(PPP * ppp)1773 ipinproc(PPP *ppp)
1774 {
1775 	Block *b;
1776 	int m, n;
1777 	Iphdr *ip;
1778 
1779 	while(!dying){
1780 
1781 		b = allocb(Buflen);
1782 		n = read(ppp->ipfd, b->wptr, b->lim-b->wptr);
1783 		if(n < 0)
1784 			break;
1785 
1786 		/* trim packet if there's padding (e.g. from ether) */
1787 		ip = (Iphdr*)b->rptr;
1788 		m = nhgets(ip->length);
1789 		if(m < n && m > 0)
1790 			n = m;
1791 		b->wptr += n;
1792 
1793 		if(pppwrite(ppp, b) < 0)
1794 			break;
1795 	}
1796 }
1797 
1798 static void
catchdie(void *,char * msg)1799 catchdie(void*, char *msg)
1800 {
1801 	if(strstr(msg, "die") != nil)
1802 		noted(NCONT);
1803 	else
1804 		noted(NDFLT);
1805 }
1806 
1807 static void
hexdump(uchar * a,int na)1808 hexdump(uchar *a, int na)
1809 {
1810 	int i;
1811 	char buf[80];
1812 
1813 	fprint(2, "dump %p %d\n", a, na);
1814 	buf[0] = '\0';
1815 	for(i=0; i<na; i++){
1816 		sprint(buf+strlen(buf), " %.2ux", a[i]);
1817 		if(i%16 == 7)
1818 			sprint(buf+strlen(buf), " --");
1819 		if(i%16==15){
1820 			sprint(buf+strlen(buf), "\n");
1821 			write(2, buf, strlen(buf));
1822 			buf[0] = '\0';
1823 		}
1824 	}
1825 	if(i%16){
1826 		sprint(buf+strlen(buf), "\n");
1827 		write(2, buf, strlen(buf));
1828 	}
1829 }
1830 
1831 static void
mediainproc(PPP * ppp)1832 mediainproc(PPP *ppp)
1833 {
1834 	Block *b;
1835 	Ipaddr remote;
1836 
1837 	notify(catchdie);
1838 	while(!dying){
1839 		b = pppread(ppp);
1840 		if(b == nil){
1841 			syslog(0, LOG, "pppread return nil");
1842 			break;
1843 		}
1844 		ppp->stat.iprecv++;
1845 		if(ppp->ipcp->state != Sopened) {
1846 			ppp->stat.iprecvnotup++;
1847 			freeb(b);
1848 			continue;
1849 		}
1850 
1851 		if(server) {
1852 			v4tov6(remote, b->rptr+12);
1853 			if(ipcmp(remote, ppp->remote) != 0) {
1854 				ppp->stat.iprecvbadsrc++;
1855 				freeb(b);
1856 				continue;
1857 			}
1858 		}
1859 		if(debug > 1){
1860 			netlog("ip write pkt %p %d\n", b->rptr, blen(b));
1861 			hexdump(b->rptr, blen(b));
1862 		}
1863 		if(write(ppp->ipfd, b->rptr, blen(b)) < 0) {
1864 			syslog(0, LOG, "error writing to pktifc");
1865 			freeb(b);
1866 			break;
1867 		}
1868 
1869 		freeb(b);
1870 	}
1871 
1872 	netlog(": remote=%I: ppp shutting down\n", ppp->remote);
1873 	syslog(0, LOG, ": remote=%I: ppp shutting down", ppp->remote);
1874 	syslog(0, LOG, "\t\tppp send = %lud/%lud recv= %lud/%lud",
1875 		ppp->out.packets, ppp->out.uchars,
1876 		ppp->in.packets, ppp->in.uchars);
1877 	syslog(0, LOG, "\t\tip send=%lud", ppp->stat.ipsend);
1878 	syslog(0, LOG, "\t\tip recv=%lud notup=%lud badsrc=%lud",
1879 		ppp->stat.iprecv, ppp->stat.iprecvnotup, ppp->stat.iprecvbadsrc);
1880 	syslog(0, LOG, "\t\tcompress=%lud in=%lud out=%lud reset=%lud",
1881 		ppp->stat.comp, ppp->stat.compin, ppp->stat.compout, ppp->stat.compreset);
1882 	syslog(0, LOG, "\t\tuncompress=%lud in=%lud out=%lud reset=%lud",
1883 		ppp->stat.uncomp, ppp->stat.uncompin, ppp->stat.uncompout,
1884 		ppp->stat.uncompreset);
1885 	syslog(0, LOG, "\t\tvjin=%lud vjout=%lud vjfail=%lud",
1886 		ppp->stat.vjin, ppp->stat.vjout, ppp->stat.vjfail);
1887 }
1888 
1889 /*
1890  *  link quality management
1891  */
1892 static void
getlqm(PPP * ppp,Block * b)1893 getlqm(PPP *ppp, Block *b)
1894 {
1895 	Qualpkt *p;
1896 
1897 	p = (Qualpkt*)b->rptr;
1898 	if(BLEN(b) == sizeof(Qualpkt)){
1899 		ppp->in.reports++;
1900 		ppp->pout.reports = nhgetl(p->peeroutreports);
1901 		ppp->pout.packets = nhgetl(p->peeroutpackets);
1902 		ppp->pout.uchars = nhgetl(p->peeroutuchars);
1903 		ppp->pin.reports = nhgetl(p->peerinreports);
1904 		ppp->pin.packets = nhgetl(p->peerinpackets);
1905 		ppp->pin.discards = nhgetl(p->peerindiscards);
1906 		ppp->pin.errors = nhgetl(p->peerinerrors);
1907 		ppp->pin.uchars = nhgetl(p->peerinuchars);
1908 
1909 		/* save our numbers at time of reception */
1910 		memmove(&ppp->sin, &ppp->in, sizeof(Qualstats));
1911 
1912 	}
1913 	freeb(b);
1914 	if(ppp->period == 0)
1915 		putlqm(ppp);
1916 
1917 }
1918 
1919 static void
putlqm(PPP * ppp)1920 putlqm(PPP *ppp)
1921 {
1922 	Qualpkt *p;
1923 	Block *b;
1924 
1925 	b = allocb(sizeof(Qualpkt));
1926 	b->wptr += sizeof(Qualpkt);
1927 	p = (Qualpkt*)b->rptr;
1928 	hnputl(p->magic, 0);
1929 
1930 	/* heresay (what he last told us) */
1931 	hnputl(p->lastoutreports, ppp->pout.reports);
1932 	hnputl(p->lastoutpackets, ppp->pout.packets);
1933 	hnputl(p->lastoutuchars, ppp->pout.uchars);
1934 
1935 	/* our numbers at time of last reception */
1936 	hnputl(p->peerinreports, ppp->sin.reports);
1937 	hnputl(p->peerinpackets, ppp->sin.packets);
1938 	hnputl(p->peerindiscards, ppp->sin.discards);
1939 	hnputl(p->peerinerrors, ppp->sin.errors);
1940 	hnputl(p->peerinuchars, ppp->sin.uchars);
1941 
1942 	/* our numbers now */
1943 	hnputl(p->peeroutreports, ppp->out.reports+1);
1944 	hnputl(p->peeroutpackets, ppp->out.packets+1);
1945 	hnputl(p->peeroutuchars, ppp->out.uchars+53/*hack*/);
1946 
1947 	putframe(ppp, Plqm, b);
1948 	freeb(b);
1949 	ppp->out.reports++;
1950 }
1951 
1952 /*
1953  * init challenge response dialog
1954  */
1955 static void
chapinit(PPP * ppp)1956 chapinit(PPP *ppp)
1957 {
1958 	Block *b;
1959 	Lcpmsg *m;
1960 	Chap *c;
1961 	int len;
1962 	char *aproto;
1963 
1964 	getauth(ppp);
1965 
1966 	c = ppp->chap;
1967 	c->id++;
1968 
1969 	switch(c->proto){
1970 	default:
1971 		abort();
1972 	case APmd5:
1973 		aproto = "chap";
1974 		break;
1975 	case APmschap:
1976 		aproto = "mschap";
1977 		break;
1978 	}
1979 	if((c->cs = auth_challenge("proto=%q role=server", aproto)) == nil)
1980 		sysfatal("auth_challenge: %r");
1981 	syslog(0, LOG, ": remote=%I: sending %d byte challenge", ppp->remote, c->cs->nchal);
1982 	len = 4 + 1 + c->cs->nchal + strlen(ppp->chapname);
1983 	b = alloclcp(Cchallenge, c->id, len, &m);
1984 
1985 	*b->wptr++ = c->cs->nchal;
1986 	memmove(b->wptr, c->cs->chal, c->cs->nchal);
1987 	b->wptr += c->cs->nchal;
1988 	memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
1989 	b->wptr += strlen(ppp->chapname);
1990 	hnputs(m->len, len);
1991 	putframe(ppp, Pchap, b);
1992 	freeb(b);
1993 
1994 	c->state = Cchalsent;
1995 }
1996 
1997 /*
1998  * BUG factotum should do this
1999  */
2000 enum {
2001 	MShashlen = 16,
2002 	MSresplen = 24,
2003 	MSchallen = 8,
2004 };
2005 
2006 void
desencrypt(uchar data[8],uchar key[7])2007 desencrypt(uchar data[8], uchar key[7])
2008 {
2009 	ulong ekey[32];
2010 
2011 	key_setup(key, ekey);
2012 	block_cipher(ekey, data, 0);
2013 }
2014 
2015 void
nthash(uchar hash[MShashlen],char * passwd)2016 nthash(uchar hash[MShashlen], char *passwd)
2017 {
2018 	uchar buf[512];
2019 	int i;
2020 
2021 	for(i=0; *passwd && i<sizeof(buf); passwd++) {
2022 		buf[i++] = *passwd;
2023 		buf[i++] = 0;
2024 	}
2025 	memset(hash, 0, 16);
2026 	md4(buf, i, hash, 0);
2027 }
2028 
2029 void
mschalresp(uchar resp[MSresplen],uchar hash[MShashlen],uchar chal[MSchallen])2030 mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen])
2031 {
2032 	int i;
2033 	uchar buf[21];
2034 
2035 	memset(buf, 0, sizeof(buf));
2036 	memcpy(buf, hash, MShashlen);
2037 
2038 	for(i=0; i<3; i++) {
2039 		memmove(resp+i*MSchallen, chal, MSchallen);
2040 		desencrypt(resp+i*MSchallen, buf+i*7);
2041 	}
2042 }
2043 
2044 /*
2045  *  challenge response dialog
2046  */
2047 extern	int	_asrdresp(int, uchar*, int);
2048 
2049 static void
getchap(PPP * ppp,Block * b)2050 getchap(PPP *ppp, Block *b)
2051 {
2052 	AuthInfo *ai;
2053 	Lcpmsg *m;
2054 	int len, vlen, i, id, n, nresp;
2055 	char md5buf[512], code;
2056 	Chap *c;
2057 	Chapreply cr;
2058 	MSchapreply mscr;
2059 	char uid[PATH];
2060 	uchar digest[16], *p, *resp, sdigest[SHA1dlen];
2061 	uchar mshash[MShashlen], mshash2[MShashlen];
2062 	DigestState *s;
2063 	uchar msresp[2*MSresplen+1];
2064 
2065 	m = (Lcpmsg*)b->rptr;
2066 	len = nhgets(m->len);
2067 	if(BLEN(b) < len){
2068 		syslog(0, LOG, "short chap message");
2069 		freeb(b);
2070 		return;
2071 	}
2072 
2073 	qlock(ppp);
2074 
2075 	switch(m->code){
2076 	case Cchallenge:
2077 		getauth(ppp);
2078 
2079 		vlen = m->data[0];
2080 		if(vlen > len - 5) {
2081 			netlog("PPP: chap: bad challenge len\n");
2082 			break;
2083 		}
2084 
2085 		id = m->id;
2086 		switch(ppp->chap->proto){
2087 		default:
2088 			abort();
2089 		case APmd5:
2090 			md5buf[0] = m->id;
2091 			strcpy(md5buf+1, ppp->secret);
2092 			n = strlen(ppp->secret) + 1;
2093 			memmove(md5buf+n, m->data+1, vlen);
2094 			n += vlen;
2095 			md5((uchar*)md5buf, n, digest, nil);
2096 			resp = digest;
2097 			nresp = 16;
2098 			break;
2099 		case APmschap:
2100 			nthash(mshash, ppp->secret);
2101 			memset(msresp, 0, sizeof msresp);
2102 			mschalresp(msresp+MSresplen, mshash, m->data+1);
2103 			resp = msresp;
2104 			nresp = sizeof msresp;
2105 			nthash(mshash, ppp->secret);
2106 			md4(mshash, 16, mshash2, 0);
2107 			s = sha1(mshash2, 16, 0, 0);
2108 			sha1(mshash2, 16, 0, s);
2109 			sha1(m->data+1, 8, sdigest, s);
2110 			memmove(ppp->key, sdigest, 16);
2111 			break;
2112 		}
2113 		len = 4 + 1 + nresp + strlen(ppp->chapname);
2114 		freeb(b);
2115 		b = alloclcp(Cresponse, id, len, &m);
2116 		*b->wptr++ = nresp;
2117 		memmove(b->wptr, resp, nresp);
2118 		b->wptr += nresp;
2119 		memmove(b->wptr, ppp->chapname, strlen(ppp->chapname));
2120 		b->wptr += strlen(ppp->chapname);
2121 		hnputs(m->len, len);
2122 		netlog("PPP: sending response len %d\n", len);
2123 		putframe(ppp, Pchap, b);
2124 		break;
2125 	case Cresponse:
2126 		c = ppp->chap;
2127 		vlen = m->data[0];
2128 		if(m->id != c->id) {
2129 			netlog("PPP: chap: bad response id\n");
2130 			break;
2131 		}
2132 		switch(c->proto) {
2133 		default:
2134 			sysfatal("unknown chap protocol: %d", c->proto);
2135 		case APmd5:
2136 			if(vlen > len - 5 || vlen != 16) {
2137 				netlog("PPP: chap: bad response len\n");
2138 				break;
2139 			}
2140 
2141 			cr.id = m->id;
2142 			memmove(cr.resp, m->data+1, 16);
2143 			memset(uid, 0, sizeof(uid));
2144 			n = len-5-vlen;
2145 			if(n >= PATH)
2146 				n = PATH-1;
2147 			memmove(uid, m->data+1+vlen, n);
2148 			c->cs->user = uid;
2149 			c->cs->resp = &cr;
2150 			c->cs->nresp = sizeof cr;
2151 			break;
2152 		case APmschap:
2153 			if(vlen > len - 5 || vlen != 49) {
2154 				netlog("PPP: chap: bad response len\n");
2155 				break;
2156 			}
2157 			memset(&mscr, 0, sizeof(mscr));
2158 			memmove(mscr.LMresp, m->data+1, 24);
2159 			memmove(mscr.NTresp, m->data+24+1, 24);
2160 			n = len-5-vlen;
2161 			p = m->data+1+vlen;
2162 			/* remove domain name */
2163 			for(i=0; i<n; i++) {
2164 				if(p[i] == '\\') {
2165 					p += i+1;
2166 					n -= i+1;
2167 					break;
2168 				}
2169 			}
2170 			if(n >= PATH)
2171 				n = PATH-1;
2172 			memset(uid, 0, sizeof(uid));
2173 			memmove(uid, p, n);
2174 			c->cs->user = uid;
2175 			c->cs->resp = &mscr;
2176 			c->cs->nresp = sizeof mscr;
2177 			break;
2178 		}
2179 
2180 		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);
2181 		if((ai = auth_response(c->cs)) == nil || auth_chuid(ai, nil) < 0){
2182 			c->state = Cunauth;
2183 			code = Cfailure;
2184 			syslog(0, LOG, ": remote=%I: auth failed: %r, uid=%s", ppp->remote, uid);
2185 		}else{
2186 			c->state = Cauthok;
2187 			code = Csuccess;
2188 			syslog(0, LOG, ": remote=%I: auth ok: uid=%s nsecret=%d", ppp->remote, uid, ai->nsecret);
2189 			if(c->proto == APmschap){
2190 				if(ai->nsecret != sizeof(ppp->key))
2191 					sysfatal("could not get the encryption key");
2192 				memmove(ppp->key, ai->secret, sizeof(ppp->key));
2193 			}
2194 		}
2195 		auth_freeAI(ai);
2196 		auth_freechal(c->cs);
2197 		c->cs = nil;
2198 		freeb(b);
2199 
2200 		/* send reply */
2201 		len = 4;
2202 		b = alloclcp(code, c->id, len, &m);
2203 		hnputs(m->len, len);
2204 		putframe(ppp, Pchap, b);
2205 
2206 		if(c->state == Cauthok) {
2207 			setphase(ppp, Pnet);
2208 		} else {
2209 			/* restart chapp negotiation */
2210 			chapinit(ppp);
2211 		}
2212 
2213 		break;
2214 	case Csuccess:
2215 		netlog("ppp: chap succeeded\n");
2216 		break;
2217 	case Cfailure:
2218 		netlog("ppp: chap failed\n");
2219 		break;
2220 	default:
2221 		syslog(0, LOG, "chap code %d?\n", m->code);
2222 		break;
2223 	}
2224 	qunlock(ppp);
2225 	freeb(b);
2226 }
2227 
2228 static void
putpaprequest(PPP * ppp)2229 putpaprequest(PPP *ppp)
2230 {
2231 	Block *b;
2232 	Lcpmsg *m;
2233 	Chap *c;
2234 	int len, nlen, slen;
2235 
2236 	getauth(ppp);
2237 
2238 	c = ppp->chap;
2239 	c->id++;
2240 	netlog("PPP: pap: send authreq %d %s %s\n", c->id, ppp->chapname, "****");
2241 
2242 	nlen = strlen(ppp->chapname);
2243 	slen = strlen(ppp->secret);
2244 	len = 4 + 1 + nlen + 1 + slen;
2245 	b = alloclcp(Pauthreq, c->id, len, &m);
2246 
2247 	*b->wptr++ = nlen;
2248 	memmove(b->wptr, ppp->chapname, nlen);
2249 	b->wptr += nlen;
2250 	*b->wptr++ = slen;
2251 	memmove(b->wptr, ppp->secret, slen);
2252 	b->wptr += slen;
2253 	hnputs(m->len, len);
2254 
2255 	putframe(ppp, Ppasswd, b);
2256 	freeb(b);
2257 }
2258 
2259 static void
papinit(PPP * ppp)2260 papinit(PPP *ppp)
2261 {
2262 	ppp->chap->id = 0;
2263 	putpaprequest(ppp);
2264 }
2265 
2266 static void
getpap(PPP * ppp,Block * b)2267 getpap(PPP *ppp, Block *b)
2268 {
2269 	Lcpmsg *m;
2270 	int len;
2271 
2272 	m = (Lcpmsg*)b->rptr;
2273 	len = 4;
2274 	if(BLEN(b) < 4 || BLEN(b) < (len = nhgets(m->len))){
2275 		syslog(0, LOG, "short pap message (%ld < %d)", BLEN(b), len);
2276 		freeb(b);
2277 		return;
2278 	}
2279 	if(len < sizeof(Lcpmsg))
2280 		m->data[0] = 0;
2281 
2282 	qlock(ppp);
2283 	switch(m->code){
2284 	case Pauthreq:
2285 		netlog("PPP: pap auth request, not supported\n");
2286 		break;
2287 	case Pauthack:
2288 		if(ppp->phase == Pauth
2289 		&& ppp->chap->proto == APpasswd
2290 		&& m->id <= ppp-> chap->id){
2291 			netlog("PPP: pap succeeded\n");
2292 			setphase(ppp, Pnet);
2293 		}
2294 		break;
2295 	case Pauthnak:
2296 		if(ppp->phase == Pauth
2297 		&& ppp->chap->proto == APpasswd
2298 		&& m->id <= ppp-> chap->id){
2299 			netlog("PPP: pap failed (%d:%.*s)\n",
2300 				m->data[0], m->data[0], (char*)m->data+1);
2301 			terminate(ppp, 0);
2302 		}
2303 		break;
2304 	default:
2305 		netlog("PPP: unknown pap messsage %d\n", m->code);
2306 	}
2307 	qunlock(ppp);
2308 	freeb(b);
2309 }
2310 
2311 static void
printopts(Pstate * p,Block * b,int send)2312 printopts(Pstate *p, Block *b, int send)
2313 {
2314 	Lcpmsg *m;
2315 	Lcpopt *o;
2316 	int proto, x, period;
2317 	uchar *cp;
2318 	char *code, *dir;
2319 
2320 	m = (Lcpmsg*)b->rptr;
2321 	switch(m->code) {
2322 	default: code = "<unknown>"; break;
2323 	case Lconfreq: code = "confrequest"; break;
2324 	case Lconfack: code = "confack"; break;
2325 	case Lconfnak: code = "confnak"; break;
2326 	case Lconfrej: code = "confreject"; break;
2327 	}
2328 
2329 	if(send)
2330 		dir = "send";
2331 	else
2332 		dir = "recv";
2333 
2334 	netlog("ppp: %s %s: id=%d\n", dir, code, m->id);
2335 
2336 	for(cp = m->data; cp < b->wptr; cp += o->len){
2337 		o = (Lcpopt*)cp;
2338 		if(cp + o->len > b->wptr){
2339 			netlog("\tbad option length %ux\n", o->type);
2340 			return;
2341 		}
2342 
2343 		switch(p->proto){
2344 		case Plcp:
2345 			switch(o->type){
2346 			default:
2347 				netlog("\tunknown %d len=%d\n", o->type, o->len);
2348 				break;
2349 			case Omtu:
2350 				netlog("\tmtu = %d\n", nhgets(o->data));
2351 				break;
2352 			case Octlmap:
2353 				netlog("\tctlmap = %ux\n", nhgetl(o->data));
2354 				break;
2355 			case Oauth:
2356 				netlog("\tauth = %ux", nhgetl(o->data));
2357 				proto = nhgets(o->data);
2358 				switch(proto) {
2359 				default:
2360 					netlog("unknown auth proto %d\n", proto);
2361 					break;
2362 				case Ppasswd:
2363 					netlog("password\n");
2364 					break;
2365 				case Pchap:
2366 					netlog("chap %ux\n", o->data[2]);
2367 					break;
2368 				}
2369 				break;
2370 			case Oquality:
2371 				proto = nhgets(o->data);
2372 				switch(proto) {
2373 				default:
2374 					netlog("\tunknown quality proto %d\n", proto);
2375 					break;
2376 				case Plqm:
2377 					x = nhgetl(o->data+2)*10;
2378 					period = (x+Period-1)/Period;
2379 					netlog("\tlqm period = %d\n", period);
2380 					break;
2381 				}
2382 			case Omagic:
2383 				netlog("\tmagic = %ux\n", nhgetl(o->data));
2384 				break;
2385 			case Opc:
2386 				netlog("\tprotocol compress\n");
2387 				break;
2388 			case Oac:
2389 				netlog("\taddr compress\n");
2390 				break;
2391 			}
2392 			break;
2393 		case Pccp:
2394 			switch(o->type){
2395 			default:
2396 				netlog("\tunknown %d len=%d\n", o->type, o->len);
2397 				break;
2398 			case Ocoui:
2399 				netlog("\tOUI\n");
2400 				break;
2401 			case Ocstac:
2402 				netlog("\tstac LZS\n");
2403 				break;
2404 			case Ocmppc:
2405 				netlog("\tMicrosoft PPC len=%d %ux\n", o->len, nhgetl(o->data));
2406 				break;
2407 			case Octhwack:
2408 				netlog("\tThwack\n");
2409 				break;
2410 			}
2411 			break;
2412 		case Pecp:
2413 			switch(o->type){
2414 			default:
2415 				netlog("\tunknown %d len=%d\n", o->type, o->len);
2416 				break;
2417 			case Oeoui:
2418 				netlog("\tOUI\n");
2419 				break;
2420 			case Oedese:
2421 				netlog("\tDES\n");
2422 				break;
2423 			}
2424 			break;
2425 		case Pipcp:
2426 			switch(o->type){
2427 			default:
2428 				netlog("\tunknown %d len=%d\n", o->type, o->len);
2429 				break;
2430 			case Oipaddrs:
2431 				netlog("\tip addrs - deprecated\n");
2432 				break;
2433 			case Oipcompress:
2434 				netlog("\tip compress\n");
2435 				break;
2436 			case Oipaddr:
2437 				netlog("\tip addr %V\n", o->data);
2438 				break;
2439 			case Oipdns:
2440 				netlog("\tdns addr %V\n", o->data);
2441 				break;
2442 			case Oipwins:
2443 				netlog("\twins addr %V\n", o->data);
2444 				break;
2445 			case Oipdns2:
2446 				netlog("\tdns2 addr %V\n", o->data);
2447 				break;
2448 			case Oipwins2:
2449 				netlog("\twins2 addr %V\n", o->data);
2450 				break;
2451 			}
2452 			break;
2453 		}
2454 	}
2455 }
2456 
2457 static void
sendtermreq(PPP * ppp,Pstate * p)2458 sendtermreq(PPP *ppp, Pstate *p)
2459 {
2460 	Block *b;
2461 	Lcpmsg *m;
2462 
2463 	p->termid = ++(p->id);
2464 	b = alloclcp(Ltermreq, p->termid, 4, &m);
2465 	hnputs(m->len, 4);
2466 	putframe(ppp, p->proto, b);
2467 	freeb(b);
2468 	newstate(ppp, p, Sclosing);
2469 }
2470 
2471 static void
sendechoreq(PPP * ppp,Pstate * p)2472 sendechoreq(PPP *ppp, Pstate *p)
2473 {
2474 	Block *b;
2475 	Lcpmsg *m;
2476 
2477 	p->termid = ++(p->id);
2478 	b = alloclcp(Lechoreq, p->id, 4, &m);
2479 	hnputs(m->len, 4);
2480 	putframe(ppp, p->proto, b);
2481 	freeb(b);
2482 }
2483 
2484 enum
2485 {
2486 	CtrlD	= 0x4,
2487 	CtrlE	= 0x5,
2488 	CtrlO	= 0xf,
2489 	Cr	= 13,
2490 	View	= 0x80,
2491 };
2492 
2493 int conndone;
2494 
2495 static void
xfer(int fd)2496 xfer(int fd)
2497 {
2498 	int i, n;
2499 	uchar xbuf[128];
2500 
2501 	for(;;) {
2502 		n = read(fd, xbuf, sizeof(xbuf));
2503 		if(n < 0)
2504 			break;
2505 		if(conndone)
2506 			break;
2507 		for(i = 0; i < n; i++)
2508 			if(xbuf[i] == Cr)
2509 				xbuf[i] = ' ';
2510 		write(1, xbuf, n);
2511 	}
2512 	close(fd);
2513 }
2514 
2515 static int
readcr(int fd,char * buf,int nbuf)2516 readcr(int fd, char *buf, int nbuf)
2517 {
2518 	char c;
2519 	int n, tot;
2520 
2521 	tot = 0;
2522 	while((n=read(fd, &c, 1)) == 1){
2523 		if(c == '\n'){
2524 			buf[tot] = 0;
2525 			return tot;
2526 		}
2527 		buf[tot++] = c;
2528 		if(tot == nbuf)
2529 			sysfatal("line too long in readcr");
2530 	}
2531 	return n;
2532 }
2533 
2534 static void
connect(int fd,int cfd)2535 connect(int fd, int cfd)
2536 {
2537 	int n, ctl;
2538 	char xbuf[128];
2539 
2540 	if (chatfile) {
2541 		int chatfd, lineno, nb;
2542 		char *buf, *p, *s, response[128];
2543 		Dir *dir;
2544 
2545 		if ((chatfd = open(chatfile, OREAD)) < 0)
2546 			sysfatal("cannot open %s: %r", chatfile);
2547 
2548 		if ((dir = dirfstat(chatfd)) == nil)
2549 			sysfatal("cannot fstat %s: %r",chatfile);
2550 
2551 		buf = (char *)malloc(dir->length + 1);
2552 		assert(buf);
2553 
2554 		if ((nb = read(chatfd, buf, dir->length)) < 0)
2555 			sysfatal("cannot read chatfile %s: %r", chatfile);
2556 		assert(nb == dir->length);
2557 		buf[dir->length] = '\0';
2558 		free(dir);
2559 		close(chatfd);
2560 
2561 		p = buf;
2562 		lineno = 0;
2563 		for(;;) {
2564 			char *_args[3];
2565 
2566 			if ((s = strchr(p, '\n')) == nil)
2567 				break;
2568 			*s++ = '\0';
2569 
2570 			lineno++;
2571 
2572 			if (*p == '#') {
2573 				p = s;
2574 				continue;
2575 			}
2576 
2577 			if (tokenize(p, _args, 3) != 2)
2578 				sysfatal("invalid line %d (line expected: 'send' 'expect')",
2579 						lineno);
2580 
2581 			if (debug)
2582 				print("sending %s, expecting %s\n", _args[0], _args[1]);
2583 
2584 			if(strlen(_args[0])){
2585 				nb = fprint(fd, "%s\r", _args[0]);
2586 				assert(nb > 0);
2587 			}
2588 
2589 			if (strlen(_args[1]) > 0) {
2590 				if ((nb = readcr(fd, response, sizeof response-1)) < 0)
2591 					sysfatal("cannot read response from: %r");
2592 
2593 				if (debug)
2594 					print("response %s\n", response);
2595 
2596 				if (nb == 0)
2597 					sysfatal("eof on input?");
2598 
2599 				if (cistrstr(response, _args[1]) == nil)
2600 					sysfatal("expected %s, got %s", _args[1], response);
2601 			}
2602 			p = s;
2603 		}
2604 		free(buf);
2605 		return;
2606 	}
2607 
2608 	print("Connect to file system now, type ctrl-d when done.\n");
2609 	print("...(Use the view or down arrow key to send a break)\n");
2610 	print("...(Use ctrl-e to set even parity or ctrl-o for odd)\n");
2611 
2612 	ctl = open("/dev/consctl", OWRITE);
2613 	if(ctl < 0)
2614 		sysfatal("opening consctl");
2615 	fprint(ctl, "rawon");
2616 
2617 	fd = dup(fd, -1);
2618 	conndone = 0;
2619 	switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
2620 	case -1:
2621 		sysfatal("forking xfer");
2622 	case 0:
2623 		xfer(fd);
2624 		_exits(nil);
2625 	}
2626 
2627 	for(;;){
2628 		read(0, xbuf, 1);
2629 		switch(xbuf[0]&0xff) {
2630 		case CtrlD:	/* done */
2631 			conndone = 1;
2632 			close(ctl);
2633 			print("\n");
2634 			return;
2635 		case CtrlE:	/* set even parity */
2636 			fprint(cfd, "pe");
2637 			break;
2638 		case CtrlO:	/* set odd parity */
2639 			fprint(cfd, "po");
2640 			break;
2641 		case View:	/* send a break */
2642 			fprint(cfd, "k500");
2643 			break;
2644 		default:
2645 			n = write(fd, xbuf, 1);
2646 			if(n < 0) {
2647 				errstr(xbuf, sizeof(xbuf));
2648 				conndone = 1;
2649 				close(ctl);
2650 				print("[remote write error (%s)]\n", xbuf);
2651 				return;
2652 			}
2653 		}
2654 	}
2655 }
2656 
2657 int interactive;
2658 
2659 void
usage(void)2660 usage(void)
2661 {
2662 	fprint(2, "usage: ppp [-CPSacdfu] [-b baud] [-k keyspec] [-m mtu] "
2663 		"[-M chatfile] [-p dev] [-x netmntpt] [-t modemcmd] "
2664 		"[local-addr [remote-addr]]\n");
2665 	exits("usage");
2666 }
2667 
2668 void
main(int argc,char ** argv)2669 main(int argc, char **argv)
2670 {
2671 	int mtu, baud, framing, user, mediain, mediaout, cfd;
2672 	Ipaddr ipaddr, remip;
2673 	char *dev, *modemcmd;
2674 	char net[128];
2675 	PPP *ppp;
2676 	char buf[128];
2677 
2678 	rfork(RFREND|RFNOTEG|RFNAMEG);
2679 
2680 	fmtinstall('I', eipfmt);
2681 	fmtinstall('V', eipfmt);
2682 	fmtinstall('E', eipfmt);
2683 
2684 	dev = nil;
2685 
2686 	invalidate(ipaddr);
2687 	invalidate(remip);
2688 
2689 	mtu = Defmtu;
2690 	baud = 0;
2691 	framing = 0;
2692 	setnetmtpt(net, sizeof(net), nil);
2693 	user = 0;
2694 	modemcmd = nil;
2695 
2696 	ARGBEGIN{
2697 	case 'a':
2698 		noauth = 1;
2699 		break;
2700 	case 'b':
2701 		baud = atoi(EARGF(usage()));
2702 		if(baud < 0)
2703 			baud = 0;
2704 		break;
2705 	case 'c':
2706 		nocompress = 1;
2707 		break;
2708 	case 'C':
2709 		noipcompress = 1;
2710 		break;
2711 	case 'd':
2712 		debug++;
2713 		break;
2714 	case 'f':
2715 		framing = 1;
2716 		break;
2717 	case 'F':
2718 		pppframing = 0;
2719 		break;
2720 	case 'k':
2721 		keyspec = EARGF(usage());
2722 		break;
2723 	case 'm':
2724 		mtu = atoi(EARGF(usage()));
2725 		if(mtu < Minmtu)
2726 			mtu = Minmtu;
2727 		if(mtu > Maxmtu)
2728 			mtu = Maxmtu;
2729 		break;
2730 	case 'M':
2731 		chatfile = EARGF(usage());
2732 		break;
2733 	case 'p':
2734 		dev = EARGF(usage());
2735 		break;
2736 	case 'P':
2737 		primary = 1;
2738 		break;
2739 	case 'S':
2740 		server = 1;
2741 		break;
2742 	case 't':
2743 		modemcmd = EARGF(usage());
2744 		break;
2745 	case 'u':
2746 		user = 1;
2747 		break;
2748 	case 'x':
2749 		setnetmtpt(net, sizeof net, EARGF(usage()));
2750 		break;
2751 	default:
2752 		fprint(2, "unknown option %c\n", ARGC());
2753 		usage();
2754 	}ARGEND;
2755 
2756 	switch(argc){
2757 	case 2:
2758 		if (parseip(remip, argv[1]) == -1)
2759 			sysfatal("bad remote ip %s", argv[1]);
2760 	case 1:
2761 		if (parseip(ipaddr, argv[0]) == -1)
2762 			sysfatal("bad ip %s", argv[0]);
2763 	case 0:
2764 		break;
2765 	default:
2766 		usage();
2767 	}
2768 
2769 	nip = nipifcs(net);
2770 	if(nip == 0 && !server)
2771 		primary = 1;
2772 
2773 	if(dev != nil){
2774 		mediain = open(dev, ORDWR);
2775 		if(mediain < 0){
2776 			if(strchr(dev, '!')){
2777 				if((mediain = dial(dev, 0, 0, &cfd)) == -1){
2778 					fprint(2, "ppp: couldn't dial %s: %r\n", dev);
2779 					exits(dev);
2780 				}
2781 			} else {
2782 				fprint(2, "ppp: couldn't open %s\n", dev);
2783 				exits(dev);
2784 			}
2785 		} else {
2786 			snprint(buf, sizeof buf, "%sctl", dev);
2787 			cfd = open(buf, ORDWR);
2788 		}
2789 		if(cfd > 0){
2790 			if(baud)
2791 				fprint(cfd, "b%d", baud);
2792 			fprint(cfd, "m1");	/* cts/rts flow control (and fifo's) on */
2793 			fprint(cfd, "q64000");	/* increase q size to 64k */
2794 			fprint(cfd, "n1");	/* nonblocking writes on */
2795 			fprint(cfd, "r1");	/* rts on */
2796 			fprint(cfd, "d1");	/* dtr on */
2797 			fprint(cfd, "c1");	/* dcdhup on */
2798 			if(user || chatfile)
2799 				connect(mediain, cfd);
2800 			close(cfd);
2801 		} else {
2802 			if(user || chatfile)
2803 				connect(mediain, -1);
2804 		}
2805 		mediaout = mediain;
2806 	} else {
2807 		mediain = open("/fd/0", OREAD);
2808 		if(mediain < 0){
2809 			fprint(2, "ppp: couldn't open /fd/0\n");
2810 			exits("/fd/0");
2811 		}
2812 		mediaout = open("/fd/1", OWRITE);
2813 		if(mediaout < 0){
2814 			fprint(2, "ppp: couldn't open /fd/0\n");
2815 			exits("/fd/1");
2816 		}
2817 	}
2818 
2819 	if(modemcmd != nil && mediaout >= 0)
2820 		fprint(mediaout, "%s\r", modemcmd);
2821 
2822 	ppp = mallocz(sizeof(*ppp), 1);
2823 	pppopen(ppp, mediain, mediaout, net, ipaddr, remip, mtu, framing);
2824 
2825 	/* wait until ip is configured */
2826 	rendezvous((void*)Rmagic, 0);
2827 
2828 	if(primary){
2829 		/* create a /net/ndb entry */
2830 		putndb(ppp, net);
2831 	}
2832 
2833 	exits(0);
2834 }
2835 
2836 void
netlog(char * fmt,...)2837 netlog(char *fmt, ...)
2838 {
2839 	va_list arg;
2840 	char *m;
2841 	static long start;
2842 	long now;
2843 
2844 	if(debug == 0)
2845 		return;
2846 
2847 	now = time(0);
2848 	if(start == 0)
2849 		start = now;
2850 
2851 	va_start(arg, fmt);
2852 	m = vsmprint(fmt, arg);
2853 	fprint(2, "%ld %s", now-start, m);
2854 	free(m);
2855 	va_end(arg);
2856 }
2857 
2858 /*
2859  *  return non-zero if this is a valid v4 address
2860  */
2861 static int
validv4(Ipaddr addr)2862 validv4(Ipaddr addr)
2863 {
2864 	return memcmp(addr, v4prefix, IPv4off) == 0 && memcmp(addr, v4prefix, IPaddrlen) != 0;
2865 }
2866 
2867 static void
invalidate(Ipaddr addr)2868 invalidate(Ipaddr addr)
2869 {
2870 	ipmove(addr, IPnoaddr);
2871 }
2872 
2873 /*
2874  *  return number of networks
2875  */
2876 static int
nipifcs(char * net)2877 nipifcs(char *net)
2878 {
2879 	static Ipifc *ifc;
2880 	Ipifc *nifc;
2881 	Iplifc *lifc;
2882 	int n;
2883 
2884 	n = 0;
2885 	ifc = readipifc(net, ifc, -1);
2886 	for(nifc = ifc; nifc != nil; nifc = nifc->next)
2887 		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
2888 			n++;
2889 	return n;
2890 }
2891 
2892 /*
2893  *   make an ndb entry and put it into /net/ndb for the servers to see
2894  */
2895 static void
putndb(PPP * ppp,char * net)2896 putndb(PPP *ppp, char *net)
2897 {
2898 	char buf[1024];
2899 	char file[64];
2900 	char *p, *e;
2901 	int fd;
2902 
2903 	e = buf + sizeof(buf);
2904 	p = buf;
2905 	p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local,
2906 			ppp->remote);
2907 	if(validv4(ppp->dns[0]))
2908 		p = seprint(p, e, "\tdns=%I\n", ppp->dns[0]);
2909 	if(validv4(ppp->dns[1]))
2910 		p = seprint(p, e, "\tdns=%I\n", ppp->dns[1]);
2911 	if(validv4(ppp->wins[0]))
2912 		p = seprint(p, e, "\twins=%I\n", ppp->wins[0]);
2913 	if(validv4(ppp->wins[1]))
2914 		p = seprint(p, e, "\twins=%I\n", ppp->wins[1]);
2915 	seprint(file, file+sizeof file, "%s/ndb", net);
2916 	fd = open(file, OWRITE);
2917 	if(fd < 0)
2918 		return;
2919 	write(fd, buf, p-buf);
2920 	close(fd);
2921 	seprint(file, file+sizeof file, "%s/cs", net);
2922 	fd = open(file, OWRITE);
2923 	write(fd, "refresh", 7);
2924 	close(fd);
2925 	seprint(file, file+sizeof file, "%s/dns", net);
2926 	fd = open(file, OWRITE);
2927 	write(fd, "refresh", 7);
2928 	close(fd);
2929 }
2930 
2931 static void
getauth(PPP * ppp)2932 getauth(PPP *ppp)
2933 {
2934 	UserPasswd *up;
2935 
2936 	if(*ppp->chapname)
2937 		return;
2938 
2939 	up = auth_getuserpasswd(auth_getkey,"proto=pass service=ppp %s", keyspec);
2940 	if(up != nil){
2941 		strcpy(ppp->chapname, up->user);
2942 		strcpy(ppp->secret, up->passwd);
2943 	}
2944 }
2945