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