Fix up eipconvtest.c
[akaros.git] / kern / src / net / ppp.c
1 #include        "u.h"
2 #include        "../port/lib.h"
3 #include        "mem.h"
4 #include        "dat.h"
5 #include        "fns.h"
6 #include        "../port/error.h"
7 #include        <libcrypt.h>
8 #include        <kernel.h>
9 #include        "ip.h"
10 #include        "ppp.h"
11
12 int     nocompress;
13 Ipaddr  pppdns[2];
14
15 /*
16  * Calculate FCS - rfc 1331
17  */
18 ushort fcstab[256] =
19 {
20       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
21       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
22       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
23       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
24       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
25       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
26       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
27       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
28       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
29       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
30       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
31       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
32       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
33       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
34       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
35       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
36       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
37       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
38       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
39       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
40       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
41       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
42       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
43       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
44       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
45       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
46       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
47       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
48       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
49       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
50       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
51       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
52 };
53
54 static char *snames[] =
55 {
56         "Sclosed",
57         "Sclosing",
58         "Sreqsent",
59         "Sackrcvd",
60         "Sacksent",
61         "Sopened",
62 };
63
64 static void     init(PPP*);
65 static void     setphase(PPP*, int);
66 static void     pinit(PPP*, Pstate*);
67 static void     ppptimer(void*);
68 static void     ptimer(PPP*, Pstate*);
69 static int      getframe(PPP*, Block**);
70 static Block*   putframe(PPP*, int, Block*);
71 static uchar*   escapebyte(PPP*, ulong, uchar*, ushort*);
72 static void     config(PPP*, Pstate*, int);
73 static int      getopts(PPP*, Pstate*, Block*);
74 static void     rejopts(PPP*, Pstate*, Block*, int);
75 static void     newstate(PPP*, Pstate*, int);
76 static void     rcv(PPP*, Pstate*, Block*);
77 static void     getchap(PPP*, Block*);
78 static void     getpap(PPP*, Block*);
79 static void     sendpap(PPP*);
80 static void     getlqm(PPP*, Block*);
81 static void     putlqm(PPP*);
82 static void     hangup(PPP*);
83 static void     remove(PPP*);
84
85 static  int             validv4(Ipaddr);
86 static  void            invalidate(Ipaddr);
87 static  void            ipconnect(PPP *);
88 static  void            setdefroute(PPP *, Ipaddr);
89 static  void            printopts(PPP *, Pstate*, Block*, int);
90 static  void            sendtermreq(PPP*, Pstate*);
91
92 static void
93 errlog(PPP *ppp, char *err)
94 {
95         int n;
96         char msg[64];
97
98         n = snprint(msg, sizeof(msg), "%s\n", err);
99         qproduce(ppp->ifc->conv->eq, msg, n);
100 }
101
102 static void
103 init(PPP* ppp)
104 {
105         if(ppp->inbuf == nil){
106                 ppp->inbuf = allocb(4096);
107                 ppp->outbuf = allocb(4096);
108
109                 ppp->lcp = malloc(sizeof(Pstate));
110                 ppp->ipcp = malloc(sizeof(Pstate));
111                 if(ppp->lcp == nil || ppp->ipcp == nil)
112                         error("ppp init: malloc");
113
114                 ppp->lcp->proto = Plcp;
115                 ppp->lcp->state = Sclosed;
116                 ppp->ipcp->proto = Pipcp;
117                 ppp->ipcp->state = Sclosed;
118
119                 ktask("ppptimer", ppptimer, ppp);
120         }
121
122         pinit(ppp, ppp->lcp);
123         setphase(ppp, Plink);
124 }
125
126 static void
127 setphase(PPP *ppp, int phase)
128 {
129         int oldphase;
130
131         oldphase = ppp->phase;
132
133         ppp->phase = phase;
134         switch(phase){
135         default:
136                 panic("ppp: unknown phase %d", phase);
137         case Pdead:
138                 /* restart or exit? */
139                 pinit(ppp, ppp->lcp);
140                 setphase(ppp, Plink);
141                 break;
142         case Plink:
143                 /* link down */
144                 switch(oldphase) {
145                 case Pnet:
146                         newstate(ppp, ppp->ipcp, Sclosed);
147                 }
148                 break;
149         case Pauth:
150                 if(ppp->usepap)
151                         sendpap(ppp);
152                 else if(!ppp->usechap)
153                         setphase(ppp, Pnet);
154                 break;
155         case Pnet:
156                 pinit(ppp, ppp->ipcp);
157                 break;
158         case Pterm:
159                 /* what? */
160                 break;
161         }
162 }
163
164 static void
165 pinit(PPP *ppp, Pstate *p)
166 {
167         p->timeout = 0;
168
169         switch(p->proto){
170         case Plcp:
171                 ppp->magic = TK2MS(MACHP(0)->ticks);
172                 ppp->xctlmap = 0xffffffff;
173                 ppp->period = 0;
174                 p->optmask = 0xffffffff;
175                 ppp->rctlmap = 0;
176                 ppp->ipcp->state = Sclosed;
177                 ppp->ipcp->optmask = 0xffffffff;
178
179                 /* quality goo */
180                 ppp->timeout = 0;
181                 memset(&ppp->in, 0, sizeof(ppp->in));
182                 memset(&ppp->out, 0, sizeof(ppp->out));
183                 memset(&ppp->pin, 0, sizeof(ppp->pin));
184                 memset(&ppp->pout, 0, sizeof(ppp->pout));
185                 memset(&ppp->sin, 0, sizeof(ppp->sin));
186                 break;
187         case Pipcp:
188                 if(ppp->localfrozen == 0)
189                         invalidate(ppp->local);
190                 if(ppp->remotefrozen == 0)
191                         invalidate(ppp->remote);
192                 p->optmask = 0xffffffff;
193                 ppp->ctcp = compress_init(ppp->ctcp);
194                 ppp->usedns = 3;
195                 invalidate(ppp->dns1);
196                 invalidate(ppp->dns2);
197                 break;
198         }
199         p->confid = p->rcvdconfid = -1;
200         config(ppp, p, 1);
201         newstate(ppp, p, Sreqsent);
202 }
203
204 /*
205  *  change protocol to a new state.
206  */
207 static void
208 newstate(PPP *ppp, Pstate *p, int state)
209 {
210         netlog(ppp->f, Logppp, "0x%x 0x%x %s->%s ctlmap 0x%lx/0x%lx flags 0x%x mtu %d mru %d\n", ppp, p->proto,
211                 snames[p->state], snames[state], ppp->rctlmap, ppp->xctlmap, p->flags,
212                 ppp->mtu, ppp->mru);
213
214         if(p->proto == Plcp) {
215                 if(state == Sopened)
216                         setphase(ppp, Pauth);
217                 else if(state == Sclosed)
218                         setphase(ppp, Pdead);
219                 else if(p->state == Sopened)
220                         setphase(ppp, Plink);
221         }
222
223         if(p->proto == Pipcp && state == Sopened && validv4(ppp->local) && validv4(ppp->remote)){
224                 netlog(ppp->f, Logppp, "pppnewstate: local %I remote %I\n", ppp->local, ppp->remote);
225                 ipmove(pppdns[0], ppp->dns1);
226                 ipmove(pppdns[1], ppp->dns2);
227                 ipconnect(ppp);
228                 /* if this is the only network, set up a default route */
229 //              if(ppp->ifc->link==nil)         /* how??? */
230                         setdefroute(ppp, ppp->remote);
231                 errlog(ppp, Enoerror);
232         }
233
234         p->state = state;
235 }
236
237 static void
238 remove(PPP *ppp)
239 {
240         free(ppp->ipcp);
241         ppp->ipcp = 0;
242         free(ppp->ctcp);
243         ppp->ctcp = 0;
244         free(ppp->lcp);
245         ppp->lcp = 0;
246         if (ppp->inbuf) {
247                 freeb(ppp->inbuf);
248                 ppp->inbuf = nil;
249         }
250         if (ppp->outbuf) {
251                 freeb(ppp->outbuf);
252                 ppp->outbuf = nil;
253         }
254         free(ppp);
255 }
256
257 void
258 pppclose(PPP *ppp)
259 {
260         hangup(ppp);
261         remove(ppp);
262 }
263
264 static void
265 dumpblock(Block *b)
266 {
267         char x[256];
268         int i;
269
270         for(i = 0; i < (sizeof(x)-1)/3 && b->rp+i < b->wp; i++)
271                 sprint(&x[3*i], "0x%2.2x ", b->rp[i]);
272         print("%s\n", x);
273 }
274
275 /* returns (protocol, information) */
276 static int
277 getframe(PPP *ppp, Block **info)
278 {
279         uchar *p, *from, *to;
280         int n, len, proto;
281         ulong c;
282         ushort fcs;
283         Block *buf, *b;
284
285         buf = ppp->inbuf;
286         for(;;){
287                 /* read till we hit a frame byte or run out of room */
288                 for(p = buf->rp; buf->wp < buf->lim;){
289                         for(; p < buf->wp; p++)
290                                 if(*p == HDLC_frame)
291                                         goto break2;
292
293                         len = buf->lim - buf->wp;
294                         n = 0;
295                         if(ppp->dchan != nil)
296                                 n = kchanio(ppp->dchan, buf->wp, len, OREAD);
297                                 netlog(ppp->f, Logppp, "ppp kchanio %d bytes\n", n);
298                         if(n <= 0){
299                                 buf->wp = buf->rp;
300 //                              if(n < 0)
301 //                                      print("ppp kchanio(%s) returned %d: %r",
302 //                                              ppp->dchan->path->elem, n);
303                                 *info = nil;
304                                 return 0;
305                         }
306                         buf->wp += n;
307                 }
308 break2:
309
310                 /* copy into block, undoing escapes, and caculating fcs */
311                 fcs = PPP_initfcs;
312                 b = allocb(p - buf->rp);
313                 to = b->wp;
314                 for(from = buf->rp; from != p;){
315                         c = *from++;
316                         if(c == HDLC_esc){
317                                 if(from == p)
318                                         break;
319                                 c = *from++ ^ 0x20;
320                         } else if((c < 0x20) && (ppp->rctlmap & (1 << c)))
321                                 continue;
322                         *to++ = c;
323                         fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
324                 }
325
326                 /* copy down what's left in buffer */
327                 p++;
328                 memmove(buf->rp, p, buf->wp - p);
329                 n = p - buf->rp;
330                 buf->wp -= n;
331                 b->wp = to - 2;
332
333                 /* return to caller if checksum matches */
334                 if(fcs == PPP_goodfcs){
335                         if(b->rp[0] == PPP_addr && b->rp[1] == PPP_ctl)
336                                 b->rp += 2;
337                         proto = *b->rp++;
338                         if((proto & 0x1) == 0)
339                                 proto = (proto<<8) | *b->rp++;
340                         if(b->rp < b->wp){
341                                 ppp->in.bytes += n;
342                                 ppp->in.packets++;
343                                 *info = b;
344                                 return proto;
345                         }
346                 } else if(BLEN(b) > 0){
347                         ppp->ifc->inerr++;
348                         ppp->in.discards++;
349                         netlog(ppp->f, Logppp, "len %d/%d cksum 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
350                                 BLEN(b), BLEN(buf), fcs, b->rp[0],
351                                 b->rp[1], b->rp[2], b->rp[3]);
352                 }
353
354                 freeblist(b);
355         }
356         *info = nil;
357         return 0;
358 }
359
360 /* send a PPP frame */
361 static Block *
362 putframe(PPP *ppp, int proto, Block *b)
363 {
364         Block *buf;
365         uchar *to, *from;
366         ushort fcs;
367         ulong ctlmap;
368         int c;
369         Block *bp;
370
371         if(ppp->dchan == nil){
372                 netlog(ppp->f, Logppp, "putframe: dchan down\n");
373                 errlog(ppp, Ehungup);
374                 return b;
375         }
376         netlog(ppp->f, Logppp, "putframe 0x%x %d %d (%d bytes)\n", proto, b->rp[0], b->rp[1], BLEN(b));
377
378         ppp->out.packets++;
379
380         if(proto == Plcp)
381                 ctlmap = 0xffffffff;
382         else
383                 ctlmap = ppp->xctlmap;
384
385         /* make sure we have head room */
386         if(b->rp - b->base < 4){
387                 b = padblock(b, 4);
388                 b->rp += 4;
389         }
390
391         /* add in the protocol and address, we'd better have left room */
392         from = b->rp;
393         *--from = proto;
394         if(!(ppp->lcp->flags&Fpc) || proto > 0x100 || proto == Plcp)
395                 *--from = proto>>8;
396         if(!(ppp->lcp->flags&Fac) || proto == Plcp){
397                 *--from = PPP_ctl;
398                 *--from = PPP_addr;
399         }
400
401         qlock(&ppp->outlock);
402         buf = ppp->outbuf;
403
404         /* escape and checksum the body */
405         fcs = PPP_initfcs;
406         to = buf->rp;
407
408         *to++ = HDLC_frame;
409
410         for(bp = b; bp; bp = bp->next){
411                 if(bp != b)
412                         from = bp->rp;
413                 for(; from < bp->wp; from++){
414                         c = *from;
415                         if(c == HDLC_frame || c == HDLC_esc
416                            || (c < 0x20 && ((1<<c) & ctlmap))){
417                                 *to++ = HDLC_esc;
418                                 *to++ = c ^ 0x20;
419                         } else 
420                                 *to++ = c;
421                         fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
422                 }
423         }
424
425         /* add on and escape the checksum */
426         fcs = ~fcs;
427         c = fcs;
428         if(c == HDLC_frame || c == HDLC_esc
429            || (c < 0x20 && ((1<<c) & ctlmap))){
430                 *to++ = HDLC_esc;
431                 *to++ = c ^ 0x20;
432         } else 
433                 *to++ = c;
434         c = fcs>>8;
435         if(c == HDLC_frame || c == HDLC_esc
436            || (c < 0x20 && ((1<<c) & ctlmap))){
437                 *to++ = HDLC_esc;
438                 *to++ = c ^ 0x20;
439         } else 
440                 *to++ = c;
441
442         /* add frame marker and send */
443         *to++ = HDLC_frame;
444         buf->wp = to;
445         if(ppp->dchan == nil){
446                 netlog(ppp->f, Logppp, "putframe: dchan down\n");
447                 errlog(ppp, Ehungup);
448         }else{
449                 kchanio(ppp->dchan, buf->rp, BLEN(buf), OWRITE);
450                 ppp->out.bytes += BLEN(buf);
451         }
452
453         qunlock(&ppp->outlock);
454         return b;
455 }
456
457 #define IPB2LCP(b) ((Lcpmsg*)((b)->wp-4))
458
459 static Block*
460 alloclcp(int code, int id, int len)
461 {
462         Block *b;
463         Lcpmsg *m;
464
465         /*
466          *  leave room for header
467          */
468         b = allocb(len);
469
470         m = (Lcpmsg*)b->wp;
471         m->code = code;
472         m->id = id;
473         b->wp += 4;
474
475         return b;
476 }
477
478 static void
479 putao(Block *b, int type, int aproto, int alg)
480 {
481         *b->wp++ = type;
482         *b->wp++ = 5;
483         hnputs(b->wp, aproto);
484         b->wp += 2;
485         *b->wp++ = alg;
486 }
487
488 static void
489 putlo(Block *b, int type, ulong val)
490 {
491         *b->wp++ = type;
492         *b->wp++ = 6;
493         hnputl(b->wp, val);
494         b->wp += 4;
495 }
496
497 static void
498 putv4o(Block *b, int type, Ipaddr val)
499 {
500         *b->wp++ = type;
501         *b->wp++ = 6;
502         if(v6tov4(b->wp, val) < 0){
503                 /*panic("putv4o")*/;
504         }
505         b->wp += 4;
506 }
507
508 static void
509 putso(Block *b, int type, ulong val)
510 {
511         *b->wp++ = type;
512         *b->wp++ = 4;
513         hnputs(b->wp, val);
514         b->wp += 2;
515 }
516
517 static void
518 puto(Block *b, int type)
519 {
520         *b->wp++ = type;
521         *b->wp++ = 2;
522 }
523
524 /*
525  *  send configuration request
526  */
527 static void
528 config(PPP *ppp, Pstate *p, int newid)
529 {
530         Block *b;
531         Lcpmsg *m;
532         int id;
533
534         if(newid){
535                 id = ++(p->id);
536                 p->confid = id;
537                 p->timeout = Timeout;
538         } else
539                 id = p->confid;
540         b = alloclcp(Lconfreq, id, 256);
541         m = IPB2LCP(b);
542         USED(m);
543
544         switch(p->proto){
545         case Plcp:
546                 if(p->optmask & Fmagic)
547                         putlo(b, Omagic, ppp->magic);
548                 if(p->optmask & Fmtu)
549                         putso(b, Omtu, ppp->mru);
550                 if(p->optmask & Fac)
551                         puto(b, Oac);
552                 if(p->optmask & Fpc)
553                         puto(b, Opc);
554                 if(p->optmask & Fctlmap)
555                         putlo(b, Octlmap, 0);   /* we don't want anything escaped */
556                 break;
557         case Pipcp:
558                 if((p->optmask & Fipaddr) /*&& validv4(ppp->local)*/)
559                         putv4o(b, Oipaddr, ppp->local);
560                 if(!nocompress && (p->optmask & Fipcompress)){
561                         *b->wp++ = Oipcompress;
562                         *b->wp++ = 6;
563                         hnputs(b->wp, Pvjctcp);
564                         b->wp += 2;
565                         *b->wp++ = MAX_STATES-1;
566                         *b->wp++ = 1;
567                 }
568                 if(ppp->usedns & 1)
569                         putlo(b, Oipdns, 0);
570                 if(ppp->usedns & 2)
571                         putlo(b, Oipdns2, 0);
572                 break;
573         }
574
575         hnputs(m->len, BLEN(b));
576         b = putframe(ppp, p->proto, b);
577         freeblist(b);
578 }
579
580 /*
581  *  parse configuration request, sends an ack or reject packet
582  *
583  *      returns:        -1 if request was syntacticly incorrect
584  *                       0 if packet was accepted
585  *                       1 if packet was rejected
586  */
587 static int
588 getopts(PPP *ppp, Pstate *p, Block *b)
589 {
590         Lcpmsg *m, *repm;       
591         Lcpopt *o;
592         uchar *cp;
593         ulong rejecting, nacking, flags, proto;
594         ulong mtu, ctlmap, period;
595         ulong x;
596         Block *repb;
597         Ipaddr ipaddr;
598
599         rejecting = 0;
600         nacking = 0;
601         flags = 0;
602
603         /* defaults */
604         invalidate(ipaddr);
605         mtu = ppp->mtu;
606
607         ctlmap = 0xffffffff;
608         period = 0;
609
610         m = (Lcpmsg*)b->rp;
611         repb = alloclcp(Lconfack, m->id, BLEN(b));
612         repm = IPB2LCP(repb);
613
614         /* copy options into ack packet */
615         memmove(repm->data, m->data, b->wp - m->data);
616         repb->wp += b->wp - m->data;
617
618         /* look for options we don't recognize or like */
619         for(cp = m->data; cp < b->wp; cp += o->len){
620                 o = (Lcpopt*)cp;
621                 if(cp + o->len > b->wp || o->len == 0){
622                         freeblist(repb);
623                         netlog(ppp->f, Logppp, "ppp %s: bad option length 0x%x\n", ppp->ifc->dev,
624                                 o->type);
625                         return -1;
626                 }
627
628                 switch(p->proto){
629                 case Plcp:
630                         switch(o->type){
631                         case Oac:
632                                 flags |= Fac;
633                                 continue;
634                         case Opc:
635                                 flags |= Fpc;
636                                 continue;
637                         case Omtu:
638                                 mtu = nhgets(o->data);
639                                 if(mtu < ppp->ifc->m->mintu){
640                                         netlog(ppp->f, Logppp, "bogus mtu %d\n", mtu);
641                                         mtu = ppp->ifc->m->mintu;
642                                 }
643                                 continue;
644                         case Omagic:
645                                 if(ppp->magic == nhgetl(o->data))
646                                         netlog(ppp->f, Logppp, "ppp: possible loop\n");
647                                 continue;
648                         case Octlmap:
649                                 ctlmap = nhgetl(o->data);
650                                 continue;
651                         case Oquality:
652                                 proto = nhgets(o->data);
653                                 if(proto != Plqm)
654                                         break;
655                                 x = nhgetl(o->data+2)*10;
656                                 period = (x+Period-1)/Period;
657                                 continue;
658                         case Oauth:
659                                 proto = nhgets(o->data);
660                                 if(proto == Ppap && ppp->chapname[0] && ppp->secret[0]){
661                                         ppp->usepap = 1;
662                                         netlog(ppp->f, Logppp, "PPP %s: select PAP\n", ppp->ifc->dev);
663                                         continue;
664                                 }
665                                 if(proto != Pchap || o->data[2] != APmd5){
666                                         if(!nacking){
667                                                 nacking = 1;
668                                                 repb->wp = repm->data;
669                                                 repm->code = Lconfnak;
670                                         }
671                                         putao(repb, Oauth, Pchap, APmd5);
672                                 }
673                                 else
674                                         ppp->usechap = 1;
675                                 ppp->usepap = 0;
676                                 continue;
677                         }
678                         break;
679                 case Pipcp:
680                         switch(o->type){
681                         case Oipaddr:   
682                                 v4tov6(ipaddr, o->data);
683                                 if(!validv4(ppp->remote))
684                                         continue;
685                                 if(!validv4(ipaddr) && !rejecting){
686                                         /* other side requesting an address */
687                                         if(!nacking){
688                                                 nacking = 1;
689                                                 repb->wp = repm->data;
690                                                 repm->code = Lconfnak;
691                                         }
692                                         putv4o(repb, Oipaddr, ppp->remote);
693                                 }
694                                 continue;
695                         case Oipcompress:
696                                 proto = nhgets(o->data);
697                                 if(nocompress || proto != Pvjctcp || compress_negotiate(ppp->ctcp, o->data+2) < 0)
698                                         break;
699                                 flags |= Fipcompress;
700                                 continue;
701                         }
702                         break;
703                 }
704
705                 /* come here if option is not recognized */
706                 if(!rejecting){
707                         rejecting = 1;
708                         repb->wp = repm->data;
709                         repm->code = Lconfrej;
710                 }
711                 netlog(ppp->f, Logppp, "ppp %s: bad 0x%x option %d\n", ppp->ifc->dev, p->proto, o->type);
712                 memmove(repb->wp, o, o->len);
713                 repb->wp += o->len;
714         }
715
716         /* permanent changes only after we know that we liked the packet */
717         if(!rejecting && !nacking){
718                 switch(p->proto){
719                 case Plcp:
720                         netlog(ppp->f, Logppp, "Plcp: mtu: %d %d x:0x%lx/r:0x%lx 0x%lx\n", mtu, ppp->mtu, ppp->xctlmap, ppp->rctlmap, ctlmap);
721                         ppp->period = period;
722                         ppp->xctlmap = ctlmap;
723                         if(mtu > Maxmtu)
724                                 mtu = Maxmtu;
725                         if(mtu < Minmtu)
726                                 mtu = Minmtu;
727                         ppp->mtu = mtu;
728                         break;
729                 case Pipcp:
730                         if(validv4(ipaddr) && ppp->remotefrozen == 0)
731                                 ipmove(ppp->remote, ipaddr);
732                         break;
733                 }
734                 p->flags = flags;
735         }
736
737         hnputs(repm->len, BLEN(repb));
738         repb = putframe(ppp, p->proto, repb);
739         freeblist(repb);
740
741         return rejecting || nacking;
742 }
743
744 /*
745  *  parse configuration rejection, just stop sending anything that they
746  *  don't like (except for ipcp address nak).
747  */
748 static void
749 rejopts(PPP *ppp, Pstate *p, Block *b, int code)
750 {
751         Lcpmsg *m;
752         Lcpopt *o;
753
754         /* just give up trying what the other side doesn't like */
755         m = (Lcpmsg*)b->rp;
756         for(b->rp = m->data; b->rp < b->wp; b->rp += o->len){
757                 o = (Lcpopt*)b->rp;
758                 if(b->rp + o->len > b->wp || o->len == 0){
759                         netlog(ppp->f, Logppp, "ppp %s: bad roption length 0x%x\n", ppp->ifc->dev,
760                                 o->type);
761                         return;
762                 }
763
764                 if(code == Lconfrej){
765                         if(o->type < 8*sizeof(p->optmask))
766                                 p->optmask &= ~(1<<o->type);
767                         if(o->type == Oipdns)
768                                 ppp->usedns &= ~1;
769                         else if(o->type == Oipdns2)
770                                 ppp->usedns &= ~2;
771                         netlog(ppp->f, Logppp, "ppp %s: 0x%x rejecting %d\n", ppp->ifc->dev, p->proto,
772                                 o->type);
773                         continue;
774                 }
775
776                 switch(p->proto){
777                 case Plcp:
778                         switch(o->type){
779                         case Octlmap:
780                                 ppp->rctlmap = nhgetl(o->data);
781                                 break;
782                         default:
783                                 if(o->type < 8*sizeof(p->optmask))
784                                         p->optmask &= ~(1<<o->type);
785                                 break;
786                         };
787                 case Pipcp:
788                         switch(o->type){
789                         case Oipaddr:
790                                 if(!validv4(ppp->local))
791                                         v4tov6(ppp->local, o->data);
792 //                              if(o->type < 8*sizeof(p->optmask))
793 //                                      p->optmask &= ~(1<<o->type);
794                                 break;
795                         case Oipdns:
796                                 if(!validv4(ppp->dns1))
797                                         v4tov6(ppp->dns1, o->data);
798                                 ppp->usedns &= ~1;
799                                 break;
800                         case Oipdns2:
801                                 if(!validv4(ppp->dns2))
802                                         v4tov6(ppp->dns2, o->data);
803                                 ppp->usedns &= ~2;
804                                 break;
805                         default:
806                                 if(o->type < 8*sizeof(p->optmask))
807                                         p->optmask &= ~(1<<o->type);
808                                 break;
809                         }
810                         break;
811                 }
812         }
813 }
814
815
816 /*
817  *  put a messages through the lcp or ipcp state machine.  They are
818  *  very similar.
819  */
820 static void
821 rcv(PPP *ppp, Pstate *p, Block *b)
822 {
823         ulong len;
824         int err;
825         Lcpmsg *m;
826
827         if(BLEN(b) < 4){
828                 netlog(ppp->f, Logppp, "ppp %s: short lcp message\n", ppp->ifc->dev);
829                 freeblist(b);
830                 return;
831         }
832         m = (Lcpmsg*)b->rp;
833         len = nhgets(m->len);
834         if(BLEN(b) < len){
835                 netlog(ppp->f, Logppp, "ppp %s: short lcp message\n", ppp->ifc->dev);
836                 freeblist(b);
837                 return;
838         }
839
840         netlog(ppp->f, Logppp, "ppp: 0x%x rcv %d len %d id %d/%d/%d\n",
841                 p->proto, m->code, len, m->id, p->confid, p->id);
842
843         if(p->proto != Plcp && ppp->lcp->state != Sopened){
844                 netlog(ppp->f, Logppp, "ppp: non-lcp with lcp not open\n");
845                 freeb(b);
846                 return;
847         }
848
849         qlock(ppp);
850         switch(m->code){
851         case Lconfreq:
852                 /* flush the output queue */
853                 if(p->state == Sopened && p->proto == Plcp)
854                         kchanio(ppp->cchan, "f", 1, OWRITE);
855
856                 printopts(ppp, p, b, 0);
857                 err = getopts(ppp, p, b);
858                 if(err < 0)
859                         break;
860
861                 if(m->id == p->rcvdconfid)
862                         break;                  /* don't change state for duplicates */
863                 p->rcvdconfid = m->id;
864
865                 switch(p->state){
866                 case Sackrcvd:
867                         if(err)
868                                 break;
869                         newstate(ppp, p, Sopened);
870                         break;
871                 case Sclosed:
872                 case Sopened:
873                         config(ppp, p, 1);
874                         if(err == 0)
875                                 newstate(ppp, p, Sacksent);
876                         else
877                                 newstate(ppp, p, Sreqsent);
878                         break;
879                         break;
880                 case Sreqsent:
881                 case Sacksent:
882                         if(err == 0)
883                                 newstate(ppp, p, Sacksent);
884                         else
885                                 newstate(ppp, p, Sreqsent);
886                         break;
887                 }
888                 break;
889         case Lconfack:
890                 if(p->confid != m->id){
891                         /* ignore if it isn't the message we're sending */
892                         netlog(ppp->f, Logppp, "ppp: dropping confack\n");
893                         break;
894                 }
895                 p->confid = -1;         /* ignore duplicates */
896                 p->id++;                /* avoid sending duplicates */
897
898                 switch(p->state){
899                 case Sopened:
900                 case Sackrcvd:
901                         config(ppp, p, 1);
902                         newstate(ppp, p, Sreqsent);
903                         break;
904                 case Sreqsent:
905                         newstate(ppp, p, Sackrcvd);
906                         break;
907                 case Sacksent:
908                         newstate(ppp, p, Sopened);
909                         break;
910                 }
911                 break;
912         case Lconfrej:
913         case Lconfnak:
914                 if(p->confid != m->id) {
915                         /* ignore if it isn't the message we're sending */
916                         netlog(ppp->f, Logppp, "ppp: dropping confrej or confnak\n");
917                         break;
918                 }
919                 p->confid = -1;         /* ignore duplicates */
920                 p->id++;                /* avoid sending duplicates */
921
922                 switch(p->state){
923                 case Sopened:
924                 case Sackrcvd:
925                         config(ppp, p, 1);
926                         newstate(ppp, p, Sreqsent);
927                         break;
928                 case Sreqsent:
929                 case Sacksent:
930                         printopts(ppp, p, b, 0);
931                         rejopts(ppp, p, b, m->code);
932                         config(ppp, p, 1);
933                         break;
934                 }
935                 break;
936         case Ltermreq:
937                 m->code = Ltermack;
938                 b = putframe(ppp, p->proto, b);
939
940                 switch(p->state){
941                 case Sackrcvd:
942                 case Sacksent:
943                         newstate(ppp, p, Sreqsent);
944                         break;
945                 case Sopened:
946                         newstate(ppp, p, Sclosing);
947                         break;
948                 }
949                 break;
950         case Ltermack:
951                 if(p->termid != m->id)  /* ignore if it isn't the message we're sending */
952                         break;
953
954                 if(p->proto == Plcp)
955                         ppp->ipcp->state = Sclosed;
956                 switch(p->state){
957                 case Sclosing:
958                         newstate(ppp, p, Sclosed);
959                         break;
960                 case Sackrcvd:
961                         newstate(ppp, p, Sreqsent);
962                         break;
963                 case Sopened:
964                         config(ppp, p, 0);
965                         newstate(ppp, p, Sreqsent);
966                         break;
967                 }
968                 break;
969         case Lcoderej:
970                 netlog(ppp->f, Logppp, "ppp %s: code reject %d\n", ppp->ifc->dev, m->data[0]);
971                 break;
972         case Lprotorej:
973                 netlog(ppp->f, Logppp, "ppp %s: proto reject 0x%lx\n", ppp->ifc->dev, nhgets(m->data));
974                 break;
975         case Lechoreq:
976                 m->code = Lechoack;
977                 b = putframe(ppp, p->proto, b);
978                 break;
979         case Lechoack:
980         case Ldiscard:
981                 /* nothing to do */
982                 break;
983         }
984
985         qunlock(ppp);
986         freeblist(b);
987 }
988
989 /*
990  *  timer for protocol state machine
991  */
992 static void
993 ptimer(PPP *ppp, Pstate *p)
994 {
995         if(p->state == Sopened || p->state == Sclosed)
996                 return;
997
998         p->timeout--;
999         switch(p->state){
1000         case Sclosing:
1001                 sendtermreq(ppp, p);
1002                 break;
1003         case Sreqsent:
1004         case Sacksent:
1005                 if(p->timeout <= 0){
1006                         if(p->proto && ppp->cchan != nil)
1007                                 kchanio(ppp->cchan, "f", 1, OWRITE); /* flush output queue */
1008                         newstate(ppp, p, Sclosed);
1009                 } else {
1010                         config(ppp, p, 0);
1011                 }
1012                 break;
1013         case Sackrcvd:
1014                 if(p->timeout <= 0){
1015                         if(p->proto && ppp->cchan != nil)
1016                                 kchanio(ppp->cchan, "f", 1, OWRITE); /* flush output queue */
1017                         newstate(ppp, p, Sclosed);
1018                 }
1019                 else {
1020                         config(ppp, p, 0);
1021                         newstate(ppp, p, Sreqsent);
1022                 }
1023                 break;
1024         }
1025 }
1026
1027 /*
1028  *  timer for ppp
1029  */
1030 static void
1031 ppptimer(void *arg)
1032 {
1033         PPP *ppp;
1034
1035         ppp = arg;
1036         ppp->timep = up;
1037         if(waserror()){
1038                 netlog(ppp->f, Logppp, "ppptimer: %I: %s\n", ppp->local, up->env->errstr);
1039                 ppp->timep = 0;
1040                 pexit("hangup", 1);
1041         }
1042         for(;;){
1043                 udelay_sched(Period * 1000);
1044                 if(ppp->pppup){
1045                         qlock(ppp);
1046
1047                         ptimer(ppp, ppp->lcp);
1048                         if(ppp->lcp->state == Sopened)
1049                                 ptimer(ppp, ppp->ipcp);
1050
1051                         if(ppp->period && --(ppp->timeout) <= 0){
1052                                 ppp->timeout = ppp->period;
1053                                 putlqm(ppp);
1054                         }
1055
1056                         qunlock(ppp);
1057                 }
1058         }
1059 }
1060
1061 static void
1062 setdefroute(PPP *ppp, Ipaddr gate)
1063 {
1064         int fd, n;
1065         char path[128], msg[128];
1066
1067         snprint(path, sizeof path, "#I%d/iproute", ppp->f->dev);
1068         fd = kopen(path, ORDWR);
1069         if(fd < 0)
1070                 return;
1071         n = snprint(msg, sizeof(msg), "add 0 0 %I", gate);
1072         kwrite(fd, msg, n);
1073         kclose(fd);
1074 }
1075
1076 static void
1077 ipconnect(PPP *ppp)
1078 {
1079         int fd, n;
1080         char path[128], msg[128];
1081
1082         snprint(path, sizeof path, "#I%d/ipifc/%d/ctl", ppp->f->dev, ppp->ifc->conv->x);
1083         fd = kopen(path, ORDWR);
1084         if(fd < 0)
1085                 return;
1086         n = snprint(msg, sizeof(msg), "connect %I 255.255.255.255 %I", ppp->local, ppp->remote);
1087         if (kwrite(fd, msg, n) != n)
1088                 print("ppp ipconnect: %s: %r\n", msg);
1089         kclose(fd);
1090 }
1091
1092 PPP*
1093 pppopen(PPP *ppp, char *dev,
1094         Ipaddr ipaddr, Ipaddr remip,
1095         int mtu, int framing,
1096         char *chapname, char *secret)
1097 {
1098         int fd, cfd;
1099         char ctl[Maxpath];
1100
1101         invalidate(ppp->remote);
1102         invalidate(ppp->local);
1103         invalidate(ppp->dns1);
1104         invalidate(ppp->dns2);
1105         ppp->mtu = Defmtu;
1106         ppp->mru = mtu;
1107         ppp->framing = framing;
1108
1109         if(remip != nil && validv4(remip)){
1110                 ipmove(ppp->remote, remip);
1111                 ppp->remotefrozen = 1;
1112         }
1113         if(ipaddr != nil && validv4(ipaddr)){
1114                 ipmove(ppp->local, ipaddr);
1115                 ppp->localfrozen = 1;
1116         }
1117
1118         /* authentication goo */
1119         ppp->secret[0] = 0;
1120         if(secret != nil)
1121                 strncpy(ppp->secret, secret, sizeof(ppp->secret));
1122         ppp->chapname[0] = 0;
1123         if(chapname != nil)
1124                 strncpy(ppp->chapname, chapname, sizeof(ppp->chapname));
1125
1126         if(strchr(dev, '!'))
1127                 fd = kdial(dev, nil, nil, nil);
1128         else
1129                 fd = kopen(dev, ORDWR);
1130         if(fd < 0){
1131                 netlog(ppp->f, Logppp, "ppp: can't open %s\n", dev);
1132                 return nil;
1133         }
1134         ppp->dchan = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
1135         kclose(fd);
1136
1137         /* set up serial line */
1138 /* XXX this stuff belongs in application, not driver */
1139         sprint(ctl, "%sctl", dev);
1140         cfd = kopen(ctl, ORDWR);
1141         if(cfd >= 0){
1142                 ppp->cchan = fdtochan(up->env->fgrp, cfd, ORDWR, 0, 1);
1143                 kclose(cfd);
1144                 kchanio(ppp->cchan, "m1", 2, OWRITE);   /* cts/rts flow control/fifo's) on */
1145                 kchanio(ppp->cchan, "q64000", 6, OWRITE);/* increas q size to 64k */
1146                 kchanio(ppp->cchan, "n1", 2, OWRITE);   /* nonblocking writes on */
1147                 kchanio(ppp->cchan, "r1", 2, OWRITE);   /* rts on */
1148                 kchanio(ppp->cchan, "d1", 2, OWRITE);   /* dtr on */
1149         }
1150
1151         ppp->pppup = 1;
1152         init(ppp);
1153         return ppp;
1154 }
1155
1156 static void
1157 hangup(PPP *ppp)
1158 {
1159         qlock(ppp);
1160         if(waserror()){
1161                 qunlock(ppp);
1162                 nexterror();
1163         }
1164         netlog(ppp->f, Logppp, "PPP Hangup\n");
1165         errlog(ppp, Ehungup);
1166         if(ppp->pppup && ppp->cchan != nil){
1167                 kchanio(ppp->cchan, "f", 1, OWRITE);    /* flush */
1168                 kchanio(ppp->cchan, "h", 1, OWRITE);    /* hangup */
1169         }
1170         cclose(ppp->dchan);
1171         cclose(ppp->cchan);
1172         ppp->dchan = nil;
1173         ppp->cchan = nil;
1174         ppp->pppup = 0;
1175         qunlock(ppp);
1176         poperror();
1177 }
1178
1179 /* return next input IP packet */
1180 Block*
1181 pppread(PPP *ppp)
1182 {
1183         Block *b;
1184         int proto;
1185         Lcpmsg *m;
1186
1187         for(;;){
1188                 proto = getframe(ppp, &b);
1189                 if(b == nil)
1190                         return nil;
1191                 netlog(ppp->f, Logppp, "ppp: read proto %d len %d\n", proto, blocklen(b));
1192                 switch(proto){
1193                 case Plcp:
1194                         rcv(ppp, ppp->lcp, b);
1195                         break;
1196                 case Pipcp:
1197                         rcv(ppp, ppp->ipcp, b);
1198                         break;
1199                 case Pip:
1200                         if(ppp->ipcp->state == Sopened)
1201                                 return b;
1202                         freeblist(b);
1203                         break;
1204                 case Plqm:
1205                         getlqm(ppp, b);
1206                         break;
1207                 case Pchap:
1208                         getchap(ppp, b);
1209                         break;
1210                 case Ppap:
1211                         getpap(ppp, b);
1212                         break;
1213                 case Pvjctcp:
1214                 case Pvjutcp:
1215                         if(ppp->ipcp->state == Sopened){
1216                                 b = tcpuncompress(ppp->ctcp, b, proto, ppp->f);
1217                                 if(b != nil)
1218                                         return b;
1219                         }
1220                         freeblist(b);
1221                         break;
1222                 default:
1223                         netlog(ppp->f, Logppp, "unknown proto 0x%x\n", proto);
1224                         if(ppp->lcp->state == Sopened){
1225                                 /* reject the protocol */
1226                                 b->rp -= 6;
1227                                 m = (Lcpmsg*)b->rp;
1228                                 m->code = Lprotorej;
1229                                 m->id = ++ppp->lcp->id;
1230                                 hnputs(m->data, proto);
1231                                 hnputs(m->len, BLEN(b));
1232                                 b = putframe(ppp, Plcp, b);
1233                         }
1234                         freeblist(b);
1235                         break;
1236                 }
1237         }
1238         return nil;             /* compiler confused */
1239 }
1240
1241 /* transmit an IP packet */
1242 int
1243 pppwrite(PPP *ppp, Block *b)
1244 {
1245         ushort proto;
1246         int r;
1247
1248         qlock(ppp);
1249
1250         /* can't send ip packets till we're established */
1251         if(ppp->ipcp->state != Sopened)
1252                 goto ret;
1253
1254         /* link hung up */
1255         if(ppp->dchan == nil)
1256                 goto ret;
1257
1258         b = concatblock(b);             /* or else compression will barf */
1259
1260         proto = Pip;
1261         if(ppp->ipcp->flags & Fipcompress)
1262                 proto = compress(ppp->ctcp, b, ppp->f);
1263         b = putframe(ppp, proto, b);
1264
1265
1266 ret:
1267         qunlock(ppp);
1268
1269         r = blocklen(b);
1270         netlog(ppp->f, Logppp, "ppp wrt len %d\n", r);
1271
1272         freeblist(b);
1273         return r;
1274 }
1275
1276 /*
1277  *  link quality management
1278  */
1279 static void
1280 getlqm(PPP *ppp, Block *b)
1281 {
1282         Qualpkt *p;
1283
1284         p = (Qualpkt*)b->rp;
1285         if(BLEN(b) == sizeof(Qualpkt)){
1286                 ppp->in.reports++;
1287                 ppp->pout.reports = nhgetl(p->peeroutreports);
1288                 ppp->pout.packets = nhgetl(p->peeroutpackets);
1289                 ppp->pout.bytes = nhgetl(p->peeroutbytes);
1290                 ppp->pin.reports = nhgetl(p->peerinreports);
1291                 ppp->pin.packets = nhgetl(p->peerinpackets);
1292                 ppp->pin.discards = nhgetl(p->peerindiscards);
1293                 ppp->pin.errors = nhgetl(p->peerinerrors);
1294                 ppp->pin.bytes = nhgetl(p->peerinbytes);
1295
1296                 /* save our numbers at time of reception */
1297                 memmove(&ppp->sin, &ppp->in, sizeof(Qualstats));
1298
1299         }
1300         freeblist(b);
1301         if(ppp->period == 0)
1302                 putlqm(ppp);
1303
1304 }
1305 static void
1306 putlqm(PPP *ppp)
1307 {
1308         Qualpkt *p;
1309         Block *b;
1310
1311         b = allocb(sizeof(Qualpkt));
1312         b->wp += sizeof(Qualpkt);
1313         p = (Qualpkt*)b->rp;
1314         hnputl(p->magic, 0);
1315
1316         /* heresay (what he last told us) */
1317         hnputl(p->lastoutreports, ppp->pout.reports);
1318         hnputl(p->lastoutpackets, ppp->pout.packets);
1319         hnputl(p->lastoutbytes, ppp->pout.bytes);
1320
1321         /* our numbers at time of last reception */
1322         hnputl(p->peerinreports, ppp->sin.reports);
1323         hnputl(p->peerinpackets, ppp->sin.packets);
1324         hnputl(p->peerindiscards, ppp->sin.discards);
1325         hnputl(p->peerinerrors, ppp->sin.errors);
1326         hnputl(p->peerinbytes, ppp->sin.bytes);
1327
1328         /* our numbers now */
1329         hnputl(p->peeroutreports, ppp->out.reports+1);
1330         hnputl(p->peeroutpackets, ppp->out.packets+1);
1331         hnputl(p->peeroutbytes, ppp->out.bytes+53/*hack*/);
1332
1333         b = putframe(ppp, Plqm, b);
1334         freeblist(b);
1335         ppp->out.reports++;
1336 }
1337
1338 /*
1339  *  challenge response dialog
1340  */
1341 static void
1342 getchap(PPP *ppp, Block *b)
1343 {
1344         Lcpmsg *m;
1345         int len, vlen, n;
1346         char md5buf[512];
1347
1348         m = (Lcpmsg*)b->rp;
1349         len = nhgets(m->len);
1350         if(BLEN(b) < len){
1351                 netlog(ppp->f, Logppp, "ppp %s: short chap message\n", ppp->ifc->dev);
1352                 freeblist(b);
1353                 return;
1354         }
1355
1356         switch(m->code){
1357         case Cchallenge:
1358                 vlen = m->data[0];
1359                 if(vlen > len - 5){
1360                         netlog(ppp->f, Logppp, "PPP %s: bad challenge len\n", ppp->ifc->dev);
1361                         freeblist(b);
1362                         break;
1363                 }
1364
1365                 netlog(ppp->f, Logppp, "PPP %s: CHAP Challenge\n", ppp->ifc->dev);
1366 netlog(ppp->f, Logppp, "(secret %s chapname %s id %d)\n", ppp->secret, ppp->chapname, m->id);
1367                 /* create string to hash */
1368                 md5buf[0] = m->id;
1369                 strcpy(md5buf+1, ppp->secret);
1370                 n = strlen(ppp->secret) + 1;
1371                 memmove(md5buf+n, m->data+1, vlen);
1372                 n += vlen;
1373                 freeblist(b);
1374
1375                 /* send reply */
1376                 len = 4 + 1 + 16 + strlen(ppp->chapname);
1377                 b = alloclcp(2, md5buf[0], len);
1378                 m = IPB2LCP(b);
1379                 m->data[0] = 16;
1380                 md5((uchar*)md5buf, n, m->data+1, 0);
1381                 memmove((char*)m->data+17, ppp->chapname, strlen(ppp->chapname));
1382                 hnputs(m->len, len);
1383                 b->wp += len-4;
1384                 b = putframe(ppp, Pchap, b);
1385                 break;
1386         case Cresponse:
1387                 netlog(ppp->f, Logppp, "PPP %s: chap response?\n", ppp->ifc->dev);
1388                 break;
1389         case Csuccess:
1390                 netlog(ppp->f, Logppp, "PPP %s: chap succeeded\n", ppp->ifc->dev);
1391                 setphase(ppp, Pnet);
1392                 break;
1393         case Cfailure:
1394                 netlog(ppp->f, Logppp, "PPP %s: chap failed: %.*s\n", ppp->ifc->dev, len-4, m->data);
1395                 errlog(ppp, Eperm);
1396                 break;
1397         default:
1398                 netlog(ppp->f, Logppp, "PPP %s: chap code %d?\n", ppp->ifc->dev, m->code);
1399                 break;
1400         }
1401         freeblist(b);
1402 }
1403
1404 /*
1405  *  password authentication protocol dialog
1406  *      -- obsolete but all we know how to use with NT just now
1407  */
1408 static void
1409 sendpap(PPP *ppp)
1410 {
1411         Lcpmsg *m;
1412         int clen, slen, len;
1413         Block *b;
1414         uchar *p;
1415
1416         clen = strlen(ppp->chapname);
1417         slen = strlen(ppp->secret);
1418         len = 4 + 1 + clen + 1 + slen;
1419         ppp->papid = ++ppp->lcp->id;
1420         b = alloclcp(Cpapreq, ppp->papid, len);
1421         m = IPB2LCP(b);
1422         p = m->data;
1423         p[0] = clen;
1424         memmove(p+1, ppp->chapname, clen);
1425         p += clen + 1;
1426         p[0] = slen;
1427         memmove(p+1, ppp->secret, slen);
1428         hnputs(m->len, len);
1429         b->wp += len-4;
1430         b = putframe(ppp, Ppap, b);
1431         netlog(ppp->f, Logppp, "PPP %s: sent pap auth req (%d)\n", ppp->ifc->dev, len);
1432         freeblist(b);
1433 }
1434
1435 static void
1436 getpap(PPP *ppp, Block *b)
1437 {
1438         Lcpmsg *m;
1439         int len;
1440
1441         m = (Lcpmsg*)b->rp;
1442         len = nhgets(m->len);
1443         if(BLEN(b) < len){
1444                 netlog(ppp->f, Logppp, "ppp %s: short pap message\n", ppp->ifc->dev);
1445                 freeblist(b);
1446                 return;
1447         }
1448
1449         switch(m->code){
1450         case Cpapreq:
1451                 netlog(ppp->f, Logppp, "PPP %s: pap request?\n", ppp->ifc->dev);
1452                 break;
1453         case Cpapack:
1454                 netlog(ppp->f, Logppp, "PPP %s: PAP succeeded\n", ppp->ifc->dev);
1455                 setphase(ppp, Pnet);
1456                 break;
1457         case Cpapnak:
1458                 if(m->data[0])
1459                         netlog(ppp->f, Logppp, "PPP %s: PAP failed: %.*s\n", ppp->ifc->dev, len-5, m->data+1);
1460                 else
1461                         netlog(ppp->f, Logppp, "PPP %s: PAP failed\n", ppp->ifc->dev);
1462                 errlog(ppp, Eperm);
1463                 break;
1464         default:
1465                 netlog(ppp->f, Logppp, "PPP %s: pap code %d?\n", ppp->ifc->dev, m->code);
1466                 break;
1467         }
1468         freeblist(b);
1469 }
1470
1471 static void
1472 printopts(PPP *ppp, Pstate *p, Block *b, int send)
1473 {
1474         Lcpmsg *m;      
1475         Lcpopt *o;
1476         int proto, x, period;
1477         uchar *cp;
1478         char *code, *dir;
1479
1480         m = (Lcpmsg*)b->rp;
1481         switch(m->code) {
1482         default: code = "<unknown>"; break;
1483         case Lconfreq: code = "confrequest"; break;
1484         case Lconfack: code = "confack"; break;
1485         case Lconfnak: code = "confnak"; break;
1486         case Lconfrej: code = "confreject"; break;
1487         }
1488
1489         if(send)
1490                 dir = "send";
1491         else
1492                 dir = "recv";
1493
1494         netlog(ppp->f, Logppp, "ppp: %s %s: id=%d\n", dir, code, m->id);
1495
1496         for(cp = m->data; cp < b->wp; cp += o->len){
1497                 o = (Lcpopt*)cp;
1498                 if(cp + o->len > b->wp || o->len == 0){
1499                         netlog(ppp->f, Logppp, "\tbad option length 0x%x\n", o->type);
1500                         return;
1501                 }
1502
1503                 switch(p->proto){
1504                 case Plcp:
1505                         switch(o->type){
1506                         default:
1507                                 netlog(ppp->f, Logppp, "\tunknown %d len=%d\n", o->type, o->len);
1508                                 break;
1509                         case Omtu:
1510                                 netlog(ppp->f, Logppp, "\tmtu = %d\n", nhgets(o->data));
1511                                 break;
1512                         case Octlmap:
1513                                 netlog(ppp->f, Logppp, "\tctlmap = 0x%x\n", nhgetl(o->data));
1514                                 break;
1515                         case Oauth:
1516                                 netlog(ppp->f, Logppp, "\tauth = ", nhgetl(o->data));
1517                                 proto = nhgets(o->data);
1518                                 switch(proto) {
1519                                 default:
1520                                         netlog(ppp->f, Logppp, "unknown auth proto %d\n", proto);
1521                                         break;
1522                                 case Ppap:
1523                                         netlog(ppp->f, Logppp, "password\n");
1524                                         break;
1525                                 case Pchap:
1526                                         netlog(ppp->f, Logppp, "chap 0x%x\n", o->data[2]);
1527                                         break;
1528                                 }
1529                                 break;
1530                         case Oquality:
1531                                 proto = nhgets(o->data);
1532                                 switch(proto) {
1533                                 default:
1534                                         netlog(ppp->f, Logppp, "\tunknown quality proto %d\n", proto);
1535                                         break;
1536                                 case Plqm:
1537                                         x = nhgetl(o->data+2)*10;
1538                                         period = (x+Period-1)/Period;
1539                                         netlog(ppp->f, Logppp, "\tlqm period = %d\n", period);
1540                                         break;
1541                                 }
1542                         case Omagic:
1543                                 netlog(ppp->f, Logppp, "\tmagic = 0x%x\n", nhgetl(o->data));
1544                                 break;
1545                         case Opc:
1546                                 netlog(ppp->f, Logppp, "\tprotocol compress\n");
1547                                 break;
1548                         case Oac:
1549                                 netlog(ppp->f, Logppp, "\taddr compress\n");
1550                                 break;
1551                         }
1552                         break;
1553                 case Pccp:
1554                         switch(o->type){
1555                         default:
1556                                 netlog(ppp->f, Logppp, "\tunknown %d len=%d\n", o->type, o->len);
1557                                 break;
1558                         case Ocoui:     
1559                                 netlog(ppp->f, Logppp, "\tOUI\n");
1560                                 break;
1561                         case Ocstac:
1562                                 netlog(ppp->f, Logppp, "\tstac LZS\n");
1563                                 break;
1564                         case Ocmppc:    
1565                                 netlog(ppp->f, Logppp, "\tMicrosoft PPC len=%d 0x%x\n", o->len, nhgetl(o->data));
1566                                 break;
1567                         }
1568                         break;
1569                 case Pecp:
1570                         switch(o->type){
1571                         default:
1572                                 netlog(ppp->f, Logppp, "\tunknown %d len=%d\n", o->type, o->len);
1573                                 break;
1574                         case Oeoui:     
1575                                 netlog(ppp->f, Logppp, "\tOUI\n");
1576                                 break;
1577                         case Oedese:
1578                                 netlog(ppp->f, Logppp, "\tDES\n");
1579                                 break;
1580                         }
1581                         break;
1582                 case Pipcp:
1583                         switch(o->type){
1584                         default:
1585                                 netlog(ppp->f, Logppp, "\tunknown %d len=%d\n", o->type, o->len);
1586                                 break;
1587                         case Oipaddrs:  
1588                                 netlog(ppp->f, Logppp, "\tip addrs - deprecated\n");
1589                                 break;
1590                         case Oipcompress:
1591                                 netlog(ppp->f, Logppp, "\tip compress\n");
1592                                 break;
1593                         case Oipaddr:   
1594                                 netlog(ppp->f, Logppp, "\tip addr %V\n", o->data);
1595                                 break;
1596                         case Oipdns:
1597                                 netlog(ppp->f, Logppp, "\tdns addr %V\n", o->data);
1598                                 break;
1599                         case Oipwins:   
1600                                 netlog(ppp->f, Logppp, "\twins addr %V\n", o->data);
1601                                 break;
1602                         case Oipdns2:
1603                                 netlog(ppp->f, Logppp, "\tdns2 addr %V\n", o->data);
1604                                 break;
1605                         case Oipwins2:  
1606                                 netlog(ppp->f, Logppp, "\twins2 addr %V\n", o->data);
1607                                 break;
1608                         }
1609                         break;
1610                 }
1611         }
1612 }
1613
1614 static void
1615 sendtermreq(PPP *ppp, Pstate *p)
1616 {
1617         Block *b;
1618         Lcpmsg *m;
1619
1620         p->termid = ++(p->id);
1621         b = alloclcp(Ltermreq, p->termid, 4);
1622         m = IPB2LCP(b);
1623         hnputs(m->len, 4);
1624         putframe(ppp, p->proto, b);
1625         freeb(b);
1626         newstate(ppp, p, Sclosing);
1627 }
1628
1629 static void
1630 sendechoreq(PPP *ppp, Pstate *p)
1631 {
1632         Block *b;
1633         Lcpmsg *m;
1634
1635         p->termid = ++(p->id);
1636         b = alloclcp(Lechoreq, p->id, 4);
1637         m = IPB2LCP(b);
1638         hnputs(m->len, 4);
1639         putframe(ppp, p->proto, b);
1640         freeb(b);
1641 }
1642
1643 /*
1644  *  return non-zero if this is a valid v4 address
1645  */
1646 static int
1647 validv4(Ipaddr addr)
1648 {
1649         return memcmp(addr, v4prefix, IPv4off) == 0;
1650 }
1651
1652 static void
1653 invalidate(Ipaddr addr)
1654 {
1655         ipmove(addr, IPnoaddr);
1656 }