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