lcp.c revision 93418
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: head/usr.sbin/ppp/lcp.c 93418 2002-03-30 12:30:09Z brian $
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 */
84struct lqrreq {
85  u_char type;
86  u_char length;
87  u_short proto;		/* Quality protocol */
88  u_int32_t period;		/* Reporting interval */
89};
90
91static int LcpLayerUp(struct fsm *);
92static void LcpLayerDown(struct fsm *);
93static void LcpLayerStart(struct fsm *);
94static void LcpLayerFinish(struct fsm *);
95static void LcpInitRestartCounter(struct fsm *, int);
96static void LcpSendConfigReq(struct fsm *);
97static void LcpSentTerminateReq(struct fsm *);
98static void LcpSendTerminateAck(struct fsm *, u_char);
99static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
100                            struct fsm_decode *);
101
102static 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
116static const char * const lcp_TimerNames[] =
117  {"LCP restart", "LCP openmode", "LCP stopped"};
118
119static const char *
120protoname(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
157int
158lcp_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#ifndef NODES
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
231static u_int32_t
232GenerateMagic(void)
233{
234  /* Generate random number which will be used as magic number */
235  randinit();
236  return random();
237}
238
239void
240lcp_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
248void
249lcp_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#ifndef NODES
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
284void
285lcp_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#ifndef NODES
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
357static void
358LcpInitRestartCounter(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
377static void
378LcpSendConfigReq(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
489void
490lcp_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
497int
498lcp_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
525void
526lcp_RecvIdentification(struct lcp *lcp, char *data)
527{
528  log_Printf(LogLCP, "Received ident: %s\n", data);
529}
530
531static void
532LcpSentTerminateReq(struct fsm *fp)
533{
534  /* Term REQ just sent by FSM */
535}
536
537static void
538LcpSendTerminateAck(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
549static void
550LcpLayerStart(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
561static void
562LcpLayerFinish(struct fsm *fp)
563{
564  /* We're now down */
565  log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
566}
567
568static int
569LcpLayerUp(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  physical_SetAsyncParams(p, lcp->want_accmap, lcp->his_accmap);
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
586static void
587LcpLayerDown(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
598static int
599E164ok(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
617static void
618LcpDecodeConfig(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#ifndef NODES
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#ifndef NODES
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#ifndef NODES
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#ifndef NODES
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#ifndef NODES
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) {
1241reqreject:
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
1306extern struct mbuf *
1307lcp_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}
1314