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