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