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