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