xref: /freebsd/usr.sbin/ppp/lcp.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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.63 1998/09/04 18:25:59 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 if (IsAccepted(lcp->cfg.pap)) {
667 	    *dec->nakend++ = *cp;
668 	    *dec->nakend++ = 4;
669 	    *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
670 	    *dec->nakend++ = (unsigned char) PROTO_PAP;
671 	  } else
672 	    goto reqreject;
673 	  break;
674 
675 	default:
676           log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
677                     request, proto);
678 	  memcpy(dec->nakend, cp, length);
679 	  dec->nakend += length;
680 	  break;
681 	}
682 	break;
683       case MODE_NAK:
684 	switch (proto) {
685 	case PROTO_PAP:
686           if (IsEnabled(lcp->cfg.pap))
687             lcp->want_auth = PROTO_PAP;
688           else {
689             log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
690 	    lcp->his_reject |= (1 << type);
691           }
692           break;
693 	case PROTO_CHAP:
694           if (IsEnabled(lcp->cfg.chap))
695             lcp->want_auth = PROTO_CHAP;
696           else {
697             log_Printf(LogLCP, "Peer will only send CHAP (not enabled)\n");
698 	    lcp->his_reject |= (1 << type);
699           }
700           break;
701         default:
702           /* We've been NAK'd with something we don't understand :-( */
703 	  lcp->his_reject |= (1 << type);
704           break;
705         }
706 	break;
707       case MODE_REJ:
708 	lcp->his_reject |= (1 << type);
709 	break;
710       }
711       break;
712 
713     case TY_QUALPROTO:
714       req = (struct lqrreq *)cp;
715       log_Printf(LogLCP, "%s proto %x, interval %lums\n",
716                 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
717       switch (mode_type) {
718       case MODE_REQ:
719 	if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
720 	  goto reqreject;
721 	else {
722 	  lcp->his_lqrperiod = ntohl(req->period);
723 	  if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
724 	    lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
725 	  req->period = htonl(lcp->his_lqrperiod);
726 	  memcpy(dec->ackend, cp, length);
727 	  dec->ackend += length;
728 	}
729 	break;
730       case MODE_NAK:
731 	break;
732       case MODE_REJ:
733 	lcp->his_reject |= (1 << type);
734 	break;
735       }
736       break;
737 
738     case TY_MAGICNUM:
739       ua_ntohl(cp + 2, &magic);
740       log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
741 
742       switch (mode_type) {
743       case MODE_REQ:
744 	if (lcp->want_magic) {
745 	  /* Validate magic number */
746 	  if (magic == lcp->want_magic) {
747 	    log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
748                       (u_long)magic, ++lcp->LcpFailedMagic);
749 	    lcp->want_magic = GenerateMagic();
750 	    memcpy(dec->nakend, cp, 6);
751 	    dec->nakend += 6;
752             ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
753             sigpause(0);
754 	  } else {
755 	    lcp->his_magic = magic;
756 	    memcpy(dec->ackend, cp, length);
757 	    dec->ackend += length;
758             lcp->LcpFailedMagic = 0;
759 	  }
760 	} else {
761 	  goto reqreject;
762 	}
763 	break;
764       case MODE_NAK:
765 	log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
766 	lcp->want_magic = GenerateMagic();
767 	break;
768       case MODE_REJ:
769 	log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
770 	lcp->want_magic = 0;
771 	lcp->his_reject |= (1 << type);
772 	break;
773       }
774       break;
775 
776     case TY_PROTOCOMP:
777       log_Printf(LogLCP, "%s\n", request);
778 
779       switch (mode_type) {
780       case MODE_REQ:
781 	if (IsAccepted(lcp->cfg.protocomp)) {
782 	  lcp->his_protocomp = 1;
783 	  memcpy(dec->ackend, cp, 2);
784 	  dec->ackend += 2;
785 	} else {
786 #ifdef OLDMST
787 	  /*
788 	   * MorningStar before v1.3 needs NAK
789 	   */
790 	  memcpy(dec->nakend, cp, 2);
791 	  dec->nakend += 2;
792 #else
793 	  goto reqreject;
794 #endif
795 	}
796 	break;
797       case MODE_NAK:
798       case MODE_REJ:
799 	lcp->want_protocomp = 0;
800 	lcp->his_reject |= (1 << type);
801 	break;
802       }
803       break;
804 
805     case TY_ACFCOMP:
806       log_Printf(LogLCP, "%s\n", request);
807       switch (mode_type) {
808       case MODE_REQ:
809 	if (IsAccepted(lcp->cfg.acfcomp)) {
810 	  lcp->his_acfcomp = 1;
811 	  memcpy(dec->ackend, cp, 2);
812 	  dec->ackend += 2;
813 	} else {
814 #ifdef OLDMST
815 	  /*
816 	   * MorningStar before v1.3 needs NAK
817 	   */
818 	  memcpy(dec->nakend, cp, 2);
819 	  dec->nakend += 2;
820 #else
821 	  goto reqreject;
822 #endif
823 	}
824 	break;
825       case MODE_NAK:
826       case MODE_REJ:
827 	lcp->want_acfcomp = 0;
828 	lcp->his_reject |= (1 << type);
829 	break;
830       }
831       break;
832 
833     case TY_SDP:
834       log_Printf(LogLCP, "%s\n", request);
835       switch (mode_type) {
836       case MODE_REQ:
837       case MODE_NAK:
838       case MODE_REJ:
839 	break;
840       }
841       break;
842 
843     case TY_CALLBACK:
844       if (length == 2)
845         op = CALLBACK_NONE;
846       else
847         op = (int)cp[2];
848       sz = length - 3;
849       switch (op) {
850         case CALLBACK_AUTH:
851           log_Printf(LogLCP, "%s Auth\n", request);
852           break;
853         case CALLBACK_DIALSTRING:
854           log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
855           break;
856         case CALLBACK_LOCATION:
857           log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
858           break;
859         case CALLBACK_E164:
860           log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
861           break;
862         case CALLBACK_NAME:
863           log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
864           break;
865         case CALLBACK_CBCP:
866           log_Printf(LogLCP, "%s CBCP\n", request);
867           break;
868         default:
869           log_Printf(LogLCP, "%s ???\n", request);
870           break;
871       }
872 
873       switch (mode_type) {
874       case MODE_REQ:
875         callback_req = 1;
876         if (p->type != PHYS_DIRECT)
877 	  goto reqreject;
878         if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
879             (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
880             (op != CALLBACK_E164 ||
881              E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
882 	  lcp->his_callback.opmask = CALLBACK_BIT(op);
883           if (sz > sizeof lcp->his_callback.msg - 1) {
884             sz = sizeof lcp->his_callback.msg - 1;
885             log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
886           }
887 	  memcpy(lcp->his_callback.msg, cp + 3, sz);
888 	  lcp->his_callback.msg[sz] = '\0';
889 	  memcpy(dec->ackend, cp, sz + 3);
890 	  dec->ackend += sz + 3;
891         } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
892                     p->link.lcp.auth_ineed) {
893           *dec->nakend++ = *cp;
894           *dec->nakend++ = 3;
895           *dec->nakend++ = CALLBACK_AUTH;
896         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
897           *dec->nakend++ = *cp;
898           *dec->nakend++ = 3;
899           *dec->nakend++ = CALLBACK_CBCP;
900         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
901           *dec->nakend++ = *cp;
902           *dec->nakend++ = 3;
903           *dec->nakend++ = CALLBACK_E164;
904         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
905           log_Printf(LogWARN, "Cannot insist on auth callback without"
906                      " PAP or CHAP enabled !\n");
907           *dec->nakend++ = *cp;
908           *dec->nakend++ = 2;
909         } else
910 	  goto reqreject;
911         break;
912       case MODE_NAK:
913         /* We don't do what he NAKs want, we do things in our preferred order */
914         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
915           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
916         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
917           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
918         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
919           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
920         if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
921           log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
922           lcp->want_callback.opmask = 0;
923         } else if (!lcp->want_callback.opmask) {
924           log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
925           fsm_Close(&lcp->fsm);
926         }
927         break;
928       case MODE_REJ:
929         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
930 	  lcp->his_reject |= (1 << type);
931           lcp->want_callback.opmask = 0;
932         } else {
933           log_Printf(LogPHASE, "Peer rejected *required* callback\n");
934           fsm_Close(&lcp->fsm);
935         }
936 	break;
937       }
938       break;
939 
940     case TY_SHORTSEQ:
941       mp = &lcp->fsm.bundle->ncp.mp;
942       log_Printf(LogLCP, "%s\n", request);
943 
944       switch (mode_type) {
945       case MODE_REQ:
946         if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
947           lcp->his_shortseq = 1;
948 	  memcpy(dec->ackend, cp, length);
949 	  dec->ackend += length;
950         } else
951 	  goto reqreject;
952         break;
953       case MODE_NAK:
954         /*
955          * He's trying to get us to ask for short sequence numbers.
956          * We ignore the NAK and honour our configuration file instead.
957          */
958         break;
959       case MODE_REJ:
960 	lcp->his_reject |= (1 << type);
961         lcp->want_shortseq = 0;		/* For when we hit MP */
962 	break;
963       }
964       break;
965 
966     case TY_ENDDISC:
967       log_Printf(LogLCP, "%s %s\n", request,
968                 mp_Enddisc(cp[2], cp + 3, length - 3));
969       switch (mode_type) {
970       case MODE_REQ:
971         if (!p) {
972           log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
973 	  goto reqreject;
974         } else if (length-3 < sizeof p->dl->peer.enddisc.address &&
975                    cp[2] <= MAX_ENDDISC_CLASS) {
976           p->dl->peer.enddisc.class = cp[2];
977           p->dl->peer.enddisc.len = length-3;
978           memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
979           p->dl->peer.enddisc.address[length - 3] = '\0';
980           /* XXX: If mp->active, compare and NAK with mp->peer ? */
981 	  memcpy(dec->ackend, cp, length);
982 	  dec->ackend += length;
983         } else {
984           if (cp[2] > MAX_ENDDISC_CLASS)
985             log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
986                       cp[2]);
987           else
988             log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
989                       (long)(sizeof p->dl->peer.enddisc.address - 1));
990 	  goto reqreject;
991         }
992 	break;
993 
994       case MODE_NAK:	/* Treat this as a REJ, we don't vary or disc */
995       case MODE_REJ:
996 	lcp->his_reject |= (1 << type);
997 	break;
998       }
999       break;
1000 
1001     default:
1002       sz = (sizeof desc - 2) / 2;
1003       if (sz > length - 2)
1004         sz = length - 2;
1005       pos = 0;
1006       desc[0] = sz ? ' ' : '\0';
1007       for (pos = 0; sz--; pos++)
1008         sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1009 
1010       log_Printf(LogLCP, "%s%s\n", request, desc);
1011 
1012       if (mode_type == MODE_REQ) {
1013 reqreject:
1014         if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1015           length = sizeof dec->rej - (dec->rejend - dec->rej);
1016           log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1017 		    cp[1], length);
1018         }
1019 	memcpy(dec->rejend, cp, length);
1020 	dec->rejend += length;
1021 	lcp->my_reject |= (1 << type);
1022         if (length != cp[1])
1023           length = 0;		/* force our way out of the loop */
1024       }
1025       break;
1026     }
1027     plen -= length;
1028     cp += length;
1029   }
1030 
1031   if (mode_type != MODE_NOP) {
1032     if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1033         p->dl->cfg.callback.opmask && !callback_req &&
1034         !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1035       /* We *REQUIRE* that the peer requests callback */
1036       *dec->nakend++ = TY_CALLBACK;
1037       *dec->nakend++ = 3;
1038       if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1039           p->link.lcp.auth_ineed)
1040         *dec->nakend++ = CALLBACK_AUTH;
1041       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1042         *dec->nakend++ = CALLBACK_CBCP;
1043       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1044         *dec->nakend++ = CALLBACK_E164;
1045       else {
1046         log_Printf(LogWARN, "Cannot insist on auth callback without"
1047                    " PAP or CHAP enabled !\n");
1048         dec->nakend[-1] = 2;	/* XXX: Silly ! */
1049       }
1050     }
1051     if (dec->rejend != dec->rej) {
1052       /* rejects are preferred */
1053       dec->ackend = dec->ack;
1054       dec->nakend = dec->nak;
1055     } else if (dec->nakend != dec->nak)
1056       /* then NAKs */
1057       dec->ackend = dec->ack;
1058   }
1059 }
1060 
1061 void
1062 lcp_Input(struct lcp *lcp, struct mbuf * bp)
1063 {
1064   /* Got PROTO_LCP from link */
1065   fsm_Input(&lcp->fsm, bp);
1066 }
1067