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