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