Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/ip/ppp/ppp.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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*
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
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*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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*
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*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2260
papinit(PPP *ppp)
2261
{
2262
	ppp->chap->id = 0;
2263
	putpaprequest(ppp);
2264
}
2265
 
2266
static void
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
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
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
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
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
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
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
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
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
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
2862
validv4(Ipaddr addr)
2863
{
2864
	return memcmp(addr, v4prefix, IPv4off) == 0 && memcmp(addr, v4prefix, IPaddrlen) != 0;
2865
}
2866
 
2867
static void
2868
invalidate(Ipaddr addr)
2869
{
2870
	ipmove(addr, IPnoaddr);
2871
}
2872
 
2873
/*
2874
 *  return number of networks
2875
 */
2876
static int
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
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
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
}