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