xref: /freebsd/usr.sbin/ppp/lcp.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
1 /*
2  *	      PPP Link Control Protocol (LCP) Module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $Id: lcp.c,v 1.64 1998/09/09 00:03:09 brian Exp $
21  *
22  * TODO:
23  *	o Limit data field length by MRU
24  */
25 
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <netinet/in_systm.h>
29 #include <netinet/ip.h>
30 #include <sys/un.h>
31 
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <termios.h>
37 #include <unistd.h>
38 
39 #include "ua.h"
40 #include "defs.h"
41 #include "command.h"
42 #include "mbuf.h"
43 #include "log.h"
44 #include "timer.h"
45 #include "fsm.h"
46 #include "iplist.h"
47 #include "lcp.h"
48 #include "throughput.h"
49 #include "lcpproto.h"
50 #include "descriptor.h"
51 #include "lqr.h"
52 #include "hdlc.h"
53 #include "ccp.h"
54 #include "async.h"
55 #include "link.h"
56 #include "physical.h"
57 #include "prompt.h"
58 #include "slcompress.h"
59 #include "ipcp.h"
60 #include "filter.h"
61 #include "mp.h"
62 #include "chat.h"
63 #include "auth.h"
64 #include "chap.h"
65 #include "cbcp.h"
66 #include "datalink.h"
67 #include "bundle.h"
68 
69 /* for received LQRs */
70 struct lqrreq {
71   u_char type;
72   u_char length;
73   u_short proto;		/* Quality protocol */
74   u_int32_t period;		/* Reporting interval */
75 };
76 
77 static int LcpLayerUp(struct fsm *);
78 static void LcpLayerDown(struct fsm *);
79 static void LcpLayerStart(struct fsm *);
80 static void LcpLayerFinish(struct fsm *);
81 static void LcpInitRestartCounter(struct fsm *);
82 static void LcpSendConfigReq(struct fsm *);
83 static void LcpSentTerminateReq(struct fsm *);
84 static void LcpSendTerminateAck(struct fsm *, u_char);
85 static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
86                             struct fsm_decode *);
87 
88 static struct fsm_callbacks lcp_Callbacks = {
89   LcpLayerUp,
90   LcpLayerDown,
91   LcpLayerStart,
92   LcpLayerFinish,
93   LcpInitRestartCounter,
94   LcpSendConfigReq,
95   LcpSentTerminateReq,
96   LcpSendTerminateAck,
97   LcpDecodeConfig,
98   fsm_NullRecvResetReq,
99   fsm_NullRecvResetAck
100 };
101 
102 static const char *lcp_TimerNames[] =
103   {"LCP restart", "LCP openmode", "LCP stopped"};
104 
105 static const char *cftypes[] = {
106   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
107   "???",
108   "MRU",	/* 1: Maximum-Receive-Unit */
109   "ACCMAP",	/* 2: Async-Control-Character-Map */
110   "AUTHPROTO",	/* 3: Authentication-Protocol */
111   "QUALPROTO",	/* 4: Quality-Protocol */
112   "MAGICNUM",	/* 5: Magic-Number */
113   "RESERVED",	/* 6: RESERVED */
114   "PROTOCOMP",	/* 7: Protocol-Field-Compression */
115   "ACFCOMP",	/* 8: Address-and-Control-Field-Compression */
116   "FCSALT",	/* 9: FCS-Alternatives */
117   "SDP",	/* 10: Self-Describing-Pad */
118   "NUMMODE",	/* 11: Numbered-Mode */
119   "MULTIPROC",	/* 12: Multi-Link-Procedure */
120   "CALLBACK",	/* 13: Callback */
121   "CONTIME",	/* 14: Connect-Time */
122   "COMPFRAME",	/* 15: Compound-Frames */
123   "NDE",	/* 16: Nominal-Data-Encapsulation */
124   "MRRU",	/* 17: Multilink-MRRU */
125   "SHORTSEQ",	/* 18: Multilink-Short-Sequence-Number-Header */
126   "ENDDISC",	/* 19: Multilink-Endpoint-Discriminator */
127   "PROPRIETRY",	/* 20: Proprietary */
128   "DCEID",	/* 21: DCE-Identifier */
129   "MULTIPP",	/* 22: Multi-Link-Plus-Procedure */
130   "LDBACP",	/* 23: Link Discriminator for BACP */
131 };
132 
133 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
134 
135 int
136 lcp_ReportStatus(struct cmdargs const *arg)
137 {
138   struct link *l;
139   struct lcp *lcp;
140 
141   l = command_ChooseLink(arg);
142   lcp = &l->lcp;
143 
144   prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
145                 State2Nam(lcp->fsm.state));
146   prompt_Printf(arg->prompt,
147 	        " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
148 	        "           MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
149 	        lcp->his_mru, (u_long)lcp->his_accmap,
150                 lcp->his_protocomp ? "on" : "off",
151                 lcp->his_acfcomp ? "on" : "off",
152                 (u_long)lcp->his_magic, lcp->his_mrru,
153                 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
154   prompt_Printf(arg->prompt,
155 	        " my  side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
156                 "           MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
157                 lcp->want_mru, (u_long)lcp->want_accmap,
158                 lcp->want_protocomp ? "on" : "off",
159                 lcp->want_acfcomp ? "on" : "off",
160                 (u_long)lcp->want_magic, lcp->want_mrru,
161                 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
162 
163   prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru);
164   prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
165   prompt_Printf(arg->prompt, "           LQR period = %us, ",
166                 lcp->cfg.lqrperiod);
167   prompt_Printf(arg->prompt, "Open Mode = %s",
168                 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
169   if (lcp->cfg.openmode > 0)
170     prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
171   prompt_Printf(arg->prompt, "\n           FSM retry = %us\n",
172                 lcp->cfg.fsmretry);
173   prompt_Printf(arg->prompt, "\n Negotiation:\n");
174   prompt_Printf(arg->prompt, "           ACFCOMP =   %s\n",
175                 command_ShowNegval(lcp->cfg.acfcomp));
176   prompt_Printf(arg->prompt, "           CHAP =      %s\n",
177                 command_ShowNegval(lcp->cfg.chap));
178   prompt_Printf(arg->prompt, "           LQR =       %s\n",
179                 command_ShowNegval(lcp->cfg.lqr));
180   prompt_Printf(arg->prompt, "           PAP =       %s\n",
181                 command_ShowNegval(lcp->cfg.pap));
182   prompt_Printf(arg->prompt, "           PROTOCOMP = %s\n",
183                 command_ShowNegval(lcp->cfg.protocomp));
184 
185   return 0;
186 }
187 
188 static u_int32_t
189 GenerateMagic(void)
190 {
191   /* Generate random number which will be used as magic number */
192   randinit();
193   return random();
194 }
195 
196 void
197 lcp_SetupCallbacks(struct lcp *lcp)
198 {
199   lcp->fsm.fn = &lcp_Callbacks;
200   lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
201   lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
202   lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
203 }
204 
205 void
206 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
207          const struct fsm_parent *parent)
208 {
209   /* Initialise ourselves */
210   int mincode = parent ? 1 : LCP_MINMPCODE;
211 
212   fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, 10, LogLCP,
213            bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
214 
215   lcp->cfg.mru = DEF_MRU;
216   lcp->cfg.accmap = 0;
217   lcp->cfg.openmode = 1;
218   lcp->cfg.lqrperiod = DEF_LQRPERIOD;
219   lcp->cfg.fsmretry = DEF_FSMRETRY;
220 
221   lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
222   lcp->cfg.chap = NEG_ACCEPTED;
223   lcp->cfg.lqr = NEG_ACCEPTED;
224   lcp->cfg.pap = NEG_ACCEPTED;
225   lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
226 
227   lcp_Setup(lcp, lcp->cfg.openmode);
228 }
229 
230 void
231 lcp_Setup(struct lcp *lcp, int openmode)
232 {
233   lcp->fsm.open_mode = openmode;
234   lcp->fsm.maxconfig = 10;
235 
236   lcp->his_mru = lcp->fsm.bundle->cfg.mtu;
237   if (!lcp->his_mru || lcp->his_mru > DEF_MRU)
238     lcp->his_mru = DEF_MRU;
239   lcp->his_mrru = 0;
240   lcp->his_magic = 0;
241   lcp->his_lqrperiod = 0;
242   lcp->his_acfcomp = 0;
243   lcp->his_auth = 0;
244   lcp->his_callback.opmask = 0;
245   lcp->his_shortseq = 0;
246 
247   lcp->want_mru = lcp->cfg.mru;
248   lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
249   lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
250   lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
251 
252   if (lcp->fsm.parent) {
253     struct physical *p = link2physical(lcp->fsm.link);
254 
255     lcp->his_accmap = 0xffffffff;
256     lcp->want_accmap = lcp->cfg.accmap;
257     lcp->his_protocomp = 0;
258     lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
259     lcp->want_magic = GenerateMagic();
260     lcp->want_auth = IsEnabled(lcp->cfg.chap) ? PROTO_CHAP :
261                      IsEnabled(lcp->cfg.pap) ?  PROTO_PAP : 0;
262     if (p->type != PHYS_DIRECT)
263       memcpy(&lcp->want_callback, &p->dl->cfg.callback, sizeof(struct callback));
264     else
265       lcp->want_callback.opmask = 0;
266     lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
267                           lcp->cfg.lqrperiod * 100 : 0;
268   } else {
269     lcp->his_accmap = lcp->want_accmap = 0;
270     lcp->his_protocomp = lcp->want_protocomp = 1;
271     lcp->want_magic = 0;
272     lcp->want_auth = 0;
273     lcp->want_callback.opmask = 0;
274     lcp->want_lqrperiod = 0;
275   }
276 
277   lcp->his_reject = lcp->my_reject = 0;
278   lcp->auth_iwait = lcp->auth_ineed = 0;
279   lcp->LcpFailedMagic = 0;
280 }
281 
282 static void
283 LcpInitRestartCounter(struct fsm * fp)
284 {
285   /* Set fsm timer load */
286   struct lcp *lcp = fsm2lcp(fp);
287 
288   fp->FsmTimer.load = lcp->cfg.fsmretry * SECTICKS;
289   fp->restart = DEF_REQs;
290 }
291 
292 static void
293 LcpSendConfigReq(struct fsm *fp)
294 {
295   /* Send config REQ please */
296   struct physical *p = link2physical(fp->link);
297   struct lcp *lcp = fsm2lcp(fp);
298   u_char buff[200];
299   struct lcp_opt *o;
300   struct mp *mp;
301   u_int16_t proto;
302 
303   if (!p) {
304     log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
305               fp->link->name);
306     return;
307   }
308 
309   o = (struct lcp_opt *)buff;
310   if (!physical_IsSync(p)) {
311     if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
312       INC_LCP_OPT(TY_ACFCOMP, 2, o);
313 
314     if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
315       INC_LCP_OPT(TY_PROTOCOMP, 2, o);
316 
317     if (!REJECTED(lcp, TY_ACCMAP)) {
318       ua_htonl(&lcp->want_accmap, o->data);
319       INC_LCP_OPT(TY_ACCMAP, 6, o);
320     }
321   }
322 
323   if (!REJECTED(lcp, TY_MRU)) {
324     ua_htons(&lcp->want_mru, o->data);
325     INC_LCP_OPT(TY_MRU, 4, o);
326   }
327 
328   if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
329     ua_htonl(&lcp->want_magic, o->data);
330     INC_LCP_OPT(TY_MAGICNUM, 6, o);
331   }
332 
333   if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
334     proto = PROTO_LQR;
335     ua_htons(&proto, o->data);
336     ua_htonl(&lcp->want_lqrperiod, o->data + 2);
337     INC_LCP_OPT(TY_QUALPROTO, 8, o);
338   }
339 
340   switch (lcp->want_auth) {
341   case PROTO_PAP:
342     proto = PROTO_PAP;
343     ua_htons(&proto, o->data);
344     INC_LCP_OPT(TY_AUTHPROTO, 4, o);
345     break;
346 
347   case PROTO_CHAP:
348     proto = PROTO_CHAP;
349     ua_htons(&proto, o->data);
350     o->data[2] = 0x05;
351     INC_LCP_OPT(TY_AUTHPROTO, 5, o);
352     break;
353   }
354 
355   if (!REJECTED(lcp, TY_CALLBACK)) {
356     if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
357       *o->data = CALLBACK_AUTH;
358       INC_LCP_OPT(TY_CALLBACK, 3, o);
359     } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
360       *o->data = CALLBACK_CBCP;
361       INC_LCP_OPT(TY_CALLBACK, 3, o);
362     } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
363       int sz = strlen(lcp->want_callback.msg);
364 
365       if (sz > sizeof o->data - 1) {
366         sz = sizeof o->data - 1;
367         log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
368       }
369       *o->data = CALLBACK_E164;
370       memcpy(o->data + 1, lcp->want_callback.msg, sz);
371       INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
372     }
373   }
374 
375   if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
376     ua_htons(&lcp->want_mrru, o->data);
377     INC_LCP_OPT(TY_MRRU, 4, o);
378 
379     if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
380       INC_LCP_OPT(TY_SHORTSEQ, 2, o);
381   }
382 
383   mp = &lcp->fsm.bundle->ncp.mp;
384   if (mp->cfg.enddisc.class != 0 && !REJECTED(lcp, TY_ENDDISC)) {
385     *o->data = mp->cfg.enddisc.class;
386     memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
387     INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
388   }
389 
390   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
391 }
392 
393 void
394 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
395 {
396   /* Don't understand `option' */
397   fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count);
398 }
399 
400 static void
401 LcpSentTerminateReq(struct fsm * fp)
402 {
403   /* Term REQ just sent by FSM */
404 }
405 
406 static void
407 LcpSendTerminateAck(struct fsm *fp, u_char id)
408 {
409   /* Send Term ACK please */
410   struct physical *p = link2physical(fp->link);
411 
412   if (p && p->dl->state == DATALINK_CBCP)
413     cbcp_ReceiveTerminateReq(p);
414 
415   fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
416 }
417 
418 static void
419 LcpLayerStart(struct fsm *fp)
420 {
421   /* We're about to start up ! */
422   struct lcp *lcp = fsm2lcp(fp);
423 
424   log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
425   lcp->LcpFailedMagic = 0;
426 }
427 
428 static void
429 LcpLayerFinish(struct fsm *fp)
430 {
431   /* We're now down */
432   log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
433 }
434 
435 static int
436 LcpLayerUp(struct fsm *fp)
437 {
438   /* We're now up */
439   struct physical *p = link2physical(fp->link);
440   struct lcp *lcp = fsm2lcp(fp);
441 
442   log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
443   async_SetLinkParams(&p->async, lcp);
444   lqr_Start(lcp);
445   hdlc_StartTimer(&p->hdlc);
446   return 1;
447 }
448 
449 static void
450 LcpLayerDown(struct fsm *fp)
451 {
452   /* About to come down */
453   struct physical *p = link2physical(fp->link);
454 
455   log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
456   hdlc_StopTimer(&p->hdlc);
457   lqr_StopTimer(p);
458   lcp_Setup(fsm2lcp(fp), 0);
459 }
460 
461 static int
462 E164ok(struct callback *cb, char *req, int sz)
463 {
464   char list[sizeof cb->msg], *next;
465   int len;
466 
467   if (!strcmp(cb->msg, "*"))
468     return 1;
469 
470   strncpy(list, cb->msg, sizeof list - 1);
471   list[sizeof list - 1] = '\0';
472   for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
473     len = strlen(next);
474     if (sz == len && !memcmp(list, req, sz))
475       return 1;
476   }
477   return 0;
478 }
479 
480 static void
481 LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
482                 struct fsm_decode *dec)
483 {
484   /* Deal with incoming PROTO_LCP */
485   struct lcp *lcp = fsm2lcp(fp);
486   int type, length, sz, pos, op, callback_req;
487   u_int32_t magic, accmap;
488   u_short mtu, mru, proto;
489   struct lqrreq *req;
490   char request[20], desc[22];
491   struct mp *mp;
492   struct physical *p = link2physical(fp->link);
493 
494   callback_req = 0;
495 
496   while (plen >= sizeof(struct fsmconfig)) {
497     type = *cp;
498     length = cp[1];
499 
500     if (type < 0 || type >= NCFTYPES)
501       snprintf(request, sizeof request, " <%d>[%d]", type, length);
502     else
503       snprintf(request, sizeof request, " %s[%d]", cftypes[type], length);
504 
505     if (length < 2) {
506       log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
507       break;
508     }
509 
510     switch (type) {
511     case TY_MRRU:
512       mp = &lcp->fsm.bundle->ncp.mp;
513       ua_ntohs(cp + 2, &mru);
514       log_Printf(LogLCP, "%s %u\n", request, mru);
515 
516       switch (mode_type) {
517       case MODE_REQ:
518         if (mp->cfg.mrru) {
519           if (REJECTED(lcp, TY_MRRU))
520             /* Ignore his previous reject so that we REQ next time */
521 	    lcp->his_reject &= ~(1 << type);
522 
523           mtu = lcp->fsm.bundle->cfg.mtu;
524           if (mru < MIN_MRU || mru < mtu) {
525             /* Push him up to MTU or MIN_MRU */
526             lcp->his_mrru = mru < mtu ? mtu : MIN_MRU;
527 	    memcpy(dec->nakend, cp, 2);
528             ua_htons(&lcp->his_mrru, dec->nakend + 2);
529 	    dec->nakend += 4;
530 	  } else {
531             lcp->his_mrru = mtu ? mtu : mru;
532 	    memcpy(dec->ackend, cp, 4);
533 	    dec->ackend += 4;
534 	  }
535 	  break;
536         } else
537 	  goto reqreject;
538         break;
539       case MODE_NAK:
540         if (mp->cfg.mrru) {
541           if (REJECTED(lcp, TY_MRRU))
542             /* Must have changed his mind ! */
543 	    lcp->his_reject &= ~(1 << type);
544 
545           if (mru > MAX_MRU)
546             lcp->want_mrru = MAX_MRU;
547           else if (mru < MIN_MRU)
548             lcp->want_mrru = MIN_MRU;
549           else
550             lcp->want_mrru = mru;
551         }
552         /* else we honour our config and don't send the suggested REQ */
553         break;
554       case MODE_REJ:
555 	lcp->his_reject |= (1 << type);
556         lcp->want_mrru = 0;		/* Ah well, no multilink :-( */
557 	break;
558       }
559       break;
560 
561     case TY_MRU:
562       ua_ntohs(cp + 2, &mru);
563       log_Printf(LogLCP, "%s %d\n", request, mru);
564 
565       switch (mode_type) {
566       case MODE_REQ:
567         mtu = lcp->fsm.bundle->cfg.mtu;
568         if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) {
569           /* Push him up to MTU or MIN_MRU */
570           lcp->his_mru = mru < mtu ? mtu : MIN_MRU;
571           memcpy(dec->nakend, cp, 2);
572           ua_htons(&lcp->his_mru, dec->nakend + 2);
573           dec->nakend += 4;
574         } else {
575           lcp->his_mru = mtu ? mtu : mru;
576           memcpy(dec->ackend, cp, 4);
577           dec->ackend += 4;
578         }
579 	break;
580       case MODE_NAK:
581         if (mru > MAX_MRU)
582           lcp->want_mru = MAX_MRU;
583         else if (mru < MIN_MRU)
584           lcp->want_mru = MIN_MRU;
585         else
586           lcp->want_mru = mru;
587 	break;
588       case MODE_REJ:
589 	lcp->his_reject |= (1 << type);
590 	break;
591       }
592       break;
593 
594     case TY_ACCMAP:
595       ua_ntohl(cp + 2, &accmap);
596       log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
597 
598       switch (mode_type) {
599       case MODE_REQ:
600 	lcp->his_accmap = accmap;
601 	memcpy(dec->ackend, cp, 6);
602 	dec->ackend += 6;
603 	break;
604       case MODE_NAK:
605 	lcp->want_accmap = accmap;
606 	break;
607       case MODE_REJ:
608 	lcp->his_reject |= (1 << type);
609 	break;
610       }
611       break;
612 
613     case TY_AUTHPROTO:
614       ua_ntohs(cp + 2, &proto);
615       switch (proto) {
616       case PROTO_PAP:
617         log_Printf(LogLCP, "%s 0x%04x (PAP)\n", request, proto);
618         break;
619       case PROTO_CHAP:
620         log_Printf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]);
621         break;
622       default:
623         log_Printf(LogLCP, "%s 0x%04x\n", request, proto);
624         break;
625       }
626 
627       switch (mode_type) {
628       case MODE_REQ:
629 	switch (proto) {
630 	case PROTO_PAP:
631 	  if (length != 4) {
632 	    log_Printf(LogLCP, " Bad length!\n");
633 	    goto reqreject;
634 	  }
635 	  if (IsAccepted(lcp->cfg.pap)) {
636 	    lcp->his_auth = proto;
637 	    memcpy(dec->ackend, cp, length);
638 	    dec->ackend += length;
639 	  } else if (IsAccepted(lcp->cfg.chap)) {
640 	    *dec->nakend++ = *cp;
641 	    *dec->nakend++ = 5;
642 	    *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
643 	    *dec->nakend++ = (unsigned char) PROTO_CHAP;
644 	    *dec->nakend++ = 0x05;
645 	  } else
646 	    goto reqreject;
647 	  break;
648 
649 	case PROTO_CHAP:
650 	  if (length < 5) {
651 	    log_Printf(LogLCP, " Bad length!\n");
652 	    goto reqreject;
653 	  }
654 #ifdef HAVE_DES
655           if (IsAccepted(lcp->cfg.chap) && (cp[4] == 0x05 || cp[4] == 0x80))
656 #else
657           if (IsAccepted(lcp->cfg.chap) && cp[4] == 0x05)
658 #endif
659 	  {
660 	    lcp->his_auth = proto;
661 	    memcpy(dec->ackend, cp, length);
662 	    dec->ackend += length;
663 #ifdef HAVE_DES
664             link2physical(fp->link)->dl->chap.using_MSChap = cp[4] == 0x80;
665 #endif
666 	  } else {
667             if (IsAccepted(lcp->cfg.chap)) {
668 #ifndef HAVE_DES
669               if (cp[4] == 0x80)
670                 log_Printf(LogWARN, "Chap 0x80 not available without DES\n");
671               else
672 #endif
673                 log_Printf(LogWARN, "Chap 0x%02x not supported\n",
674                            (unsigned)cp[4]);
675             }
676             if (IsAccepted(lcp->cfg.pap)) {
677 	      *dec->nakend++ = *cp;
678 	      *dec->nakend++ = 4;
679 	      *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
680 	      *dec->nakend++ = (unsigned char) PROTO_PAP;
681 	    } else
682 	      goto reqreject;
683           }
684 	  break;
685 
686 	default:
687           log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
688                     request, proto);
689 	  memcpy(dec->nakend, cp, length);
690 	  dec->nakend += length;
691 	  break;
692 	}
693 	break;
694       case MODE_NAK:
695 	switch (proto) {
696 	case PROTO_PAP:
697           if (IsEnabled(lcp->cfg.pap))
698             lcp->want_auth = PROTO_PAP;
699           else {
700             log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
701 	    lcp->his_reject |= (1 << type);
702           }
703           break;
704 	case PROTO_CHAP:
705           if (IsEnabled(lcp->cfg.chap))
706             lcp->want_auth = PROTO_CHAP;
707           else {
708             log_Printf(LogLCP, "Peer will only send CHAP (not enabled)\n");
709 	    lcp->his_reject |= (1 << type);
710           }
711           break;
712         default:
713           /* We've been NAK'd with something we don't understand :-( */
714 	  lcp->his_reject |= (1 << type);
715           break;
716         }
717 	break;
718       case MODE_REJ:
719 	lcp->his_reject |= (1 << type);
720 	break;
721       }
722       break;
723 
724     case TY_QUALPROTO:
725       req = (struct lqrreq *)cp;
726       log_Printf(LogLCP, "%s proto %x, interval %lums\n",
727                 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
728       switch (mode_type) {
729       case MODE_REQ:
730 	if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
731 	  goto reqreject;
732 	else {
733 	  lcp->his_lqrperiod = ntohl(req->period);
734 	  if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
735 	    lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
736 	  req->period = htonl(lcp->his_lqrperiod);
737 	  memcpy(dec->ackend, cp, length);
738 	  dec->ackend += length;
739 	}
740 	break;
741       case MODE_NAK:
742 	break;
743       case MODE_REJ:
744 	lcp->his_reject |= (1 << type);
745 	break;
746       }
747       break;
748 
749     case TY_MAGICNUM:
750       ua_ntohl(cp + 2, &magic);
751       log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
752 
753       switch (mode_type) {
754       case MODE_REQ:
755 	if (lcp->want_magic) {
756 	  /* Validate magic number */
757 	  if (magic == lcp->want_magic) {
758 	    log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
759                       (u_long)magic, ++lcp->LcpFailedMagic);
760 	    lcp->want_magic = GenerateMagic();
761 	    memcpy(dec->nakend, cp, 6);
762 	    dec->nakend += 6;
763             ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
764             sigpause(0);
765 	  } else {
766 	    lcp->his_magic = magic;
767 	    memcpy(dec->ackend, cp, length);
768 	    dec->ackend += length;
769             lcp->LcpFailedMagic = 0;
770 	  }
771 	} else {
772 	  goto reqreject;
773 	}
774 	break;
775       case MODE_NAK:
776 	log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
777 	lcp->want_magic = GenerateMagic();
778 	break;
779       case MODE_REJ:
780 	log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
781 	lcp->want_magic = 0;
782 	lcp->his_reject |= (1 << type);
783 	break;
784       }
785       break;
786 
787     case TY_PROTOCOMP:
788       log_Printf(LogLCP, "%s\n", request);
789 
790       switch (mode_type) {
791       case MODE_REQ:
792 	if (IsAccepted(lcp->cfg.protocomp)) {
793 	  lcp->his_protocomp = 1;
794 	  memcpy(dec->ackend, cp, 2);
795 	  dec->ackend += 2;
796 	} else {
797 #ifdef OLDMST
798 	  /*
799 	   * MorningStar before v1.3 needs NAK
800 	   */
801 	  memcpy(dec->nakend, cp, 2);
802 	  dec->nakend += 2;
803 #else
804 	  goto reqreject;
805 #endif
806 	}
807 	break;
808       case MODE_NAK:
809       case MODE_REJ:
810 	lcp->want_protocomp = 0;
811 	lcp->his_reject |= (1 << type);
812 	break;
813       }
814       break;
815 
816     case TY_ACFCOMP:
817       log_Printf(LogLCP, "%s\n", request);
818       switch (mode_type) {
819       case MODE_REQ:
820 	if (IsAccepted(lcp->cfg.acfcomp)) {
821 	  lcp->his_acfcomp = 1;
822 	  memcpy(dec->ackend, cp, 2);
823 	  dec->ackend += 2;
824 	} else {
825 #ifdef OLDMST
826 	  /*
827 	   * MorningStar before v1.3 needs NAK
828 	   */
829 	  memcpy(dec->nakend, cp, 2);
830 	  dec->nakend += 2;
831 #else
832 	  goto reqreject;
833 #endif
834 	}
835 	break;
836       case MODE_NAK:
837       case MODE_REJ:
838 	lcp->want_acfcomp = 0;
839 	lcp->his_reject |= (1 << type);
840 	break;
841       }
842       break;
843 
844     case TY_SDP:
845       log_Printf(LogLCP, "%s\n", request);
846       switch (mode_type) {
847       case MODE_REQ:
848       case MODE_NAK:
849       case MODE_REJ:
850 	break;
851       }
852       break;
853 
854     case TY_CALLBACK:
855       if (length == 2)
856         op = CALLBACK_NONE;
857       else
858         op = (int)cp[2];
859       sz = length - 3;
860       switch (op) {
861         case CALLBACK_AUTH:
862           log_Printf(LogLCP, "%s Auth\n", request);
863           break;
864         case CALLBACK_DIALSTRING:
865           log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
866           break;
867         case CALLBACK_LOCATION:
868           log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
869           break;
870         case CALLBACK_E164:
871           log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
872           break;
873         case CALLBACK_NAME:
874           log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
875           break;
876         case CALLBACK_CBCP:
877           log_Printf(LogLCP, "%s CBCP\n", request);
878           break;
879         default:
880           log_Printf(LogLCP, "%s ???\n", request);
881           break;
882       }
883 
884       switch (mode_type) {
885       case MODE_REQ:
886         callback_req = 1;
887         if (p->type != PHYS_DIRECT)
888 	  goto reqreject;
889         if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
890             (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
891             (op != CALLBACK_E164 ||
892              E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
893 	  lcp->his_callback.opmask = CALLBACK_BIT(op);
894           if (sz > sizeof lcp->his_callback.msg - 1) {
895             sz = sizeof lcp->his_callback.msg - 1;
896             log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
897           }
898 	  memcpy(lcp->his_callback.msg, cp + 3, sz);
899 	  lcp->his_callback.msg[sz] = '\0';
900 	  memcpy(dec->ackend, cp, sz + 3);
901 	  dec->ackend += sz + 3;
902         } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
903                     p->link.lcp.auth_ineed) {
904           *dec->nakend++ = *cp;
905           *dec->nakend++ = 3;
906           *dec->nakend++ = CALLBACK_AUTH;
907         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
908           *dec->nakend++ = *cp;
909           *dec->nakend++ = 3;
910           *dec->nakend++ = CALLBACK_CBCP;
911         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
912           *dec->nakend++ = *cp;
913           *dec->nakend++ = 3;
914           *dec->nakend++ = CALLBACK_E164;
915         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
916           log_Printf(LogWARN, "Cannot insist on auth callback without"
917                      " PAP or CHAP enabled !\n");
918           *dec->nakend++ = *cp;
919           *dec->nakend++ = 2;
920         } else
921 	  goto reqreject;
922         break;
923       case MODE_NAK:
924         /* We don't do what he NAKs want, we do things in our preferred order */
925         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
926           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
927         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
928           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
929         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
930           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
931         if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
932           log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
933           lcp->want_callback.opmask = 0;
934         } else if (!lcp->want_callback.opmask) {
935           log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
936           fsm_Close(&lcp->fsm);
937         }
938         break;
939       case MODE_REJ:
940         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
941 	  lcp->his_reject |= (1 << type);
942           lcp->want_callback.opmask = 0;
943         } else {
944           log_Printf(LogPHASE, "Peer rejected *required* callback\n");
945           fsm_Close(&lcp->fsm);
946         }
947 	break;
948       }
949       break;
950 
951     case TY_SHORTSEQ:
952       mp = &lcp->fsm.bundle->ncp.mp;
953       log_Printf(LogLCP, "%s\n", request);
954 
955       switch (mode_type) {
956       case MODE_REQ:
957         if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
958           lcp->his_shortseq = 1;
959 	  memcpy(dec->ackend, cp, length);
960 	  dec->ackend += length;
961         } else
962 	  goto reqreject;
963         break;
964       case MODE_NAK:
965         /*
966          * He's trying to get us to ask for short sequence numbers.
967          * We ignore the NAK and honour our configuration file instead.
968          */
969         break;
970       case MODE_REJ:
971 	lcp->his_reject |= (1 << type);
972         lcp->want_shortseq = 0;		/* For when we hit MP */
973 	break;
974       }
975       break;
976 
977     case TY_ENDDISC:
978       log_Printf(LogLCP, "%s %s\n", request,
979                 mp_Enddisc(cp[2], cp + 3, length - 3));
980       switch (mode_type) {
981       case MODE_REQ:
982         if (!p) {
983           log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
984 	  goto reqreject;
985         } else if (length-3 < sizeof p->dl->peer.enddisc.address &&
986                    cp[2] <= MAX_ENDDISC_CLASS) {
987           p->dl->peer.enddisc.class = cp[2];
988           p->dl->peer.enddisc.len = length-3;
989           memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
990           p->dl->peer.enddisc.address[length - 3] = '\0';
991           /* XXX: If mp->active, compare and NAK with mp->peer ? */
992 	  memcpy(dec->ackend, cp, length);
993 	  dec->ackend += length;
994         } else {
995           if (cp[2] > MAX_ENDDISC_CLASS)
996             log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
997                       cp[2]);
998           else
999             log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1000                       (long)(sizeof p->dl->peer.enddisc.address - 1));
1001 	  goto reqreject;
1002         }
1003 	break;
1004 
1005       case MODE_NAK:	/* Treat this as a REJ, we don't vary or disc */
1006       case MODE_REJ:
1007 	lcp->his_reject |= (1 << type);
1008 	break;
1009       }
1010       break;
1011 
1012     default:
1013       sz = (sizeof desc - 2) / 2;
1014       if (sz > length - 2)
1015         sz = length - 2;
1016       pos = 0;
1017       desc[0] = sz ? ' ' : '\0';
1018       for (pos = 0; sz--; pos++)
1019         sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1020 
1021       log_Printf(LogLCP, "%s%s\n", request, desc);
1022 
1023       if (mode_type == MODE_REQ) {
1024 reqreject:
1025         if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1026           length = sizeof dec->rej - (dec->rejend - dec->rej);
1027           log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1028 		    cp[1], length);
1029         }
1030 	memcpy(dec->rejend, cp, length);
1031 	dec->rejend += length;
1032 	lcp->my_reject |= (1 << type);
1033         if (length != cp[1])
1034           length = 0;		/* force our way out of the loop */
1035       }
1036       break;
1037     }
1038     plen -= length;
1039     cp += length;
1040   }
1041 
1042   if (mode_type != MODE_NOP) {
1043     if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1044         p->dl->cfg.callback.opmask && !callback_req &&
1045         !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1046       /* We *REQUIRE* that the peer requests callback */
1047       *dec->nakend++ = TY_CALLBACK;
1048       *dec->nakend++ = 3;
1049       if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1050           p->link.lcp.auth_ineed)
1051         *dec->nakend++ = CALLBACK_AUTH;
1052       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1053         *dec->nakend++ = CALLBACK_CBCP;
1054       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1055         *dec->nakend++ = CALLBACK_E164;
1056       else {
1057         log_Printf(LogWARN, "Cannot insist on auth callback without"
1058                    " PAP or CHAP enabled !\n");
1059         dec->nakend[-1] = 2;	/* XXX: Silly ! */
1060       }
1061     }
1062     if (dec->rejend != dec->rej) {
1063       /* rejects are preferred */
1064       dec->ackend = dec->ack;
1065       dec->nakend = dec->nak;
1066     } else if (dec->nakend != dec->nak)
1067       /* then NAKs */
1068       dec->ackend = dec->ack;
1069   }
1070 }
1071 
1072 void
1073 lcp_Input(struct lcp *lcp, struct mbuf * bp)
1074 {
1075   /* Got PROTO_LCP from link */
1076   fsm_Input(&lcp->fsm, bp);
1077 }
1078