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