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