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