kcollect - Fix swap text output
[dragonfly.git] / usr.sbin / ppp / lcp.c
blob2f5a5aa83df74497659935d3e5f93a2892c8f035
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.
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.
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.
28 * $FreeBSD: src/usr.sbin/ppp/lcp.c,v 1.81.2.13 2002/09/01 02:12:28 brian Exp $
29 * $DragonFly: src/usr.sbin/ppp/lcp.c,v 1.2 2003/06/17 04:30:00 dillon Exp $
32 #include <sys/param.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <sys/socket.h>
37 #include <sys/un.h>
39 #include <signal.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <termios.h>
45 #include <unistd.h>
47 #include "layer.h"
48 #include "ua.h"
49 #include "defs.h"
50 #include "command.h"
51 #include "mbuf.h"
52 #include "log.h"
53 #include "timer.h"
54 #include "fsm.h"
55 #include "iplist.h"
56 #include "throughput.h"
57 #include "proto.h"
58 #include "descriptor.h"
59 #include "lqr.h"
60 #include "hdlc.h"
61 #include "lcp.h"
62 #include "ccp.h"
63 #include "async.h"
64 #include "link.h"
65 #include "physical.h"
66 #include "prompt.h"
67 #include "slcompress.h"
68 #include "ncpaddr.h"
69 #include "ipcp.h"
70 #include "filter.h"
71 #include "mp.h"
72 #include "chat.h"
73 #include "auth.h"
74 #include "chap.h"
75 #include "cbcp.h"
76 #include "datalink.h"
77 #ifndef NORADIUS
78 #include "radius.h"
79 #endif
80 #include "ipv6cp.h"
81 #include "ncp.h"
82 #include "bundle.h"
84 /* for received LQRs */
85 struct lqrreq {
86 struct fsm_opt_hdr hdr;
87 u_short proto; /* Quality protocol */
88 u_int32_t period; /* Reporting interval */
91 static int LcpLayerUp(struct fsm *);
92 static void LcpLayerDown(struct fsm *);
93 static void LcpLayerStart(struct fsm *);
94 static void LcpLayerFinish(struct fsm *);
95 static void LcpInitRestartCounter(struct fsm *, int);
96 static void LcpSendConfigReq(struct fsm *);
97 static void LcpSentTerminateReq(struct fsm *);
98 static void LcpSendTerminateAck(struct fsm *, u_char);
99 static void LcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
100 struct fsm_decode *);
102 static struct fsm_callbacks lcp_Callbacks = {
103 LcpLayerUp,
104 LcpLayerDown,
105 LcpLayerStart,
106 LcpLayerFinish,
107 LcpInitRestartCounter,
108 LcpSendConfigReq,
109 LcpSentTerminateReq,
110 LcpSendTerminateAck,
111 LcpDecodeConfig,
112 fsm_NullRecvResetReq,
113 fsm_NullRecvResetAck
116 static const char * const lcp_TimerNames[] =
117 {"LCP restart", "LCP openmode", "LCP stopped"};
119 static const char *
120 protoname(unsigned proto)
122 static const char * const cftypes[] = {
123 /* Check out the latest ``Assigned numbers'' rfc (1700) */
124 NULL,
125 "MRU", /* 1: Maximum-Receive-Unit */
126 "ACCMAP", /* 2: Async-Control-Character-Map */
127 "AUTHPROTO", /* 3: Authentication-Protocol */
128 "QUALPROTO", /* 4: Quality-Protocol */
129 "MAGICNUM", /* 5: Magic-Number */
130 "RESERVED", /* 6: RESERVED */
131 "PROTOCOMP", /* 7: Protocol-Field-Compression */
132 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */
133 "FCSALT", /* 9: FCS-Alternatives */
134 "SDP", /* 10: Self-Describing-Pad */
135 "NUMMODE", /* 11: Numbered-Mode */
136 "MULTIPROC", /* 12: Multi-Link-Procedure */
137 "CALLBACK", /* 13: Callback */
138 "CONTIME", /* 14: Connect-Time */
139 "COMPFRAME", /* 15: Compound-Frames */
140 "NDE", /* 16: Nominal-Data-Encapsulation */
141 "MRRU", /* 17: Multilink-MRRU */
142 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
143 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
144 "PROPRIETRY", /* 20: Proprietary */
145 "DCEID", /* 21: DCE-Identifier */
146 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */
147 "LDBACP", /* 23: Link Discriminator for BACP */
150 if (proto > sizeof cftypes / sizeof *cftypes || cftypes[proto] == NULL)
151 return HexStr(proto, NULL, 0);
153 return cftypes[proto];
157 lcp_ReportStatus(struct cmdargs const *arg)
159 struct link *l;
160 struct lcp *lcp;
162 l = command_ChooseLink(arg);
163 lcp = &l->lcp;
165 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
166 State2Nam(lcp->fsm.state));
167 prompt_Printf(arg->prompt,
168 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
169 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
170 lcp->his_mru, (u_long)lcp->his_accmap,
171 lcp->his_protocomp ? "on" : "off",
172 lcp->his_acfcomp ? "on" : "off",
173 (u_long)lcp->his_magic, lcp->his_mrru,
174 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
175 prompt_Printf(arg->prompt,
176 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
177 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
178 lcp->want_mru, (u_long)lcp->want_accmap,
179 lcp->want_protocomp ? "on" : "off",
180 lcp->want_acfcomp ? "on" : "off",
181 (u_long)lcp->want_magic, lcp->want_mrru,
182 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
184 if (lcp->cfg.mru)
185 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d (max %d), ",
186 lcp->cfg.mru, lcp->cfg.max_mru);
187 else
188 prompt_Printf(arg->prompt, "\n Defaults: MRU = any (max %d), ",
189 lcp->cfg.max_mru);
190 if (lcp->cfg.mtu)
191 prompt_Printf(arg->prompt, "MTU = %d (max %d), ",
192 lcp->cfg.mtu, lcp->cfg.max_mtu);
193 else
194 prompt_Printf(arg->prompt, "MTU = any (max %d), ", lcp->cfg.max_mtu);
195 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
196 prompt_Printf(arg->prompt, " LQR period = %us, ",
197 lcp->cfg.lqrperiod);
198 prompt_Printf(arg->prompt, "Open Mode = %s",
199 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
200 if (lcp->cfg.openmode > 0)
201 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
202 prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
203 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
204 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
205 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
206 prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
207 prompt_Printf(arg->prompt, "\n Negotiation:\n");
208 prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
209 command_ShowNegval(lcp->cfg.acfcomp));
210 prompt_Printf(arg->prompt, " CHAP = %s\n",
211 command_ShowNegval(lcp->cfg.chap05));
212 #ifndef NODES
213 prompt_Printf(arg->prompt, " CHAP80 = %s\n",
214 command_ShowNegval(lcp->cfg.chap80nt));
215 prompt_Printf(arg->prompt, " LANMan = %s\n",
216 command_ShowNegval(lcp->cfg.chap80lm));
217 prompt_Printf(arg->prompt, " CHAP81 = %s\n",
218 command_ShowNegval(lcp->cfg.chap81));
219 #endif
220 prompt_Printf(arg->prompt, " LQR = %s\n",
221 command_ShowNegval(lcp->cfg.lqr));
222 prompt_Printf(arg->prompt, " PAP = %s\n",
223 command_ShowNegval(lcp->cfg.pap));
224 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
225 command_ShowNegval(lcp->cfg.protocomp));
227 return 0;
230 static u_int32_t
231 GenerateMagic(void)
233 /* Generate random number which will be used as magic number */
234 randinit();
235 return random();
238 void
239 lcp_SetupCallbacks(struct lcp *lcp)
241 lcp->fsm.fn = &lcp_Callbacks;
242 lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
243 lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
244 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
247 void
248 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
249 const struct fsm_parent *parent)
251 /* Initialise ourselves */
252 int mincode = parent ? 1 : LCP_MINMPCODE;
254 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
255 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
257 lcp->cfg.mru = 0;
258 lcp->cfg.max_mru = MAX_MRU;
259 lcp->cfg.mtu = 0;
260 lcp->cfg.max_mtu = MAX_MTU;
261 lcp->cfg.accmap = 0;
262 lcp->cfg.openmode = 1;
263 lcp->cfg.lqrperiod = DEF_LQRPERIOD;
264 lcp->cfg.fsm.timeout = DEF_FSMRETRY;
265 lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
266 lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
268 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
269 lcp->cfg.chap05 = NEG_ACCEPTED;
270 #ifndef NODES
271 lcp->cfg.chap80nt = NEG_ACCEPTED;
272 lcp->cfg.chap80lm = 0;
273 lcp->cfg.chap81 = NEG_ACCEPTED;
274 #endif
275 lcp->cfg.lqr = NEG_ACCEPTED;
276 lcp->cfg.pap = NEG_ACCEPTED;
277 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
278 *lcp->cfg.ident = '\0';
280 lcp_Setup(lcp, lcp->cfg.openmode);
283 void
284 lcp_Setup(struct lcp *lcp, int openmode)
286 struct physical *p = link2physical(lcp->fsm.link);
288 lcp->fsm.open_mode = openmode;
290 lcp->his_mru = DEF_MRU;
291 lcp->his_mrru = 0;
292 lcp->his_magic = 0;
293 lcp->his_lqrperiod = 0;
294 lcp->his_acfcomp = 0;
295 lcp->his_auth = 0;
296 lcp->his_authtype = 0;
297 lcp->his_callback.opmask = 0;
298 lcp->his_shortseq = 0;
299 lcp->mru_req = 0;
301 if ((lcp->want_mru = lcp->cfg.mru) == 0)
302 lcp->want_mru = DEF_MRU;
303 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
304 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
305 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
307 if (lcp->fsm.parent) {
308 lcp->his_accmap = 0xffffffff;
309 lcp->want_accmap = lcp->cfg.accmap;
310 lcp->his_protocomp = 0;
311 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
312 lcp->want_magic = GenerateMagic();
314 if (IsEnabled(lcp->cfg.chap05)) {
315 lcp->want_auth = PROTO_CHAP;
316 lcp->want_authtype = 0x05;
317 #ifndef NODES
318 } else if (IsEnabled(lcp->cfg.chap80nt) ||
319 IsEnabled(lcp->cfg.chap80lm)) {
320 lcp->want_auth = PROTO_CHAP;
321 lcp->want_authtype = 0x80;
322 } else if (IsEnabled(lcp->cfg.chap81)) {
323 lcp->want_auth = PROTO_CHAP;
324 lcp->want_authtype = 0x81;
325 #endif
326 } else if (IsEnabled(lcp->cfg.pap)) {
327 lcp->want_auth = PROTO_PAP;
328 lcp->want_authtype = 0;
329 } else {
330 lcp->want_auth = 0;
331 lcp->want_authtype = 0;
334 if (p->type != PHYS_DIRECT)
335 memcpy(&lcp->want_callback, &p->dl->cfg.callback,
336 sizeof(struct callback));
337 else
338 lcp->want_callback.opmask = 0;
339 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
340 lcp->cfg.lqrperiod * 100 : 0;
341 } else {
342 lcp->his_accmap = lcp->want_accmap = 0;
343 lcp->his_protocomp = lcp->want_protocomp = 1;
344 lcp->want_magic = 0;
345 lcp->want_auth = 0;
346 lcp->want_authtype = 0;
347 lcp->want_callback.opmask = 0;
348 lcp->want_lqrperiod = 0;
351 lcp->his_reject = lcp->my_reject = 0;
352 lcp->auth_iwait = lcp->auth_ineed = 0;
353 lcp->LcpFailedMagic = 0;
356 static void
357 LcpInitRestartCounter(struct fsm *fp, int what)
359 /* Set fsm timer load */
360 struct lcp *lcp = fsm2lcp(fp);
362 fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
363 switch (what) {
364 case FSM_REQ_TIMER:
365 fp->restart = lcp->cfg.fsm.maxreq;
366 break;
367 case FSM_TRM_TIMER:
368 fp->restart = lcp->cfg.fsm.maxtrm;
369 break;
370 default:
371 fp->restart = 1;
372 break;
376 static void
377 LcpSendConfigReq(struct fsm *fp)
379 /* Send config REQ please */
380 struct physical *p = link2physical(fp->link);
381 struct lcp *lcp = fsm2lcp(fp);
382 u_char buff[200];
383 struct fsm_opt *o;
384 struct mp *mp;
385 u_int16_t proto;
386 u_short maxmru;
388 if (!p) {
389 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
390 fp->link->name);
391 return;
394 o = (struct fsm_opt *)buff;
395 if (!physical_IsSync(p)) {
396 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
397 INC_FSM_OPT(TY_ACFCOMP, 2, o);
399 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
400 INC_FSM_OPT(TY_PROTOCOMP, 2, o);
402 if (!REJECTED(lcp, TY_ACCMAP)) {
403 ua_htonl(&lcp->want_accmap, o->data);
404 INC_FSM_OPT(TY_ACCMAP, 6, o);
408 maxmru = p ? physical_DeviceMTU(p) : 0;
409 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
410 maxmru = lcp->cfg.max_mru;
411 if (maxmru && lcp->want_mru > maxmru) {
412 log_Printf(LogWARN, "%s: Reducing configured MRU from %u to %u\n",
413 fp->link->name, lcp->want_mru, maxmru);
414 lcp->want_mru = maxmru;
416 if (!REJECTED(lcp, TY_MRU)) {
417 ua_htons(&lcp->want_mru, o->data);
418 INC_FSM_OPT(TY_MRU, 4, o);
421 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
422 ua_htonl(&lcp->want_magic, o->data);
423 INC_FSM_OPT(TY_MAGICNUM, 6, o);
426 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
427 proto = PROTO_LQR;
428 ua_htons(&proto, o->data);
429 ua_htonl(&lcp->want_lqrperiod, o->data + 2);
430 INC_FSM_OPT(TY_QUALPROTO, 8, o);
433 switch (lcp->want_auth) {
434 case PROTO_PAP:
435 proto = PROTO_PAP;
436 ua_htons(&proto, o->data);
437 INC_FSM_OPT(TY_AUTHPROTO, 4, o);
438 break;
440 case PROTO_CHAP:
441 proto = PROTO_CHAP;
442 ua_htons(&proto, o->data);
443 o->data[2] = lcp->want_authtype;
444 INC_FSM_OPT(TY_AUTHPROTO, 5, o);
445 break;
448 if (!REJECTED(lcp, TY_CALLBACK)) {
449 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
450 *o->data = CALLBACK_AUTH;
451 INC_FSM_OPT(TY_CALLBACK, 3, o);
452 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
453 *o->data = CALLBACK_CBCP;
454 INC_FSM_OPT(TY_CALLBACK, 3, o);
455 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
456 size_t sz = strlen(lcp->want_callback.msg);
458 if (sz > sizeof o->data - 1) {
459 sz = sizeof o->data - 1;
460 log_Printf(LogWARN, "Truncating E164 data to %zu octets (oops!)\n", sz);
462 *o->data = CALLBACK_E164;
463 memcpy(o->data + 1, lcp->want_callback.msg, sz);
464 INC_FSM_OPT(TY_CALLBACK, sz + 3, o);
468 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
469 ua_htons(&lcp->want_mrru, o->data);
470 INC_FSM_OPT(TY_MRRU, 4, o);
472 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
473 INC_FSM_OPT(TY_SHORTSEQ, 2, o);
476 mp = &lcp->fsm.bundle->ncp.mp;
477 if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
478 !REJECTED(lcp, TY_ENDDISC)) {
479 *o->data = mp->cfg.enddisc.class;
480 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
481 INC_FSM_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
484 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
485 MB_LCPOUT);
488 void
489 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
491 /* Don't understand `option' */
492 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
493 MB_LCPOUT);
497 lcp_SendIdentification(struct lcp *lcp)
499 static u_char id; /* Use a private id */
500 u_char msg[DEF_MRU - 3];
501 const char *argv[2];
502 char *exp[2];
504 if (*lcp->cfg.ident == '\0')
505 return 0;
507 argv[0] = lcp->cfg.ident;
508 argv[1] = NULL;
510 command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
512 ua_htonl(&lcp->want_magic, msg);
513 strncpy(msg + 4, exp[0], sizeof msg - 5);
514 msg[sizeof msg - 1] = '\0';
516 fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
517 log_Printf(LogLCP, " MAGICNUM %08x\n", lcp->want_magic);
518 log_Printf(LogLCP, " TEXT %s\n", msg + 4);
520 command_Free(1, exp);
521 return 1;
524 void
525 lcp_RecvIdentification(struct lcp *lcp, char *data)
527 log_Printf(LogLCP, " MAGICNUM %08x\n", lcp->his_magic);
528 log_Printf(LogLCP, " TEXT %s\n", data);
531 static void
532 LcpSentTerminateReq(struct fsm *fp __unused)
534 /* Term REQ just sent by FSM */
537 static void
538 LcpSendTerminateAck(struct fsm *fp, u_char id)
540 /* Send Term ACK please */
541 struct physical *p = link2physical(fp->link);
543 if (p && p->dl->state == DATALINK_CBCP)
544 cbcp_ReceiveTerminateReq(p);
546 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
549 static void
550 LcpLayerStart(struct fsm *fp)
552 /* We're about to start up ! */
553 struct lcp *lcp = fsm2lcp(fp);
555 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
556 lcp->LcpFailedMagic = 0;
557 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
558 lcp->mru_req = 0;
561 static void
562 LcpLayerFinish(struct fsm *fp)
564 /* We're now down */
565 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
568 static int
569 LcpLayerUp(struct fsm *fp)
571 /* We're now up */
572 struct physical *p = link2physical(fp->link);
573 struct lcp *lcp = fsm2lcp(fp);
575 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
576 physical_SetAsyncParams(p, lcp->want_accmap, lcp->his_accmap);
577 lqr_Start(lcp);
578 hdlc_StartTimer(&p->hdlc);
579 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
581 lcp_SendIdentification(lcp);
583 return 1;
586 static void
587 LcpLayerDown(struct fsm *fp)
589 /* About to come down */
590 struct physical *p = link2physical(fp->link);
592 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
593 hdlc_StopTimer(&p->hdlc);
594 lqr_StopTimer(p);
595 lcp_Setup(fsm2lcp(fp), 0);
598 static int
599 E164ok(struct callback *cb, char *req, int sz)
601 char list[sizeof cb->msg], *next;
602 int len;
604 if (!strcmp(cb->msg, "*"))
605 return 1;
607 strncpy(list, cb->msg, sizeof list - 1);
608 list[sizeof list - 1] = '\0';
609 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
610 len = strlen(next);
611 if (sz == len && !memcmp(list, req, sz))
612 return 1;
614 return 0;
617 static int
618 lcp_auth_nak(struct lcp *lcp, struct fsm_decode *dec)
620 struct fsm_opt nak;
622 nak.hdr.id = TY_AUTHPROTO;
624 if (IsAccepted(lcp->cfg.pap)) {
625 nak.hdr.len = 4;
626 nak.data[0] = (unsigned char)(PROTO_PAP >> 8);
627 nak.data[1] = (unsigned char)PROTO_PAP;
628 fsm_nak(dec, &nak);
629 return 1;
632 nak.hdr.len = 5;
633 nak.data[0] = (unsigned char)(PROTO_CHAP >> 8);
634 nak.data[1] = (unsigned char)PROTO_CHAP;
636 if (IsAccepted(lcp->cfg.chap05)) {
637 nak.data[2] = 0x05;
638 fsm_nak(dec, &nak);
639 #ifndef NODES
640 } else if (IsAccepted(lcp->cfg.chap80nt) ||
641 IsAccepted(lcp->cfg.chap80lm)) {
642 nak.data[2] = 0x80;
643 fsm_nak(dec, &nak);
644 } else if (IsAccepted(lcp->cfg.chap81)) {
645 nak.data[2] = 0x81;
646 fsm_nak(dec, &nak);
647 #endif
648 } else {
649 return 0;
652 return 1;
655 static void
656 LcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
657 struct fsm_decode *dec)
659 /* Deal with incoming PROTO_LCP */
660 struct lcp *lcp = fsm2lcp(fp);
661 int pos, op, callback_req, chap_type;
662 size_t sz;
663 u_int32_t magic, accmap;
664 u_short mru, phmtu, maxmtu, maxmru, wantmtu, wantmru, proto;
665 struct lqrreq *req;
666 char request[20], desc[22];
667 struct mp *mp;
668 struct physical *p = link2physical(fp->link);
669 struct fsm_opt *opt, nak;
671 sz = 0;
672 op = callback_req = 0;
674 while (end - cp >= (int)sizeof(opt->hdr)) {
675 if ((opt = fsm_readopt(&cp)) == NULL)
676 break;
678 snprintf(request, sizeof request, " %s[%d]", protoname(opt->hdr.id),
679 opt->hdr.len);
681 switch (opt->hdr.id) {
682 case TY_MRRU:
683 mp = &lcp->fsm.bundle->ncp.mp;
684 ua_ntohs(opt->data, &mru);
685 log_Printf(LogLCP, "%s %u\n", request, mru);
687 switch (mode_type) {
688 case MODE_REQ:
689 if (mp->cfg.mrru) {
690 if (REJECTED(lcp, TY_MRRU))
691 /* Ignore his previous reject so that we REQ next time */
692 lcp->his_reject &= ~(1 << opt->hdr.id);
694 if (mru > MAX_MRU) {
695 /* Push him down to MAX_MRU */
696 lcp->his_mrru = MAX_MRU;
697 nak.hdr.id = TY_MRRU;
698 nak.hdr.len = 4;
699 ua_htons(&lcp->his_mrru, nak.data);
700 fsm_nak(dec, &nak);
701 } else if (mru < MIN_MRU) {
702 /* Push him up to MIN_MRU */
703 lcp->his_mrru = MIN_MRU;
704 nak.hdr.id = TY_MRRU;
705 nak.hdr.len = 4;
706 ua_htons(&lcp->his_mrru, nak.data);
707 fsm_nak(dec, &nak);
708 } else {
709 lcp->his_mrru = mru;
710 fsm_ack(dec, opt);
712 break;
713 } else {
714 fsm_rej(dec, opt);
715 lcp->my_reject |= (1 << opt->hdr.id);
717 break;
718 case MODE_NAK:
719 if (mp->cfg.mrru) {
720 if (REJECTED(lcp, TY_MRRU))
721 /* Must have changed his mind ! */
722 lcp->his_reject &= ~(1 << opt->hdr.id);
724 if (mru > MAX_MRU)
725 lcp->want_mrru = MAX_MRU;
726 else if (mru < MIN_MRU)
727 lcp->want_mrru = MIN_MRU;
728 else
729 lcp->want_mrru = mru;
731 /* else we honour our config and don't send the suggested REQ */
732 break;
733 case MODE_REJ:
734 lcp->his_reject |= (1 << opt->hdr.id);
735 lcp->want_mrru = 0; /* Ah well, no multilink :-( */
736 break;
738 break;
740 case TY_MRU:
741 lcp->mru_req = 1;
742 ua_ntohs(opt->data, &mru);
743 log_Printf(LogLCP, "%s %d\n", request, mru);
745 switch (mode_type) {
746 case MODE_REQ:
747 maxmtu = p ? physical_DeviceMTU(p) : 0;
748 if (lcp->cfg.max_mtu && (!maxmtu || maxmtu > lcp->cfg.max_mtu))
749 maxmtu = lcp->cfg.max_mtu;
750 wantmtu = lcp->cfg.mtu;
751 if (maxmtu && wantmtu > maxmtu) {
752 log_Printf(LogWARN, "%s: Reducing configured MTU from %u to %u\n",
753 fp->link->name, wantmtu, maxmtu);
754 wantmtu = maxmtu;
757 if (maxmtu && mru > maxmtu) {
758 lcp->his_mru = maxmtu;
759 nak.hdr.id = TY_MRU;
760 nak.hdr.len = 4;
761 ua_htons(&lcp->his_mru, nak.data);
762 fsm_nak(dec, &nak);
763 } else if (wantmtu && mru < wantmtu) {
764 /* Push him up to MTU or MIN_MRU */
765 lcp->his_mru = wantmtu;
766 nak.hdr.id = TY_MRU;
767 nak.hdr.len = 4;
768 ua_htons(&lcp->his_mru, nak.data);
769 fsm_nak(dec, &nak);
770 } else {
771 lcp->his_mru = mru;
772 fsm_ack(dec, opt);
774 break;
775 case MODE_NAK:
776 maxmru = p ? physical_DeviceMTU(p) : 0;
777 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
778 maxmru = lcp->cfg.max_mru;
779 wantmru = lcp->cfg.mru > maxmru ? maxmru : lcp->cfg.mru;
781 if (wantmru && mru > wantmru)
782 lcp->want_mru = wantmru;
783 else if (mru > maxmru)
784 lcp->want_mru = maxmru;
785 else if (mru < MIN_MRU)
786 lcp->want_mru = MIN_MRU;
787 else
788 lcp->want_mru = mru;
789 break;
790 case MODE_REJ:
791 lcp->his_reject |= (1 << opt->hdr.id);
792 break;
794 break;
796 case TY_ACCMAP:
797 ua_ntohl(opt->data, &accmap);
798 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
800 switch (mode_type) {
801 case MODE_REQ:
802 lcp->his_accmap = accmap;
803 fsm_ack(dec, opt);
804 break;
805 case MODE_NAK:
806 lcp->want_accmap = accmap;
807 break;
808 case MODE_REJ:
809 lcp->his_reject |= (1 << opt->hdr.id);
810 break;
812 break;
814 case TY_AUTHPROTO:
815 ua_ntohs(opt->data, &proto);
816 chap_type = opt->hdr.len == 5 ? opt->data[2] : 0;
818 log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
819 Auth2Nam(proto, chap_type));
821 switch (mode_type) {
822 case MODE_REQ:
823 switch (proto) {
824 case PROTO_PAP:
825 if (opt->hdr.len == 4 && IsAccepted(lcp->cfg.pap)) {
826 lcp->his_auth = proto;
827 lcp->his_authtype = 0;
828 fsm_ack(dec, opt);
829 } else if (!lcp_auth_nak(lcp, dec)) {
830 lcp->my_reject |= (1 << opt->hdr.id);
831 fsm_rej(dec, opt);
833 break;
835 case PROTO_CHAP:
836 if ((chap_type == 0x05 && IsAccepted(lcp->cfg.chap05))
837 #ifndef NODES
838 || (chap_type == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
839 (IsAccepted(lcp->cfg.chap80lm))))
840 || (chap_type == 0x81 && IsAccepted(lcp->cfg.chap81))
841 #endif
843 lcp->his_auth = proto;
844 lcp->his_authtype = chap_type;
845 fsm_ack(dec, opt);
846 } else {
847 #ifdef NODES
848 if (chap_type == 0x80) {
849 log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
850 } else if (chap_type == 0x81) {
851 log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
852 } else
853 #endif
854 if (chap_type != 0x05)
855 log_Printf(LogWARN, "%s not supported\n",
856 Auth2Nam(PROTO_CHAP, chap_type));
858 if (!lcp_auth_nak(lcp, dec)) {
859 lcp->my_reject |= (1 << opt->hdr.id);
860 fsm_rej(dec, opt);
863 break;
865 default:
866 log_Printf(LogLCP, "%s 0x%04x - not recognised\n",
867 request, proto);
868 if (!lcp_auth_nak(lcp, dec)) {
869 lcp->my_reject |= (1 << opt->hdr.id);
870 fsm_rej(dec, opt);
872 break;
874 break;
876 case MODE_NAK:
877 switch (proto) {
878 case PROTO_PAP:
879 if (IsEnabled(lcp->cfg.pap)) {
880 lcp->want_auth = PROTO_PAP;
881 lcp->want_authtype = 0;
882 } else {
883 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
884 lcp->his_reject |= (1 << opt->hdr.id);
886 break;
887 case PROTO_CHAP:
888 if (chap_type == 0x05 && IsEnabled(lcp->cfg.chap05)) {
889 lcp->want_auth = PROTO_CHAP;
890 lcp->want_authtype = 0x05;
891 #ifndef NODES
892 } else if (chap_type == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
893 IsEnabled(lcp->cfg.chap80lm))) {
894 lcp->want_auth = PROTO_CHAP;
895 lcp->want_authtype = 0x80;
896 } else if (chap_type == 0x81 && IsEnabled(lcp->cfg.chap81)) {
897 lcp->want_auth = PROTO_CHAP;
898 lcp->want_authtype = 0x81;
899 #endif
900 } else {
901 #ifdef NODES
902 if (chap_type == 0x80) {
903 log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
904 " without DES)\n");
905 } else if (chap_type == 0x81) {
906 log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
907 " without DES)\n");
908 } else
909 #endif
910 log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
911 Auth2Nam(PROTO_CHAP, chap_type),
912 #ifndef NODES
913 (chap_type == 0x80 || chap_type == 0x81) ? "configured" :
914 #endif
915 "supported");
916 lcp->his_reject |= (1 << opt->hdr.id);
918 break;
919 default:
920 /* We've been NAK'd with something we don't understand :-( */
921 lcp->his_reject |= (1 << opt->hdr.id);
922 break;
924 break;
926 case MODE_REJ:
927 lcp->his_reject |= (1 << opt->hdr.id);
928 break;
930 break;
932 case TY_QUALPROTO:
933 req = (struct lqrreq *)opt;
934 log_Printf(LogLCP, "%s proto %x, interval %lums\n",
935 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
936 switch (mode_type) {
937 case MODE_REQ:
938 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr)) {
939 fsm_rej(dec, opt);
940 lcp->my_reject |= (1 << opt->hdr.id);
941 } else {
942 lcp->his_lqrperiod = ntohl(req->period);
943 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
944 lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
945 req->period = htonl(lcp->his_lqrperiod);
946 fsm_ack(dec, opt);
948 break;
949 case MODE_NAK:
950 lcp->want_lqrperiod = ntohl(req->period);
951 break;
952 case MODE_REJ:
953 lcp->his_reject |= (1 << opt->hdr.id);
954 break;
956 break;
958 case TY_MAGICNUM:
959 ua_ntohl(opt->data, &magic);
960 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
962 switch (mode_type) {
963 case MODE_REQ:
964 if (lcp->want_magic) {
965 /* Validate magic number */
966 if (magic == lcp->want_magic) {
967 sigset_t emptyset;
969 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
970 (u_long)magic, ++lcp->LcpFailedMagic);
971 lcp->want_magic = GenerateMagic();
972 fsm_nak(dec, opt);
973 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
974 sigemptyset(&emptyset);
975 sigsuspend(&emptyset);
976 } else {
977 lcp->his_magic = magic;
978 lcp->LcpFailedMagic = 0;
979 fsm_ack(dec, opt);
981 } else {
982 lcp->my_reject |= (1 << opt->hdr.id);
983 fsm_rej(dec, opt);
985 break;
986 case MODE_NAK:
987 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
988 lcp->want_magic = GenerateMagic();
989 break;
990 case MODE_REJ:
991 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
992 lcp->want_magic = 0;
993 lcp->his_reject |= (1 << opt->hdr.id);
994 break;
996 break;
998 case TY_PROTOCOMP:
999 log_Printf(LogLCP, "%s\n", request);
1001 switch (mode_type) {
1002 case MODE_REQ:
1003 if (IsAccepted(lcp->cfg.protocomp)) {
1004 lcp->his_protocomp = 1;
1005 fsm_ack(dec, opt);
1006 } else {
1007 #ifdef OLDMST
1008 /* MorningStar before v1.3 needs NAK */
1009 fsm_nak(dec, opt);
1010 #else
1011 fsm_rej(dec, opt);
1012 lcp->my_reject |= (1 << opt->hdr.id);
1013 #endif
1015 break;
1016 case MODE_NAK:
1017 case MODE_REJ:
1018 lcp->want_protocomp = 0;
1019 lcp->his_reject |= (1 << opt->hdr.id);
1020 break;
1022 break;
1024 case TY_ACFCOMP:
1025 log_Printf(LogLCP, "%s\n", request);
1026 switch (mode_type) {
1027 case MODE_REQ:
1028 if (IsAccepted(lcp->cfg.acfcomp)) {
1029 lcp->his_acfcomp = 1;
1030 fsm_ack(dec, opt);
1031 } else {
1032 #ifdef OLDMST
1033 /* MorningStar before v1.3 needs NAK */
1034 fsm_nak(dec, opt);
1035 #else
1036 fsm_rej(dec, opt);
1037 lcp->my_reject |= (1 << opt->hdr.id);
1038 #endif
1040 break;
1041 case MODE_NAK:
1042 case MODE_REJ:
1043 lcp->want_acfcomp = 0;
1044 lcp->his_reject |= (1 << opt->hdr.id);
1045 break;
1047 break;
1049 case TY_SDP:
1050 log_Printf(LogLCP, "%s\n", request);
1051 switch (mode_type) {
1052 case MODE_REQ:
1053 case MODE_NAK:
1054 case MODE_REJ:
1055 break;
1057 break;
1059 case TY_CALLBACK:
1060 if (opt->hdr.len == 2) {
1061 op = CALLBACK_NONE;
1062 sz = 0;
1063 } else {
1064 op = (int)opt->data[0];
1065 sz = opt->hdr.len - 3;
1067 switch (op) {
1068 case CALLBACK_AUTH:
1069 log_Printf(LogLCP, "%s Auth\n", request);
1070 break;
1071 case CALLBACK_DIALSTRING:
1072 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, (int)sz,
1073 opt->data + 1);
1074 break;
1075 case CALLBACK_LOCATION:
1076 log_Printf(LogLCP, "%s Location %.*s\n", request, (int)sz, opt->data + 1);
1077 break;
1078 case CALLBACK_E164:
1079 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, (int)sz, opt->data + 1);
1080 break;
1081 case CALLBACK_NAME:
1082 log_Printf(LogLCP, "%s Name %.*s\n", request, (int)sz, opt->data + 1);
1083 break;
1084 case CALLBACK_CBCP:
1085 log_Printf(LogLCP, "%s CBCP\n", request);
1086 break;
1087 default:
1088 log_Printf(LogLCP, "%s ???\n", request);
1089 break;
1092 switch (mode_type) {
1093 case MODE_REQ:
1094 callback_req = 1;
1095 if (p->type != PHYS_DIRECT) {
1096 fsm_rej(dec, opt);
1097 lcp->my_reject |= (1 << opt->hdr.id);
1099 nak.hdr.id = opt->hdr.id;
1100 nak.hdr.len = 3;
1101 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
1102 (op != CALLBACK_AUTH || p->link.lcp.want_auth) &&
1103 (op != CALLBACK_E164 ||
1104 E164ok(&p->dl->cfg.callback, opt->data + 1, sz))) {
1105 lcp->his_callback.opmask = CALLBACK_BIT(op);
1106 if (sz > sizeof lcp->his_callback.msg - 1) {
1107 sz = sizeof lcp->his_callback.msg - 1;
1108 log_Printf(LogWARN, "Truncating option arg to %zu octets\n", sz);
1110 memcpy(lcp->his_callback.msg, opt->data + 1, sz);
1111 lcp->his_callback.msg[sz] = '\0';
1112 fsm_ack(dec, opt);
1113 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1114 p->link.lcp.auth_ineed) {
1115 nak.data[0] = CALLBACK_AUTH;
1116 fsm_nak(dec, &nak);
1117 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1118 nak.data[0] = CALLBACK_CBCP;
1119 fsm_nak(dec, &nak);
1120 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1121 nak.data[0] = CALLBACK_E164;
1122 fsm_nak(dec, &nak);
1123 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1124 log_Printf(LogWARN, "Cannot insist on auth callback without"
1125 " PAP or CHAP enabled !\n");
1126 nak.data[0] = 2;
1127 fsm_nak(dec, &nak);
1128 } else {
1129 lcp->my_reject |= (1 << opt->hdr.id);
1130 fsm_rej(dec, opt);
1132 break;
1133 case MODE_NAK:
1134 /* We don't do what he NAKs with, we do things in our preferred order */
1135 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1136 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1137 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1138 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1139 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1140 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1141 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1142 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1143 lcp->want_callback.opmask = 0;
1144 } else if (!lcp->want_callback.opmask) {
1145 log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1146 fsm_Close(&lcp->fsm);
1148 break;
1149 case MODE_REJ:
1150 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1151 lcp->his_reject |= (1 << opt->hdr.id);
1152 lcp->want_callback.opmask = 0;
1153 } else {
1154 log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1155 fsm_Close(&lcp->fsm);
1157 break;
1159 break;
1161 case TY_SHORTSEQ:
1162 mp = &lcp->fsm.bundle->ncp.mp;
1163 log_Printf(LogLCP, "%s\n", request);
1165 switch (mode_type) {
1166 case MODE_REQ:
1167 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1168 lcp->his_shortseq = 1;
1169 fsm_ack(dec, opt);
1170 } else {
1171 fsm_rej(dec, opt);
1172 lcp->my_reject |= (1 << opt->hdr.id);
1174 break;
1175 case MODE_NAK:
1177 * He's trying to get us to ask for short sequence numbers.
1178 * We ignore the NAK and honour our configuration file instead.
1180 break;
1181 case MODE_REJ:
1182 lcp->his_reject |= (1 << opt->hdr.id);
1183 lcp->want_shortseq = 0; /* For when we hit MP */
1184 break;
1186 break;
1188 case TY_ENDDISC:
1189 mp = &lcp->fsm.bundle->ncp.mp;
1190 log_Printf(LogLCP, "%s %s\n", request,
1191 mp_Enddisc(opt->data[0], opt->data + 1, opt->hdr.len - 3));
1192 switch (mode_type) {
1193 case MODE_REQ:
1194 if (!p) {
1195 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1196 fsm_rej(dec, opt);
1197 lcp->my_reject |= (1 << opt->hdr.id);
1198 } else if (!IsAccepted(mp->cfg.negenddisc)) {
1199 lcp->my_reject |= (1 << opt->hdr.id);
1200 fsm_rej(dec, opt);
1201 } else if (opt->hdr.len < sizeof p->dl->peer.enddisc.address + 3 &&
1202 opt->data[0] <= MAX_ENDDISC_CLASS) {
1203 p->dl->peer.enddisc.class = opt->data[0];
1204 p->dl->peer.enddisc.len = opt->hdr.len - 3;
1205 memcpy(p->dl->peer.enddisc.address, opt->data + 1, opt->hdr.len - 3);
1206 p->dl->peer.enddisc.address[opt->hdr.len - 3] = '\0';
1207 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1208 fsm_ack(dec, opt);
1209 } else {
1210 if (opt->data[0] > MAX_ENDDISC_CLASS)
1211 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1212 opt->data[0]);
1213 else
1214 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1215 (long)(sizeof p->dl->peer.enddisc.address - 1));
1216 fsm_rej(dec, opt);
1217 lcp->my_reject |= (1 << opt->hdr.id);
1219 break;
1221 case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
1222 case MODE_REJ:
1223 lcp->his_reject |= (1 << opt->hdr.id);
1224 break;
1226 break;
1228 default:
1229 sz = (sizeof desc - 2) / 2;
1230 if (sz + 2 > opt->hdr.len)
1231 sz = opt->hdr.len - 2;
1232 pos = 0;
1233 desc[0] = sz ? ' ' : '\0';
1234 for (pos = 0; sz--; pos++)
1235 sprintf(desc+(pos<<1)+1, "%02x", opt->data[pos]);
1237 log_Printf(LogLCP, "%s%s\n", request, desc);
1239 if (mode_type == MODE_REQ) {
1240 fsm_rej(dec, opt);
1241 lcp->my_reject |= (1 << opt->hdr.id);
1243 break;
1247 if (mode_type != MODE_NOP) {
1248 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1249 p->dl->cfg.callback.opmask && !callback_req &&
1250 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1251 /* We *REQUIRE* that the peer requests callback */
1252 nak.hdr.id = TY_CALLBACK;
1253 nak.hdr.len = 3;
1254 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1255 p->link.lcp.want_auth)
1256 nak.data[0] = CALLBACK_AUTH;
1257 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1258 nak.data[0] = CALLBACK_CBCP;
1259 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1260 nak.data[0] = CALLBACK_E164;
1261 else {
1262 log_Printf(LogWARN, "Cannot insist on auth callback without"
1263 " PAP or CHAP enabled !\n");
1264 nak.hdr.len = 2; /* XXX: Silly ! */
1266 fsm_nak(dec, &nak);
1268 if (mode_type == MODE_REQ && !lcp->mru_req) {
1269 mru = DEF_MRU;
1270 phmtu = p ? physical_DeviceMTU(p) : 0;
1271 if (phmtu && mru > phmtu)
1272 mru = phmtu;
1273 if (mru > lcp->cfg.max_mtu)
1274 mru = lcp->cfg.max_mtu;
1275 if (mru < DEF_MRU) {
1276 /* Don't let the peer use the default MRU */
1277 lcp->his_mru = lcp->cfg.mtu && lcp->cfg.mtu < mru ? lcp->cfg.mtu : mru;
1278 nak.hdr.id = TY_MRU;
1279 nak.hdr.len = 4;
1280 ua_htons(&lcp->his_mru, nak.data);
1281 fsm_nak(dec, &nak);
1282 lcp->mru_req = 1; /* Don't keep NAK'ing this */
1285 fsm_opt_normalise(dec);
1289 extern struct mbuf *
1290 lcp_Input(struct bundle *bundle __unused, struct link *l, struct mbuf *bp)
1292 /* Got PROTO_LCP from link */
1293 m_settype(bp, MB_LCPIN);
1294 fsm_Input(&l->lcp.fsm, bp);
1295 return NULL;