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