cpdup - Fix NULL pointer indirection on lost socket
[dragonfly.git] / usr.sbin / ppp / lcp.c
blob8f785a1532d2a8620cb8225e5a86437197758d10
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 $
31 #include <sys/param.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <sys/socket.h>
36 #include <sys/un.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <termios.h>
44 #include <unistd.h>
46 #include "layer.h"
47 #include "ua.h"
48 #include "defs.h"
49 #include "command.h"
50 #include "mbuf.h"
51 #include "log.h"
52 #include "timer.h"
53 #include "fsm.h"
54 #include "iplist.h"
55 #include "throughput.h"
56 #include "proto.h"
57 #include "descriptor.h"
58 #include "lqr.h"
59 #include "hdlc.h"
60 #include "lcp.h"
61 #include "ccp.h"
62 #include "async.h"
63 #include "link.h"
64 #include "physical.h"
65 #include "prompt.h"
66 #include "slcompress.h"
67 #include "ncpaddr.h"
68 #include "ipcp.h"
69 #include "filter.h"
70 #include "mp.h"
71 #include "chat.h"
72 #include "auth.h"
73 #include "chap.h"
74 #include "cbcp.h"
75 #include "datalink.h"
76 #ifndef NORADIUS
77 #include "radius.h"
78 #endif
79 #include "ipv6cp.h"
80 #include "ncp.h"
81 #include "bundle.h"
83 /* for received LQRs */
84 struct lqrreq {
85 struct fsm_opt_hdr hdr;
86 u_short proto; /* Quality protocol */
87 u_int32_t period; /* Reporting interval */
90 static int LcpLayerUp(struct fsm *);
91 static void LcpLayerDown(struct fsm *);
92 static void LcpLayerStart(struct fsm *);
93 static void LcpLayerFinish(struct fsm *);
94 static void LcpInitRestartCounter(struct fsm *, int);
95 static void LcpSendConfigReq(struct fsm *);
96 static void LcpSentTerminateReq(struct fsm *);
97 static void LcpSendTerminateAck(struct fsm *, u_char);
98 static void LcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
99 struct fsm_decode *);
101 static struct fsm_callbacks lcp_Callbacks = {
102 LcpLayerUp,
103 LcpLayerDown,
104 LcpLayerStart,
105 LcpLayerFinish,
106 LcpInitRestartCounter,
107 LcpSendConfigReq,
108 LcpSentTerminateReq,
109 LcpSendTerminateAck,
110 LcpDecodeConfig,
111 fsm_NullRecvResetReq,
112 fsm_NullRecvResetAck
115 static const char * const lcp_TimerNames[] =
116 {"LCP restart", "LCP openmode", "LCP stopped"};
118 static const char *
119 protoname(unsigned proto)
121 static const char * const cftypes[] = {
122 /* Check out the latest ``Assigned numbers'' rfc (1700) */
123 NULL,
124 "MRU", /* 1: Maximum-Receive-Unit */
125 "ACCMAP", /* 2: Async-Control-Character-Map */
126 "AUTHPROTO", /* 3: Authentication-Protocol */
127 "QUALPROTO", /* 4: Quality-Protocol */
128 "MAGICNUM", /* 5: Magic-Number */
129 "RESERVED", /* 6: RESERVED */
130 "PROTOCOMP", /* 7: Protocol-Field-Compression */
131 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */
132 "FCSALT", /* 9: FCS-Alternatives */
133 "SDP", /* 10: Self-Describing-Pad */
134 "NUMMODE", /* 11: Numbered-Mode */
135 "MULTIPROC", /* 12: Multi-Link-Procedure */
136 "CALLBACK", /* 13: Callback */
137 "CONTIME", /* 14: Connect-Time */
138 "COMPFRAME", /* 15: Compound-Frames */
139 "NDE", /* 16: Nominal-Data-Encapsulation */
140 "MRRU", /* 17: Multilink-MRRU */
141 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
142 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
143 "PROPRIETRY", /* 20: Proprietary */
144 "DCEID", /* 21: DCE-Identifier */
145 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */
146 "LDBACP", /* 23: Link Discriminator for BACP */
149 if (proto > NELEM(cftypes) || cftypes[proto] == NULL)
150 return HexStr(proto, NULL, 0);
152 return cftypes[proto];
156 lcp_ReportStatus(struct cmdargs const *arg)
158 struct link *l;
159 struct lcp *lcp;
161 l = command_ChooseLink(arg);
162 lcp = &l->lcp;
164 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
165 State2Nam(lcp->fsm.state));
166 prompt_Printf(arg->prompt,
167 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
168 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
169 lcp->his_mru, (u_long)lcp->his_accmap,
170 lcp->his_protocomp ? "on" : "off",
171 lcp->his_acfcomp ? "on" : "off",
172 (u_long)lcp->his_magic, lcp->his_mrru,
173 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
174 prompt_Printf(arg->prompt,
175 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
176 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
177 lcp->want_mru, (u_long)lcp->want_accmap,
178 lcp->want_protocomp ? "on" : "off",
179 lcp->want_acfcomp ? "on" : "off",
180 (u_long)lcp->want_magic, lcp->want_mrru,
181 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
183 if (lcp->cfg.mru)
184 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d (max %d), ",
185 lcp->cfg.mru, lcp->cfg.max_mru);
186 else
187 prompt_Printf(arg->prompt, "\n Defaults: MRU = any (max %d), ",
188 lcp->cfg.max_mru);
189 if (lcp->cfg.mtu)
190 prompt_Printf(arg->prompt, "MTU = %d (max %d), ",
191 lcp->cfg.mtu, lcp->cfg.max_mtu);
192 else
193 prompt_Printf(arg->prompt, "MTU = any (max %d), ", lcp->cfg.max_mtu);
194 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
195 prompt_Printf(arg->prompt, " LQR period = %us, ",
196 lcp->cfg.lqrperiod);
197 prompt_Printf(arg->prompt, "Open Mode = %s",
198 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
199 if (lcp->cfg.openmode > 0)
200 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
201 prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
202 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
203 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
204 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
205 prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
206 prompt_Printf(arg->prompt, "\n Negotiation:\n");
207 prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
208 command_ShowNegval(lcp->cfg.acfcomp));
209 prompt_Printf(arg->prompt, " CHAP = %s\n",
210 command_ShowNegval(lcp->cfg.chap05));
211 #ifndef NODES
212 prompt_Printf(arg->prompt, " CHAP80 = %s\n",
213 command_ShowNegval(lcp->cfg.chap80nt));
214 prompt_Printf(arg->prompt, " LANMan = %s\n",
215 command_ShowNegval(lcp->cfg.chap80lm));
216 prompt_Printf(arg->prompt, " CHAP81 = %s\n",
217 command_ShowNegval(lcp->cfg.chap81));
218 #endif
219 prompt_Printf(arg->prompt, " LQR = %s\n",
220 command_ShowNegval(lcp->cfg.lqr));
221 prompt_Printf(arg->prompt, " PAP = %s\n",
222 command_ShowNegval(lcp->cfg.pap));
223 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
224 command_ShowNegval(lcp->cfg.protocomp));
226 return 0;
229 static u_int32_t
230 GenerateMagic(void)
232 /* Generate random number which will be used as magic number */
233 randinit();
234 return random();
237 void
238 lcp_SetupCallbacks(struct lcp *lcp)
240 lcp->fsm.fn = &lcp_Callbacks;
241 lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
242 lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
243 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
246 void
247 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
248 const struct fsm_parent *parent)
250 /* Initialise ourselves */
251 int mincode = parent ? 1 : LCP_MINMPCODE;
253 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
254 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
256 lcp->cfg.mru = 0;
257 lcp->cfg.max_mru = MAX_MRU;
258 lcp->cfg.mtu = 0;
259 lcp->cfg.max_mtu = MAX_MTU;
260 lcp->cfg.accmap = 0;
261 lcp->cfg.openmode = 1;
262 lcp->cfg.lqrperiod = DEF_LQRPERIOD;
263 lcp->cfg.fsm.timeout = DEF_FSMRETRY;
264 lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
265 lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
267 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
268 lcp->cfg.chap05 = NEG_ACCEPTED;
269 #ifndef NODES
270 lcp->cfg.chap80nt = NEG_ACCEPTED;
271 lcp->cfg.chap80lm = 0;
272 lcp->cfg.chap81 = NEG_ACCEPTED;
273 #endif
274 lcp->cfg.lqr = NEG_ACCEPTED;
275 lcp->cfg.pap = NEG_ACCEPTED;
276 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
277 *lcp->cfg.ident = '\0';
279 lcp_Setup(lcp, lcp->cfg.openmode);
282 void
283 lcp_Setup(struct lcp *lcp, int openmode)
285 struct physical *p = link2physical(lcp->fsm.link);
287 lcp->fsm.open_mode = openmode;
289 lcp->his_mru = DEF_MRU;
290 lcp->his_mrru = 0;
291 lcp->his_magic = 0;
292 lcp->his_lqrperiod = 0;
293 lcp->his_acfcomp = 0;
294 lcp->his_auth = 0;
295 lcp->his_authtype = 0;
296 lcp->his_callback.opmask = 0;
297 lcp->his_shortseq = 0;
298 lcp->mru_req = 0;
300 if ((lcp->want_mru = lcp->cfg.mru) == 0)
301 lcp->want_mru = DEF_MRU;
302 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
303 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
304 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
306 if (lcp->fsm.parent) {
307 lcp->his_accmap = 0xffffffff;
308 lcp->want_accmap = lcp->cfg.accmap;
309 lcp->his_protocomp = 0;
310 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
311 lcp->want_magic = GenerateMagic();
313 if (IsEnabled(lcp->cfg.chap05)) {
314 lcp->want_auth = PROTO_CHAP;
315 lcp->want_authtype = 0x05;
316 #ifndef NODES
317 } else if (IsEnabled(lcp->cfg.chap80nt) ||
318 IsEnabled(lcp->cfg.chap80lm)) {
319 lcp->want_auth = PROTO_CHAP;
320 lcp->want_authtype = 0x80;
321 } else if (IsEnabled(lcp->cfg.chap81)) {
322 lcp->want_auth = PROTO_CHAP;
323 lcp->want_authtype = 0x81;
324 #endif
325 } else if (IsEnabled(lcp->cfg.pap)) {
326 lcp->want_auth = PROTO_PAP;
327 lcp->want_authtype = 0;
328 } else {
329 lcp->want_auth = 0;
330 lcp->want_authtype = 0;
333 if (p->type != PHYS_DIRECT)
334 memcpy(&lcp->want_callback, &p->dl->cfg.callback,
335 sizeof(struct callback));
336 else
337 lcp->want_callback.opmask = 0;
338 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
339 lcp->cfg.lqrperiod * 100 : 0;
340 } else {
341 lcp->his_accmap = lcp->want_accmap = 0;
342 lcp->his_protocomp = lcp->want_protocomp = 1;
343 lcp->want_magic = 0;
344 lcp->want_auth = 0;
345 lcp->want_authtype = 0;
346 lcp->want_callback.opmask = 0;
347 lcp->want_lqrperiod = 0;
350 lcp->his_reject = lcp->my_reject = 0;
351 lcp->auth_iwait = lcp->auth_ineed = 0;
352 lcp->LcpFailedMagic = 0;
355 static void
356 LcpInitRestartCounter(struct fsm *fp, int what)
358 /* Set fsm timer load */
359 struct lcp *lcp = fsm2lcp(fp);
361 fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
362 switch (what) {
363 case FSM_REQ_TIMER:
364 fp->restart = lcp->cfg.fsm.maxreq;
365 break;
366 case FSM_TRM_TIMER:
367 fp->restart = lcp->cfg.fsm.maxtrm;
368 break;
369 default:
370 fp->restart = 1;
371 break;
375 static void
376 LcpSendConfigReq(struct fsm *fp)
378 /* Send config REQ please */
379 struct physical *p = link2physical(fp->link);
380 struct lcp *lcp = fsm2lcp(fp);
381 u_char buff[200];
382 struct fsm_opt *o;
383 struct mp *mp;
384 u_int16_t proto;
385 u_short maxmru;
387 if (!p) {
388 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
389 fp->link->name);
390 return;
393 o = (struct fsm_opt *)buff;
394 if (!physical_IsSync(p)) {
395 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
396 INC_FSM_OPT(TY_ACFCOMP, 2, o);
398 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
399 INC_FSM_OPT(TY_PROTOCOMP, 2, o);
401 if (!REJECTED(lcp, TY_ACCMAP)) {
402 ua_htonl(&lcp->want_accmap, o->data);
403 INC_FSM_OPT(TY_ACCMAP, 6, o);
407 maxmru = p ? physical_DeviceMTU(p) : 0;
408 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
409 maxmru = lcp->cfg.max_mru;
410 if (maxmru && lcp->want_mru > maxmru) {
411 log_Printf(LogWARN, "%s: Reducing configured MRU from %u to %u\n",
412 fp->link->name, lcp->want_mru, maxmru);
413 lcp->want_mru = maxmru;
415 if (!REJECTED(lcp, TY_MRU)) {
416 ua_htons(&lcp->want_mru, o->data);
417 INC_FSM_OPT(TY_MRU, 4, o);
420 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
421 ua_htonl(&lcp->want_magic, o->data);
422 INC_FSM_OPT(TY_MAGICNUM, 6, o);
425 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
426 proto = PROTO_LQR;
427 ua_htons(&proto, o->data);
428 ua_htonl(&lcp->want_lqrperiod, o->data + 2);
429 INC_FSM_OPT(TY_QUALPROTO, 8, o);
432 switch (lcp->want_auth) {
433 case PROTO_PAP:
434 proto = PROTO_PAP;
435 ua_htons(&proto, o->data);
436 INC_FSM_OPT(TY_AUTHPROTO, 4, o);
437 break;
439 case PROTO_CHAP:
440 proto = PROTO_CHAP;
441 ua_htons(&proto, o->data);
442 o->data[2] = lcp->want_authtype;
443 INC_FSM_OPT(TY_AUTHPROTO, 5, o);
444 break;
447 if (!REJECTED(lcp, TY_CALLBACK)) {
448 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
449 *o->data = CALLBACK_AUTH;
450 INC_FSM_OPT(TY_CALLBACK, 3, o);
451 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
452 *o->data = CALLBACK_CBCP;
453 INC_FSM_OPT(TY_CALLBACK, 3, o);
454 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
455 size_t sz = strlen(lcp->want_callback.msg);
457 if (sz > sizeof o->data - 1) {
458 sz = sizeof o->data - 1;
459 log_Printf(LogWARN, "Truncating E164 data to %zu octets (oops!)\n", sz);
461 *o->data = CALLBACK_E164;
462 memcpy(o->data + 1, lcp->want_callback.msg, sz);
463 INC_FSM_OPT(TY_CALLBACK, sz + 3, o);
467 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
468 ua_htons(&lcp->want_mrru, o->data);
469 INC_FSM_OPT(TY_MRRU, 4, o);
471 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
472 INC_FSM_OPT(TY_SHORTSEQ, 2, o);
475 mp = &lcp->fsm.bundle->ncp.mp;
476 if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
477 !REJECTED(lcp, TY_ENDDISC)) {
478 *o->data = mp->cfg.enddisc.class;
479 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
480 INC_FSM_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
483 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
484 MB_LCPOUT);
487 void
488 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
490 /* Don't understand `option' */
491 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
492 MB_LCPOUT);
496 lcp_SendIdentification(struct lcp *lcp)
498 static u_char id; /* Use a private id */
499 u_char msg[DEF_MRU - 3];
500 const char *argv[2];
501 char *exp[2];
503 if (*lcp->cfg.ident == '\0')
504 return 0;
506 argv[0] = lcp->cfg.ident;
507 argv[1] = NULL;
509 command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
511 ua_htonl(&lcp->want_magic, msg);
512 strncpy(msg + 4, exp[0], sizeof msg - 5);
513 msg[sizeof msg - 1] = '\0';
515 fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
516 log_Printf(LogLCP, " MAGICNUM %08x\n", lcp->want_magic);
517 log_Printf(LogLCP, " TEXT %s\n", msg + 4);
519 command_Free(1, exp);
520 return 1;
523 void
524 lcp_RecvIdentification(struct lcp *lcp, char *data)
526 log_Printf(LogLCP, " MAGICNUM %08x\n", lcp->his_magic);
527 log_Printf(LogLCP, " TEXT %s\n", data);
530 static void
531 LcpSentTerminateReq(struct fsm *fp __unused)
533 /* Term REQ just sent by FSM */
536 static void
537 LcpSendTerminateAck(struct fsm *fp, u_char id)
539 /* Send Term ACK please */
540 struct physical *p = link2physical(fp->link);
542 if (p && p->dl->state == DATALINK_CBCP)
543 cbcp_ReceiveTerminateReq(p);
545 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
548 static void
549 LcpLayerStart(struct fsm *fp)
551 /* We're about to start up ! */
552 struct lcp *lcp = fsm2lcp(fp);
554 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
555 lcp->LcpFailedMagic = 0;
556 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
557 lcp->mru_req = 0;
560 static void
561 LcpLayerFinish(struct fsm *fp)
563 /* We're now down */
564 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
567 static int
568 LcpLayerUp(struct fsm *fp)
570 /* We're now up */
571 struct physical *p = link2physical(fp->link);
572 struct lcp *lcp = fsm2lcp(fp);
574 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
575 physical_SetAsyncParams(p, lcp->want_accmap, lcp->his_accmap);
576 lqr_Start(lcp);
577 hdlc_StartTimer(&p->hdlc);
578 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
580 lcp_SendIdentification(lcp);
582 return 1;
585 static void
586 LcpLayerDown(struct fsm *fp)
588 /* About to come down */
589 struct physical *p = link2physical(fp->link);
591 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
592 hdlc_StopTimer(&p->hdlc);
593 lqr_StopTimer(p);
594 lcp_Setup(fsm2lcp(fp), 0);
597 static int
598 E164ok(struct callback *cb, char *req, int sz)
600 char list[sizeof cb->msg], *next;
601 int len;
603 if (!strcmp(cb->msg, "*"))
604 return 1;
606 strncpy(list, cb->msg, sizeof list - 1);
607 list[sizeof list - 1] = '\0';
608 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
609 len = strlen(next);
610 if (sz == len && !memcmp(list, req, sz))
611 return 1;
613 return 0;
616 static int
617 lcp_auth_nak(struct lcp *lcp, struct fsm_decode *dec)
619 struct fsm_opt nak;
621 nak.hdr.id = TY_AUTHPROTO;
623 if (IsAccepted(lcp->cfg.pap)) {
624 nak.hdr.len = 4;
625 nak.data[0] = (unsigned char)(PROTO_PAP >> 8);
626 nak.data[1] = (unsigned char)PROTO_PAP;
627 fsm_nak(dec, &nak);
628 return 1;
631 nak.hdr.len = 5;
632 nak.data[0] = (unsigned char)(PROTO_CHAP >> 8);
633 nak.data[1] = (unsigned char)PROTO_CHAP;
635 if (IsAccepted(lcp->cfg.chap05)) {
636 nak.data[2] = 0x05;
637 fsm_nak(dec, &nak);
638 #ifndef NODES
639 } else if (IsAccepted(lcp->cfg.chap80nt) ||
640 IsAccepted(lcp->cfg.chap80lm)) {
641 nak.data[2] = 0x80;
642 fsm_nak(dec, &nak);
643 } else if (IsAccepted(lcp->cfg.chap81)) {
644 nak.data[2] = 0x81;
645 fsm_nak(dec, &nak);
646 #endif
647 } else {
648 return 0;
651 return 1;
654 static void
655 LcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
656 struct fsm_decode *dec)
658 /* Deal with incoming PROTO_LCP */
659 struct lcp *lcp = fsm2lcp(fp);
660 int pos, op, callback_req, chap_type;
661 size_t sz;
662 u_int32_t magic, accmap;
663 u_short mru, phmtu, maxmtu, maxmru, wantmtu, wantmru, proto;
664 struct lqrreq *req;
665 char request[20], desc[22];
666 struct mp *mp;
667 struct physical *p = link2physical(fp->link);
668 struct fsm_opt *opt, nak;
670 sz = 0;
671 op = callback_req = 0;
673 while (end - cp >= (int)sizeof(opt->hdr)) {
674 if ((opt = fsm_readopt(&cp)) == NULL)
675 break;
677 snprintf(request, sizeof request, " %s[%d]", protoname(opt->hdr.id),
678 opt->hdr.len);
680 switch (opt->hdr.id) {
681 case TY_MRRU:
682 mp = &lcp->fsm.bundle->ncp.mp;
683 ua_ntohs(opt->data, &mru);
684 log_Printf(LogLCP, "%s %u\n", request, mru);
686 switch (mode_type) {
687 case MODE_REQ:
688 if (mp->cfg.mrru) {
689 if (REJECTED(lcp, TY_MRRU))
690 /* Ignore his previous reject so that we REQ next time */
691 lcp->his_reject &= ~(1 << opt->hdr.id);
693 if (mru > MAX_MRU) {
694 /* Push him down to MAX_MRU */
695 lcp->his_mrru = MAX_MRU;
696 nak.hdr.id = TY_MRRU;
697 nak.hdr.len = 4;
698 ua_htons(&lcp->his_mrru, nak.data);
699 fsm_nak(dec, &nak);
700 } else if (mru < MIN_MRU) {
701 /* Push him up to MIN_MRU */
702 lcp->his_mrru = MIN_MRU;
703 nak.hdr.id = TY_MRRU;
704 nak.hdr.len = 4;
705 ua_htons(&lcp->his_mrru, nak.data);
706 fsm_nak(dec, &nak);
707 } else {
708 lcp->his_mrru = mru;
709 fsm_ack(dec, opt);
711 break;
712 } else {
713 fsm_rej(dec, opt);
714 lcp->my_reject |= (1 << opt->hdr.id);
716 break;
717 case MODE_NAK:
718 if (mp->cfg.mrru) {
719 if (REJECTED(lcp, TY_MRRU))
720 /* Must have changed his mind ! */
721 lcp->his_reject &= ~(1 << opt->hdr.id);
723 if (mru > MAX_MRU)
724 lcp->want_mrru = MAX_MRU;
725 else if (mru < MIN_MRU)
726 lcp->want_mrru = MIN_MRU;
727 else
728 lcp->want_mrru = mru;
730 /* else we honour our config and don't send the suggested REQ */
731 break;
732 case MODE_REJ:
733 lcp->his_reject |= (1 << opt->hdr.id);
734 lcp->want_mrru = 0; /* Ah well, no multilink :-( */
735 break;
737 break;
739 case TY_MRU:
740 lcp->mru_req = 1;
741 ua_ntohs(opt->data, &mru);
742 log_Printf(LogLCP, "%s %d\n", request, mru);
744 switch (mode_type) {
745 case MODE_REQ:
746 maxmtu = p ? physical_DeviceMTU(p) : 0;
747 if (lcp->cfg.max_mtu && (!maxmtu || maxmtu > lcp->cfg.max_mtu))
748 maxmtu = lcp->cfg.max_mtu;
749 wantmtu = lcp->cfg.mtu;
750 if (maxmtu && wantmtu > maxmtu) {
751 log_Printf(LogWARN, "%s: Reducing configured MTU from %u to %u\n",
752 fp->link->name, wantmtu, maxmtu);
753 wantmtu = maxmtu;
756 if (maxmtu && mru > maxmtu) {
757 lcp->his_mru = maxmtu;
758 nak.hdr.id = TY_MRU;
759 nak.hdr.len = 4;
760 ua_htons(&lcp->his_mru, nak.data);
761 fsm_nak(dec, &nak);
762 } else if (wantmtu && mru < wantmtu) {
763 /* Push him up to MTU or MIN_MRU */
764 lcp->his_mru = wantmtu;
765 nak.hdr.id = TY_MRU;
766 nak.hdr.len = 4;
767 ua_htons(&lcp->his_mru, nak.data);
768 fsm_nak(dec, &nak);
769 } else {
770 lcp->his_mru = mru;
771 fsm_ack(dec, opt);
773 break;
774 case MODE_NAK:
775 maxmru = p ? physical_DeviceMTU(p) : 0;
776 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
777 maxmru = lcp->cfg.max_mru;
778 wantmru = lcp->cfg.mru > maxmru ? maxmru : lcp->cfg.mru;
780 if (wantmru && mru > wantmru)
781 lcp->want_mru = wantmru;
782 else if (mru > maxmru)
783 lcp->want_mru = maxmru;
784 else if (mru < MIN_MRU)
785 lcp->want_mru = MIN_MRU;
786 else
787 lcp->want_mru = mru;
788 break;
789 case MODE_REJ:
790 lcp->his_reject |= (1 << opt->hdr.id);
791 break;
793 break;
795 case TY_ACCMAP:
796 ua_ntohl(opt->data, &accmap);
797 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
799 switch (mode_type) {
800 case MODE_REQ:
801 lcp->his_accmap = accmap;
802 fsm_ack(dec, opt);
803 break;
804 case MODE_NAK:
805 lcp->want_accmap = accmap;
806 break;
807 case MODE_REJ:
808 lcp->his_reject |= (1 << opt->hdr.id);
809 break;
811 break;
813 case TY_AUTHPROTO:
814 ua_ntohs(opt->data, &proto);
815 chap_type = opt->hdr.len == 5 ? opt->data[2] : 0;
817 log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
818 Auth2Nam(proto, chap_type));
820 switch (mode_type) {
821 case MODE_REQ:
822 switch (proto) {
823 case PROTO_PAP:
824 if (opt->hdr.len == 4 && IsAccepted(lcp->cfg.pap)) {
825 lcp->his_auth = proto;
826 lcp->his_authtype = 0;
827 fsm_ack(dec, opt);
828 } else if (!lcp_auth_nak(lcp, dec)) {
829 lcp->my_reject |= (1 << opt->hdr.id);
830 fsm_rej(dec, opt);
832 break;
834 case PROTO_CHAP:
835 if ((chap_type == 0x05 && IsAccepted(lcp->cfg.chap05))
836 #ifndef NODES
837 || (chap_type == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
838 (IsAccepted(lcp->cfg.chap80lm))))
839 || (chap_type == 0x81 && IsAccepted(lcp->cfg.chap81))
840 #endif
842 lcp->his_auth = proto;
843 lcp->his_authtype = chap_type;
844 fsm_ack(dec, opt);
845 } else {
846 #ifdef NODES
847 if (chap_type == 0x80) {
848 log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
849 } else if (chap_type == 0x81) {
850 log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
851 } else
852 #endif
853 if (chap_type != 0x05)
854 log_Printf(LogWARN, "%s not supported\n",
855 Auth2Nam(PROTO_CHAP, chap_type));
857 if (!lcp_auth_nak(lcp, dec)) {
858 lcp->my_reject |= (1 << opt->hdr.id);
859 fsm_rej(dec, opt);
862 break;
864 default:
865 log_Printf(LogLCP, "%s 0x%04x - not recognised\n",
866 request, proto);
867 if (!lcp_auth_nak(lcp, dec)) {
868 lcp->my_reject |= (1 << opt->hdr.id);
869 fsm_rej(dec, opt);
871 break;
873 break;
875 case MODE_NAK:
876 switch (proto) {
877 case PROTO_PAP:
878 if (IsEnabled(lcp->cfg.pap)) {
879 lcp->want_auth = PROTO_PAP;
880 lcp->want_authtype = 0;
881 } else {
882 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
883 lcp->his_reject |= (1 << opt->hdr.id);
885 break;
886 case PROTO_CHAP:
887 if (chap_type == 0x05 && IsEnabled(lcp->cfg.chap05)) {
888 lcp->want_auth = PROTO_CHAP;
889 lcp->want_authtype = 0x05;
890 #ifndef NODES
891 } else if (chap_type == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
892 IsEnabled(lcp->cfg.chap80lm))) {
893 lcp->want_auth = PROTO_CHAP;
894 lcp->want_authtype = 0x80;
895 } else if (chap_type == 0x81 && IsEnabled(lcp->cfg.chap81)) {
896 lcp->want_auth = PROTO_CHAP;
897 lcp->want_authtype = 0x81;
898 #endif
899 } else {
900 #ifdef NODES
901 if (chap_type == 0x80) {
902 log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
903 " without DES)\n");
904 } else if (chap_type == 0x81) {
905 log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
906 " without DES)\n");
907 } else
908 #endif
909 log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
910 Auth2Nam(PROTO_CHAP, chap_type),
911 #ifndef NODES
912 (chap_type == 0x80 || chap_type == 0x81) ? "configured" :
913 #endif
914 "supported");
915 lcp->his_reject |= (1 << opt->hdr.id);
917 break;
918 default:
919 /* We've been NAK'd with something we don't understand :-( */
920 lcp->his_reject |= (1 << opt->hdr.id);
921 break;
923 break;
925 case MODE_REJ:
926 lcp->his_reject |= (1 << opt->hdr.id);
927 break;
929 break;
931 case TY_QUALPROTO:
932 req = (struct lqrreq *)opt;
933 log_Printf(LogLCP, "%s proto %x, interval %lums\n",
934 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
935 switch (mode_type) {
936 case MODE_REQ:
937 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr)) {
938 fsm_rej(dec, opt);
939 lcp->my_reject |= (1 << opt->hdr.id);
940 } else {
941 lcp->his_lqrperiod = ntohl(req->period);
942 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
943 lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
944 req->period = htonl(lcp->his_lqrperiod);
945 fsm_ack(dec, opt);
947 break;
948 case MODE_NAK:
949 lcp->want_lqrperiod = ntohl(req->period);
950 break;
951 case MODE_REJ:
952 lcp->his_reject |= (1 << opt->hdr.id);
953 break;
955 break;
957 case TY_MAGICNUM:
958 ua_ntohl(opt->data, &magic);
959 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
961 switch (mode_type) {
962 case MODE_REQ:
963 if (lcp->want_magic) {
964 /* Validate magic number */
965 if (magic == lcp->want_magic) {
966 sigset_t emptyset;
968 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
969 (u_long)magic, ++lcp->LcpFailedMagic);
970 lcp->want_magic = GenerateMagic();
971 fsm_nak(dec, opt);
972 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
973 sigemptyset(&emptyset);
974 sigsuspend(&emptyset);
975 } else {
976 lcp->his_magic = magic;
977 lcp->LcpFailedMagic = 0;
978 fsm_ack(dec, opt);
980 } else {
981 lcp->my_reject |= (1 << opt->hdr.id);
982 fsm_rej(dec, opt);
984 break;
985 case MODE_NAK:
986 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
987 lcp->want_magic = GenerateMagic();
988 break;
989 case MODE_REJ:
990 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
991 lcp->want_magic = 0;
992 lcp->his_reject |= (1 << opt->hdr.id);
993 break;
995 break;
997 case TY_PROTOCOMP:
998 log_Printf(LogLCP, "%s\n", request);
1000 switch (mode_type) {
1001 case MODE_REQ:
1002 if (IsAccepted(lcp->cfg.protocomp)) {
1003 lcp->his_protocomp = 1;
1004 fsm_ack(dec, opt);
1005 } else {
1006 #ifdef OLDMST
1007 /* MorningStar before v1.3 needs NAK */
1008 fsm_nak(dec, opt);
1009 #else
1010 fsm_rej(dec, opt);
1011 lcp->my_reject |= (1 << opt->hdr.id);
1012 #endif
1014 break;
1015 case MODE_NAK:
1016 case MODE_REJ:
1017 lcp->want_protocomp = 0;
1018 lcp->his_reject |= (1 << opt->hdr.id);
1019 break;
1021 break;
1023 case TY_ACFCOMP:
1024 log_Printf(LogLCP, "%s\n", request);
1025 switch (mode_type) {
1026 case MODE_REQ:
1027 if (IsAccepted(lcp->cfg.acfcomp)) {
1028 lcp->his_acfcomp = 1;
1029 fsm_ack(dec, opt);
1030 } else {
1031 #ifdef OLDMST
1032 /* MorningStar before v1.3 needs NAK */
1033 fsm_nak(dec, opt);
1034 #else
1035 fsm_rej(dec, opt);
1036 lcp->my_reject |= (1 << opt->hdr.id);
1037 #endif
1039 break;
1040 case MODE_NAK:
1041 case MODE_REJ:
1042 lcp->want_acfcomp = 0;
1043 lcp->his_reject |= (1 << opt->hdr.id);
1044 break;
1046 break;
1048 case TY_SDP:
1049 log_Printf(LogLCP, "%s\n", request);
1050 switch (mode_type) {
1051 case MODE_REQ:
1052 case MODE_NAK:
1053 case MODE_REJ:
1054 break;
1056 break;
1058 case TY_CALLBACK:
1059 if (opt->hdr.len == 2) {
1060 op = CALLBACK_NONE;
1061 sz = 0;
1062 } else {
1063 op = (int)opt->data[0];
1064 sz = opt->hdr.len - 3;
1066 switch (op) {
1067 case CALLBACK_AUTH:
1068 log_Printf(LogLCP, "%s Auth\n", request);
1069 break;
1070 case CALLBACK_DIALSTRING:
1071 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, (int)sz,
1072 opt->data + 1);
1073 break;
1074 case CALLBACK_LOCATION:
1075 log_Printf(LogLCP, "%s Location %.*s\n", request, (int)sz, opt->data + 1);
1076 break;
1077 case CALLBACK_E164:
1078 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, (int)sz, opt->data + 1);
1079 break;
1080 case CALLBACK_NAME:
1081 log_Printf(LogLCP, "%s Name %.*s\n", request, (int)sz, opt->data + 1);
1082 break;
1083 case CALLBACK_CBCP:
1084 log_Printf(LogLCP, "%s CBCP\n", request);
1085 break;
1086 default:
1087 log_Printf(LogLCP, "%s ???\n", request);
1088 break;
1091 switch (mode_type) {
1092 case MODE_REQ:
1093 callback_req = 1;
1094 if (p->type != PHYS_DIRECT) {
1095 fsm_rej(dec, opt);
1096 lcp->my_reject |= (1 << opt->hdr.id);
1098 nak.hdr.id = opt->hdr.id;
1099 nak.hdr.len = 3;
1100 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
1101 (op != CALLBACK_AUTH || p->link.lcp.want_auth) &&
1102 (op != CALLBACK_E164 ||
1103 E164ok(&p->dl->cfg.callback, opt->data + 1, sz))) {
1104 lcp->his_callback.opmask = CALLBACK_BIT(op);
1105 if (sz > sizeof lcp->his_callback.msg - 1) {
1106 sz = sizeof lcp->his_callback.msg - 1;
1107 log_Printf(LogWARN, "Truncating option arg to %zu octets\n", sz);
1109 memcpy(lcp->his_callback.msg, opt->data + 1, sz);
1110 lcp->his_callback.msg[sz] = '\0';
1111 fsm_ack(dec, opt);
1112 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1113 p->link.lcp.auth_ineed) {
1114 nak.data[0] = CALLBACK_AUTH;
1115 fsm_nak(dec, &nak);
1116 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1117 nak.data[0] = CALLBACK_CBCP;
1118 fsm_nak(dec, &nak);
1119 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1120 nak.data[0] = CALLBACK_E164;
1121 fsm_nak(dec, &nak);
1122 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1123 log_Printf(LogWARN, "Cannot insist on auth callback without"
1124 " PAP or CHAP enabled !\n");
1125 nak.data[0] = 2;
1126 fsm_nak(dec, &nak);
1127 } else {
1128 lcp->my_reject |= (1 << opt->hdr.id);
1129 fsm_rej(dec, opt);
1131 break;
1132 case MODE_NAK:
1133 /* We don't do what he NAKs with, we do things in our preferred order */
1134 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1135 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1136 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1137 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1138 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1139 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1140 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1141 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1142 lcp->want_callback.opmask = 0;
1143 } else if (!lcp->want_callback.opmask) {
1144 log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1145 fsm_Close(&lcp->fsm);
1147 break;
1148 case MODE_REJ:
1149 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1150 lcp->his_reject |= (1 << opt->hdr.id);
1151 lcp->want_callback.opmask = 0;
1152 } else {
1153 log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1154 fsm_Close(&lcp->fsm);
1156 break;
1158 break;
1160 case TY_SHORTSEQ:
1161 mp = &lcp->fsm.bundle->ncp.mp;
1162 log_Printf(LogLCP, "%s\n", request);
1164 switch (mode_type) {
1165 case MODE_REQ:
1166 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1167 lcp->his_shortseq = 1;
1168 fsm_ack(dec, opt);
1169 } else {
1170 fsm_rej(dec, opt);
1171 lcp->my_reject |= (1 << opt->hdr.id);
1173 break;
1174 case MODE_NAK:
1176 * He's trying to get us to ask for short sequence numbers.
1177 * We ignore the NAK and honour our configuration file instead.
1179 break;
1180 case MODE_REJ:
1181 lcp->his_reject |= (1 << opt->hdr.id);
1182 lcp->want_shortseq = 0; /* For when we hit MP */
1183 break;
1185 break;
1187 case TY_ENDDISC:
1188 mp = &lcp->fsm.bundle->ncp.mp;
1189 log_Printf(LogLCP, "%s %s\n", request,
1190 mp_Enddisc(opt->data[0], opt->data + 1, opt->hdr.len - 3));
1191 switch (mode_type) {
1192 case MODE_REQ:
1193 if (!p) {
1194 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1195 fsm_rej(dec, opt);
1196 lcp->my_reject |= (1 << opt->hdr.id);
1197 } else if (!IsAccepted(mp->cfg.negenddisc)) {
1198 lcp->my_reject |= (1 << opt->hdr.id);
1199 fsm_rej(dec, opt);
1200 } else if (opt->hdr.len < sizeof p->dl->peer.enddisc.address + 3 &&
1201 opt->data[0] <= MAX_ENDDISC_CLASS) {
1202 p->dl->peer.enddisc.class = opt->data[0];
1203 p->dl->peer.enddisc.len = opt->hdr.len - 3;
1204 memcpy(p->dl->peer.enddisc.address, opt->data + 1, opt->hdr.len - 3);
1205 p->dl->peer.enddisc.address[opt->hdr.len - 3] = '\0';
1206 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1207 fsm_ack(dec, opt);
1208 } else {
1209 if (opt->data[0] > MAX_ENDDISC_CLASS)
1210 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1211 opt->data[0]);
1212 else
1213 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1214 (long)(sizeof p->dl->peer.enddisc.address - 1));
1215 fsm_rej(dec, opt);
1216 lcp->my_reject |= (1 << opt->hdr.id);
1218 break;
1220 case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
1221 case MODE_REJ:
1222 lcp->his_reject |= (1 << opt->hdr.id);
1223 break;
1225 break;
1227 default:
1228 sz = (sizeof desc - 2) / 2;
1229 if (sz + 2 > opt->hdr.len)
1230 sz = opt->hdr.len - 2;
1231 pos = 0;
1232 desc[0] = sz ? ' ' : '\0';
1233 for (pos = 0; sz--; pos++)
1234 sprintf(desc+(pos<<1)+1, "%02x", opt->data[pos]);
1236 log_Printf(LogLCP, "%s%s\n", request, desc);
1238 if (mode_type == MODE_REQ) {
1239 fsm_rej(dec, opt);
1240 lcp->my_reject |= (1 << opt->hdr.id);
1242 break;
1246 if (mode_type != MODE_NOP) {
1247 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1248 p->dl->cfg.callback.opmask && !callback_req &&
1249 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1250 /* We *REQUIRE* that the peer requests callback */
1251 nak.hdr.id = TY_CALLBACK;
1252 nak.hdr.len = 3;
1253 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1254 p->link.lcp.want_auth)
1255 nak.data[0] = CALLBACK_AUTH;
1256 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1257 nak.data[0] = CALLBACK_CBCP;
1258 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1259 nak.data[0] = CALLBACK_E164;
1260 else {
1261 log_Printf(LogWARN, "Cannot insist on auth callback without"
1262 " PAP or CHAP enabled !\n");
1263 nak.hdr.len = 2; /* XXX: Silly ! */
1265 fsm_nak(dec, &nak);
1267 if (mode_type == MODE_REQ && !lcp->mru_req) {
1268 mru = DEF_MRU;
1269 phmtu = p ? physical_DeviceMTU(p) : 0;
1270 if (phmtu && mru > phmtu)
1271 mru = phmtu;
1272 if (mru > lcp->cfg.max_mtu)
1273 mru = lcp->cfg.max_mtu;
1274 if (mru < DEF_MRU) {
1275 /* Don't let the peer use the default MRU */
1276 lcp->his_mru = lcp->cfg.mtu && lcp->cfg.mtu < mru ? lcp->cfg.mtu : mru;
1277 nak.hdr.id = TY_MRU;
1278 nak.hdr.len = 4;
1279 ua_htons(&lcp->his_mru, nak.data);
1280 fsm_nak(dec, &nak);
1281 lcp->mru_req = 1; /* Don't keep NAK'ing this */
1284 fsm_opt_normalise(dec);
1288 extern struct mbuf *
1289 lcp_Input(struct bundle *bundle __unused, struct link *l, struct mbuf *bp)
1291 /* Got PROTO_LCP from link */
1292 m_settype(bp, MB_LCPIN);
1293 fsm_Input(&l->lcp.fsm, bp);
1294 return NULL;