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)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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>
55 #include "throughput.h"
57 #include "descriptor.h"
66 #include "slcompress.h"
83 /* for received LQRs */
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,
101 static struct fsm_callbacks lcp_Callbacks
= {
106 LcpInitRestartCounter
,
111 fsm_NullRecvResetReq
,
115 static const char * const lcp_TimerNames
[] =
116 {"LCP restart", "LCP openmode", "LCP stopped"};
119 protoname(unsigned proto
)
121 static const char * const cftypes
[] = {
122 /* Check out the latest ``Assigned numbers'' rfc (1700) */
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
> sizeof cftypes
/ sizeof *cftypes
|| cftypes
[proto
] == NULL
)
150 return HexStr(proto
, NULL
, 0);
152 return cftypes
[proto
];
156 lcp_ReportStatus(struct cmdargs
const *arg
)
161 l
= command_ChooseLink(arg
);
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
);
184 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = %d (max %d), ",
185 lcp
->cfg
.mru
, lcp
->cfg
.max_mru
);
187 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = any (max %d), ",
190 prompt_Printf(arg
->prompt
, "MTU = %d (max %d), ",
191 lcp
->cfg
.mtu
, lcp
->cfg
.max_mtu
);
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, ",
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
));
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
));
219 prompt_Printf(arg
->prompt
, " LQR = %s\n",
220 command_ShowNegval(lcp
->cfg
.lqr
));
221 prompt_Printf(arg
->prompt
, " LCP ECHO = %s\n",
222 lcp
->cfg
.echo
? "enabled" : "disabled");
223 prompt_Printf(arg
->prompt
, " PAP = %s\n",
224 command_ShowNegval(lcp
->cfg
.pap
));
225 prompt_Printf(arg
->prompt
, " PROTOCOMP = %s\n",
226 command_ShowNegval(lcp
->cfg
.protocomp
));
234 /* Generate random number which will be used as magic number */
240 lcp_SetupCallbacks(struct lcp
*lcp
)
242 lcp
->fsm
.fn
= &lcp_Callbacks
;
243 lcp
->fsm
.FsmTimer
.name
= lcp_TimerNames
[0];
244 lcp
->fsm
.OpenTimer
.name
= lcp_TimerNames
[1];
245 lcp
->fsm
.StoppedTimer
.name
= lcp_TimerNames
[2];
249 lcp_Init(struct lcp
*lcp
, struct bundle
*bundle
, struct link
*l
,
250 const struct fsm_parent
*parent
)
252 /* Initialise ourselves */
253 int mincode
= parent
? 1 : LCP_MINMPCODE
;
255 fsm_Init(&lcp
->fsm
, "LCP", PROTO_LCP
, mincode
, LCP_MAXCODE
, LogLCP
,
256 bundle
, l
, parent
, &lcp_Callbacks
, lcp_TimerNames
);
259 lcp
->cfg
.max_mru
= MAX_MRU
;
261 lcp
->cfg
.max_mtu
= MAX_MTU
;
263 lcp
->cfg
.openmode
= 1;
264 lcp
->cfg
.lqrperiod
= DEF_LQRPERIOD
;
265 lcp
->cfg
.fsm
.timeout
= DEF_FSMRETRY
;
266 lcp
->cfg
.fsm
.maxreq
= DEF_FSMTRIES
;
267 lcp
->cfg
.fsm
.maxtrm
= DEF_FSMTRIES
;
269 lcp
->cfg
.acfcomp
= NEG_ENABLED
|NEG_ACCEPTED
;
270 lcp
->cfg
.chap05
= NEG_ACCEPTED
;
272 lcp
->cfg
.chap80nt
= NEG_ACCEPTED
;
273 lcp
->cfg
.chap80lm
= 0;
274 lcp
->cfg
.chap81
= NEG_ACCEPTED
;
276 lcp
->cfg
.lqr
= NEG_ACCEPTED
;
278 lcp
->cfg
.pap
= NEG_ACCEPTED
;
279 lcp
->cfg
.protocomp
= NEG_ENABLED
|NEG_ACCEPTED
;
280 *lcp
->cfg
.ident
= '\0';
282 lcp_Setup(lcp
, lcp
->cfg
.openmode
);
286 lcp_Setup(struct lcp
*lcp
, int openmode
)
288 struct physical
*p
= link2physical(lcp
->fsm
.link
);
290 lcp
->fsm
.open_mode
= openmode
;
292 lcp
->his_mru
= DEF_MRU
;
295 lcp
->his_lqrperiod
= 0;
296 lcp
->his_acfcomp
= 0;
298 lcp
->his_authtype
= 0;
299 lcp
->his_callback
.opmask
= 0;
300 lcp
->his_shortseq
= 0;
303 if ((lcp
->want_mru
= lcp
->cfg
.mru
) == 0)
304 lcp
->want_mru
= DEF_MRU
;
305 lcp
->want_mrru
= lcp
->fsm
.bundle
->ncp
.mp
.cfg
.mrru
;
306 lcp
->want_shortseq
= IsEnabled(lcp
->fsm
.bundle
->ncp
.mp
.cfg
.shortseq
) ? 1 : 0;
307 lcp
->want_acfcomp
= IsEnabled(lcp
->cfg
.acfcomp
) ? 1 : 0;
309 if (lcp
->fsm
.parent
) {
310 lcp
->his_accmap
= 0xffffffff;
311 lcp
->want_accmap
= lcp
->cfg
.accmap
;
312 lcp
->his_protocomp
= 0;
313 lcp
->want_protocomp
= IsEnabled(lcp
->cfg
.protocomp
) ? 1 : 0;
314 lcp
->want_magic
= GenerateMagic();
316 if (IsEnabled(lcp
->cfg
.chap05
)) {
317 lcp
->want_auth
= PROTO_CHAP
;
318 lcp
->want_authtype
= 0x05;
320 } else if (IsEnabled(lcp
->cfg
.chap80nt
) ||
321 IsEnabled(lcp
->cfg
.chap80lm
)) {
322 lcp
->want_auth
= PROTO_CHAP
;
323 lcp
->want_authtype
= 0x80;
324 } else if (IsEnabled(lcp
->cfg
.chap81
)) {
325 lcp
->want_auth
= PROTO_CHAP
;
326 lcp
->want_authtype
= 0x81;
328 } else if (IsEnabled(lcp
->cfg
.pap
)) {
329 lcp
->want_auth
= PROTO_PAP
;
330 lcp
->want_authtype
= 0;
333 lcp
->want_authtype
= 0;
336 if (p
->type
!= PHYS_DIRECT
)
337 memcpy(&lcp
->want_callback
, &p
->dl
->cfg
.callback
,
338 sizeof(struct callback
));
340 lcp
->want_callback
.opmask
= 0;
341 lcp
->want_lqrperiod
= IsEnabled(lcp
->cfg
.lqr
) ?
342 lcp
->cfg
.lqrperiod
* 100 : 0;
344 lcp
->his_accmap
= lcp
->want_accmap
= 0;
345 lcp
->his_protocomp
= lcp
->want_protocomp
= 1;
348 lcp
->want_authtype
= 0;
349 lcp
->want_callback
.opmask
= 0;
350 lcp
->want_lqrperiod
= 0;
353 lcp
->his_reject
= lcp
->my_reject
= 0;
354 lcp
->auth_iwait
= lcp
->auth_ineed
= 0;
355 lcp
->LcpFailedMagic
= 0;
359 LcpInitRestartCounter(struct fsm
*fp
, int what
)
361 /* Set fsm timer load */
362 struct lcp
*lcp
= fsm2lcp(fp
);
364 fp
->FsmTimer
.load
= lcp
->cfg
.fsm
.timeout
* SECTICKS
;
367 fp
->restart
= lcp
->cfg
.fsm
.maxreq
;
370 fp
->restart
= lcp
->cfg
.fsm
.maxtrm
;
379 LcpSendConfigReq(struct fsm
*fp
)
381 /* Send config REQ please */
382 struct physical
*p
= link2physical(fp
->link
);
383 struct lcp
*lcp
= fsm2lcp(fp
);
391 log_Printf(LogERROR
, "%s: LcpSendConfigReq: Not a physical link !\n",
396 o
= (struct fsm_opt
*)buff
;
397 if (!physical_IsSync(p
)) {
398 if (lcp
->want_acfcomp
&& !REJECTED(lcp
, TY_ACFCOMP
))
399 INC_FSM_OPT(TY_ACFCOMP
, 2, o
);
401 if (lcp
->want_protocomp
&& !REJECTED(lcp
, TY_PROTOCOMP
))
402 INC_FSM_OPT(TY_PROTOCOMP
, 2, o
);
404 if (!REJECTED(lcp
, TY_ACCMAP
)) {
405 ua_htonl(&lcp
->want_accmap
, o
->data
);
406 INC_FSM_OPT(TY_ACCMAP
, 6, o
);
410 maxmru
= p
? physical_DeviceMTU(p
) : 0;
411 if (lcp
->cfg
.max_mru
&& (!maxmru
|| maxmru
> lcp
->cfg
.max_mru
))
412 maxmru
= lcp
->cfg
.max_mru
;
413 if (maxmru
&& lcp
->want_mru
> maxmru
) {
414 log_Printf(LogWARN
, "%s: Reducing configured MRU from %u to %u\n",
415 fp
->link
->name
, lcp
->want_mru
, maxmru
);
416 lcp
->want_mru
= maxmru
;
418 if (!REJECTED(lcp
, TY_MRU
)) {
419 ua_htons(&lcp
->want_mru
, o
->data
);
420 INC_FSM_OPT(TY_MRU
, 4, o
);
423 if (lcp
->want_magic
&& !REJECTED(lcp
, TY_MAGICNUM
)) {
424 ua_htonl(&lcp
->want_magic
, o
->data
);
425 INC_FSM_OPT(TY_MAGICNUM
, 6, o
);
428 if (lcp
->want_lqrperiod
&& !REJECTED(lcp
, TY_QUALPROTO
)) {
430 ua_htons(&proto
, o
->data
);
431 ua_htonl(&lcp
->want_lqrperiod
, o
->data
+ 2);
432 INC_FSM_OPT(TY_QUALPROTO
, 8, o
);
435 switch (lcp
->want_auth
) {
438 ua_htons(&proto
, o
->data
);
439 INC_FSM_OPT(TY_AUTHPROTO
, 4, o
);
444 ua_htons(&proto
, o
->data
);
445 o
->data
[2] = lcp
->want_authtype
;
446 INC_FSM_OPT(TY_AUTHPROTO
, 5, o
);
450 if (!REJECTED(lcp
, TY_CALLBACK
)) {
451 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) {
452 *o
->data
= CALLBACK_AUTH
;
453 INC_FSM_OPT(TY_CALLBACK
, 3, o
);
454 } else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
)) {
455 *o
->data
= CALLBACK_CBCP
;
456 INC_FSM_OPT(TY_CALLBACK
, 3, o
);
457 } else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
)) {
458 size_t sz
= strlen(lcp
->want_callback
.msg
);
460 if (sz
> sizeof o
->data
- 1) {
461 sz
= sizeof o
->data
- 1;
462 log_Printf(LogWARN
, "Truncating E164 data to %zu octets (oops!)\n",
465 *o
->data
= CALLBACK_E164
;
466 memcpy(o
->data
+ 1, lcp
->want_callback
.msg
, sz
);
467 INC_FSM_OPT(TY_CALLBACK
, sz
+ 3, o
);
471 if (lcp
->want_mrru
&& !REJECTED(lcp
, TY_MRRU
)) {
472 ua_htons(&lcp
->want_mrru
, o
->data
);
473 INC_FSM_OPT(TY_MRRU
, 4, o
);
475 if (lcp
->want_shortseq
&& !REJECTED(lcp
, TY_SHORTSEQ
))
476 INC_FSM_OPT(TY_SHORTSEQ
, 2, o
);
479 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
480 if (mp
->cfg
.enddisc
.class != 0 && IsEnabled(mp
->cfg
.negenddisc
) &&
481 !REJECTED(lcp
, TY_ENDDISC
)) {
482 *o
->data
= mp
->cfg
.enddisc
.class;
483 memcpy(o
->data
+1, mp
->cfg
.enddisc
.address
, mp
->cfg
.enddisc
.len
);
484 INC_FSM_OPT(TY_ENDDISC
, mp
->cfg
.enddisc
.len
+ 3, o
);
487 fsm_Output(fp
, CODE_CONFIGREQ
, fp
->reqid
, buff
, (u_char
*)o
- buff
,
492 lcp_SendProtoRej(struct lcp
*lcp
, u_char
*option
, int count
)
494 /* Don't understand `option' */
495 fsm_Output(&lcp
->fsm
, CODE_PROTOREJ
, lcp
->fsm
.reqid
, option
, count
,
500 lcp_SendIdentification(struct lcp
*lcp
)
502 static u_char id
; /* Use a private id */
503 u_char msg
[DEF_MRU
- 3];
507 if (*lcp
->cfg
.ident
== '\0')
510 argv
[0] = lcp
->cfg
.ident
;
513 command_Expand(exp
, 1, argv
, lcp
->fsm
.bundle
, 1, getpid());
515 ua_htonl(&lcp
->want_magic
, msg
);
516 strncpy(msg
+ 4, exp
[0], sizeof msg
- 5);
517 msg
[sizeof msg
- 1] = '\0';
519 fsm_Output(&lcp
->fsm
, CODE_IDENT
, id
++, msg
, 4 + strlen(msg
+ 4), MB_LCPOUT
);
520 log_Printf(LogLCP
, " MAGICNUM %08x\n", lcp
->want_magic
);
521 log_Printf(LogLCP
, " TEXT %s\n", msg
+ 4);
523 command_Free(1, exp
);
528 lcp_RecvIdentification(struct lcp
*lcp
, char *data
)
530 log_Printf(LogLCP
, " MAGICNUM %08x\n", lcp
->his_magic
);
531 log_Printf(LogLCP
, " TEXT %s\n", data
);
535 LcpSentTerminateReq(struct fsm
*fp __unused
)
537 /* Term REQ just sent by FSM */
541 LcpSendTerminateAck(struct fsm
*fp
, u_char id
)
543 /* Send Term ACK please */
544 struct physical
*p
= link2physical(fp
->link
);
546 if (p
&& p
->dl
->state
== DATALINK_CBCP
)
547 cbcp_ReceiveTerminateReq(p
);
549 fsm_Output(fp
, CODE_TERMACK
, id
, NULL
, 0, MB_LCPOUT
);
553 LcpLayerStart(struct fsm
*fp
)
555 /* We're about to start up ! */
556 struct lcp
*lcp
= fsm2lcp(fp
);
558 log_Printf(LogLCP
, "%s: LayerStart\n", fp
->link
->name
);
559 lcp
->LcpFailedMagic
= 0;
560 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= lcp
->cfg
.fsm
.maxreq
* 3;
565 LcpLayerFinish(struct fsm
*fp
)
568 log_Printf(LogLCP
, "%s: LayerFinish\n", fp
->link
->name
);
572 LcpLayerUp(struct fsm
*fp
)
575 struct physical
*p
= link2physical(fp
->link
);
576 struct lcp
*lcp
= fsm2lcp(fp
);
578 log_Printf(LogLCP
, "%s: LayerUp\n", fp
->link
->name
);
579 physical_SetAsyncParams(p
, lcp
->want_accmap
, lcp
->his_accmap
);
581 hdlc_StartTimer(&p
->hdlc
);
582 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= lcp
->cfg
.fsm
.maxreq
* 3;
584 lcp_SendIdentification(lcp
);
590 LcpLayerDown(struct fsm
*fp
)
592 /* About to come down */
593 struct physical
*p
= link2physical(fp
->link
);
595 log_Printf(LogLCP
, "%s: LayerDown\n", fp
->link
->name
);
596 hdlc_StopTimer(&p
->hdlc
);
598 lcp_Setup(fsm2lcp(fp
), 0);
602 E164ok(struct callback
*cb
, char *req
, int sz
)
604 char list
[sizeof cb
->msg
], *next
;
607 if (!strcmp(cb
->msg
, "*"))
610 strncpy(list
, cb
->msg
, sizeof list
- 1);
611 list
[sizeof list
- 1] = '\0';
612 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ",")) {
614 if (sz
== len
&& !memcmp(list
, req
, sz
))
621 lcp_auth_nak(struct lcp
*lcp
, struct fsm_decode
*dec
)
625 nak
.hdr
.id
= TY_AUTHPROTO
;
627 if (IsAccepted(lcp
->cfg
.pap
)) {
629 nak
.data
[0] = (unsigned char)(PROTO_PAP
>> 8);
630 nak
.data
[1] = (unsigned char)PROTO_PAP
;
636 nak
.data
[0] = (unsigned char)(PROTO_CHAP
>> 8);
637 nak
.data
[1] = (unsigned char)PROTO_CHAP
;
639 if (IsAccepted(lcp
->cfg
.chap05
)) {
643 } else if (IsAccepted(lcp
->cfg
.chap80nt
) ||
644 IsAccepted(lcp
->cfg
.chap80lm
)) {
647 } else if (IsAccepted(lcp
->cfg
.chap81
)) {
659 LcpDecodeConfig(struct fsm
*fp
, u_char
*cp
, u_char
*end
, int mode_type
,
660 struct fsm_decode
*dec
)
662 /* Deal with incoming PROTO_LCP */
663 struct lcp
*lcp
= fsm2lcp(fp
);
664 int pos
, op
, callback_req
, chap_type
;
666 u_int32_t magic
, accmap
;
667 u_short mru
, phmtu
, maxmtu
, maxmru
, wantmtu
, wantmru
, proto
;
669 char request
[20], desc
[22];
671 struct physical
*p
= link2physical(fp
->link
);
672 struct fsm_opt
*opt
, nak
;
675 op
= callback_req
= 0;
677 while (end
- cp
>= (int)sizeof(opt
->hdr
)) {
678 if ((opt
= fsm_readopt(&cp
)) == NULL
)
681 snprintf(request
, sizeof request
, " %s[%d]", protoname(opt
->hdr
.id
),
684 switch (opt
->hdr
.id
) {
686 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
687 ua_ntohs(opt
->data
, &mru
);
688 log_Printf(LogLCP
, "%s %u\n", request
, mru
);
693 if (REJECTED(lcp
, TY_MRRU
))
694 /* Ignore his previous reject so that we REQ next time */
695 lcp
->his_reject
&= ~(1 << opt
->hdr
.id
);
698 /* Push him down to MAX_MRU */
699 lcp
->his_mrru
= MAX_MRU
;
700 nak
.hdr
.id
= TY_MRRU
;
702 ua_htons(&lcp
->his_mrru
, nak
.data
);
704 } else if (mru
< MIN_MRU
) {
705 /* Push him up to MIN_MRU */
706 lcp
->his_mrru
= MIN_MRU
;
707 nak
.hdr
.id
= TY_MRRU
;
709 ua_htons(&lcp
->his_mrru
, nak
.data
);
718 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
723 if (REJECTED(lcp
, TY_MRRU
))
724 /* Must have changed his mind ! */
725 lcp
->his_reject
&= ~(1 << opt
->hdr
.id
);
728 lcp
->want_mrru
= MAX_MRU
;
729 else if (mru
< MIN_MRU
)
730 lcp
->want_mrru
= MIN_MRU
;
732 lcp
->want_mrru
= mru
;
734 /* else we honour our config and don't send the suggested REQ */
737 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
738 lcp
->want_mrru
= 0; /* Ah well, no multilink :-( */
745 ua_ntohs(opt
->data
, &mru
);
746 log_Printf(LogLCP
, "%s %d\n", request
, mru
);
750 maxmtu
= p
? physical_DeviceMTU(p
) : 0;
751 if (lcp
->cfg
.max_mtu
&& (!maxmtu
|| maxmtu
> lcp
->cfg
.max_mtu
))
752 maxmtu
= lcp
->cfg
.max_mtu
;
753 wantmtu
= lcp
->cfg
.mtu
;
754 if (maxmtu
&& wantmtu
> maxmtu
) {
755 log_Printf(LogWARN
, "%s: Reducing configured MTU from %u to %u\n",
756 fp
->link
->name
, wantmtu
, maxmtu
);
760 if (maxmtu
&& mru
> maxmtu
) {
761 lcp
->his_mru
= maxmtu
;
764 ua_htons(&lcp
->his_mru
, nak
.data
);
766 } else if (wantmtu
&& mru
< wantmtu
) {
767 /* Push him up to MTU or MIN_MRU */
768 lcp
->his_mru
= wantmtu
;
771 ua_htons(&lcp
->his_mru
, nak
.data
);
779 maxmru
= p
? physical_DeviceMTU(p
) : 0;
780 if (lcp
->cfg
.max_mru
&& (!maxmru
|| maxmru
> lcp
->cfg
.max_mru
))
781 maxmru
= lcp
->cfg
.max_mru
;
782 wantmru
= lcp
->cfg
.mru
> maxmru
? maxmru
: lcp
->cfg
.mru
;
784 if (wantmru
&& mru
> wantmru
)
785 lcp
->want_mru
= wantmru
;
786 else if (mru
> maxmru
)
787 lcp
->want_mru
= maxmru
;
788 else if (mru
< MIN_MRU
)
789 lcp
->want_mru
= MIN_MRU
;
794 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
795 /* Set the MTU to what we want anyway - the peer won't care! */
796 if (lcp
->his_mru
> lcp
->want_mru
)
797 lcp
->his_mru
= lcp
->want_mru
;
803 ua_ntohl(opt
->data
, &accmap
);
804 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)accmap
);
808 lcp
->his_accmap
= accmap
;
812 lcp
->want_accmap
= accmap
;
815 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
821 ua_ntohs(opt
->data
, &proto
);
822 chap_type
= opt
->hdr
.len
== 5 ? opt
->data
[2] : 0;
824 log_Printf(LogLCP
, "%s 0x%04x (%s)\n", request
, proto
,
825 Auth2Nam(proto
, chap_type
));
831 if (opt
->hdr
.len
== 4 && IsAccepted(lcp
->cfg
.pap
)) {
832 lcp
->his_auth
= proto
;
833 lcp
->his_authtype
= 0;
835 } else if (!lcp_auth_nak(lcp
, dec
)) {
836 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
842 if ((chap_type
== 0x05 && IsAccepted(lcp
->cfg
.chap05
))
844 || (chap_type
== 0x80 && (IsAccepted(lcp
->cfg
.chap80nt
) ||
845 (IsAccepted(lcp
->cfg
.chap80lm
))))
846 || (chap_type
== 0x81 && IsAccepted(lcp
->cfg
.chap81
))
849 lcp
->his_auth
= proto
;
850 lcp
->his_authtype
= chap_type
;
854 if (chap_type
== 0x80) {
855 log_Printf(LogWARN
, "CHAP 0x80 not available without DES\n");
856 } else if (chap_type
== 0x81) {
857 log_Printf(LogWARN
, "CHAP 0x81 not available without DES\n");
860 if (chap_type
!= 0x05)
861 log_Printf(LogWARN
, "%s not supported\n",
862 Auth2Nam(PROTO_CHAP
, chap_type
));
864 if (!lcp_auth_nak(lcp
, dec
)) {
865 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
872 log_Printf(LogLCP
, "%s 0x%04x - not recognised\n",
874 if (!lcp_auth_nak(lcp
, dec
)) {
875 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
885 if (IsEnabled(lcp
->cfg
.pap
)) {
886 lcp
->want_auth
= PROTO_PAP
;
887 lcp
->want_authtype
= 0;
889 log_Printf(LogLCP
, "Peer will only send PAP (not enabled)\n");
890 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
894 if (chap_type
== 0x05 && IsEnabled(lcp
->cfg
.chap05
)) {
895 lcp
->want_auth
= PROTO_CHAP
;
896 lcp
->want_authtype
= 0x05;
898 } else if (chap_type
== 0x80 && (IsEnabled(lcp
->cfg
.chap80nt
) ||
899 IsEnabled(lcp
->cfg
.chap80lm
))) {
900 lcp
->want_auth
= PROTO_CHAP
;
901 lcp
->want_authtype
= 0x80;
902 } else if (chap_type
== 0x81 && IsEnabled(lcp
->cfg
.chap81
)) {
903 lcp
->want_auth
= PROTO_CHAP
;
904 lcp
->want_authtype
= 0x81;
908 if (chap_type
== 0x80) {
909 log_Printf(LogLCP
, "Peer will only send MSCHAP (not available"
911 } else if (chap_type
== 0x81) {
912 log_Printf(LogLCP
, "Peer will only send MSCHAPV2 (not available"
916 log_Printf(LogLCP
, "Peer will only send %s (not %s)\n",
917 Auth2Nam(PROTO_CHAP
, chap_type
),
919 (chap_type
== 0x80 || chap_type
== 0x81) ? "configured" :
922 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
926 /* We've been NAK'd with something we don't understand :-( */
927 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
933 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
939 memcpy(&req
, opt
, sizeof req
);
940 log_Printf(LogLCP
, "%s proto %x, interval %lums\n",
941 request
, ntohs(req
.proto
), (u_long
)ntohl(req
.period
) * 10);
944 if (ntohs(req
.proto
) != PROTO_LQR
|| !IsAccepted(lcp
->cfg
.lqr
)) {
946 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
948 lcp
->his_lqrperiod
= ntohl(req
.period
);
949 if (lcp
->his_lqrperiod
< MIN_LQRPERIOD
* 100)
950 lcp
->his_lqrperiod
= MIN_LQRPERIOD
* 100;
951 req
.period
= htonl(lcp
->his_lqrperiod
);
956 lcp
->want_lqrperiod
= ntohl(req
.period
);
959 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
965 ua_ntohl(opt
->data
, &magic
);
966 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)magic
);
970 if (lcp
->want_magic
) {
971 /* Validate magic number */
972 if (magic
== lcp
->want_magic
) {
975 log_Printf(LogLCP
, "Magic is same (%08lx) - %d times\n",
976 (u_long
)magic
, ++lcp
->LcpFailedMagic
);
977 lcp
->want_magic
= GenerateMagic();
979 ualarm(TICKUNIT
* (4 + 4 * lcp
->LcpFailedMagic
), 0);
980 sigemptyset(&emptyset
);
981 sigsuspend(&emptyset
);
983 lcp
->his_magic
= magic
;
984 lcp
->LcpFailedMagic
= 0;
988 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
993 log_Printf(LogLCP
, " Magic 0x%08lx is NAKed!\n", (u_long
)magic
);
994 lcp
->want_magic
= GenerateMagic();
997 log_Printf(LogLCP
, " Magic 0x%08x is REJected!\n", magic
);
999 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1005 log_Printf(LogLCP
, "%s\n", request
);
1007 switch (mode_type
) {
1009 if (IsAccepted(lcp
->cfg
.protocomp
)) {
1010 lcp
->his_protocomp
= 1;
1014 /* MorningStar before v1.3 needs NAK */
1018 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1024 lcp
->want_protocomp
= 0;
1025 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1031 log_Printf(LogLCP
, "%s\n", request
);
1032 switch (mode_type
) {
1034 if (IsAccepted(lcp
->cfg
.acfcomp
)) {
1035 lcp
->his_acfcomp
= 1;
1039 /* MorningStar before v1.3 needs NAK */
1043 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1049 lcp
->want_acfcomp
= 0;
1050 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1056 log_Printf(LogLCP
, "%s\n", request
);
1057 switch (mode_type
) {
1066 if (opt
->hdr
.len
== 2) {
1070 op
= (int)opt
->data
[0];
1071 sz
= opt
->hdr
.len
- 3;
1075 log_Printf(LogLCP
, "%s Auth\n", request
);
1077 case CALLBACK_DIALSTRING
:
1078 log_Printf(LogLCP
, "%s Dialstring %.*s\n", request
, (int)sz
,
1081 case CALLBACK_LOCATION
:
1082 log_Printf(LogLCP
, "%s Location %.*s\n", request
, (int)sz
,
1086 log_Printf(LogLCP
, "%s E.164 (%.*s)\n", request
, (int)sz
,
1090 log_Printf(LogLCP
, "%s Name %.*s\n", request
, (int)sz
,
1094 log_Printf(LogLCP
, "%s CBCP\n", request
);
1097 log_Printf(LogLCP
, "%s ???\n", request
);
1101 switch (mode_type
) {
1104 if (p
->type
!= PHYS_DIRECT
) {
1106 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1108 nak
.hdr
.id
= opt
->hdr
.id
;
1110 if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(op
)) &&
1111 (op
!= CALLBACK_AUTH
|| p
->link
.lcp
.want_auth
) &&
1112 (op
!= CALLBACK_E164
||
1113 E164ok(&p
->dl
->cfg
.callback
, opt
->data
+ 1, sz
))) {
1114 lcp
->his_callback
.opmask
= CALLBACK_BIT(op
);
1115 if (sz
> sizeof lcp
->his_callback
.msg
- 1) {
1116 sz
= sizeof lcp
->his_callback
.msg
- 1;
1117 log_Printf(LogWARN
, "Truncating option arg to %zu octets\n", sz
);
1119 memcpy(lcp
->his_callback
.msg
, opt
->data
+ 1, sz
);
1120 lcp
->his_callback
.msg
[sz
] = '\0';
1122 } else if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) &&
1123 p
->link
.lcp
.auth_ineed
) {
1124 nak
.data
[0] = CALLBACK_AUTH
;
1126 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
)) {
1127 nak
.data
[0] = CALLBACK_CBCP
;
1129 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
)) {
1130 nak
.data
[0] = CALLBACK_E164
;
1132 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) {
1133 log_Printf(LogWARN
, "Cannot insist on auth callback without"
1134 " PAP or CHAP enabled !\n");
1138 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1143 /* We don't do what he NAKs with, we do things in our preferred order */
1144 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
))
1145 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_AUTH
);
1146 else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
))
1147 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_CBCP
);
1148 else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
))
1149 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_E164
);
1150 if (lcp
->want_callback
.opmask
== CALLBACK_BIT(CALLBACK_NONE
)) {
1151 log_Printf(LogPHASE
, "Peer NAKd all callbacks, trying none\n");
1152 lcp
->want_callback
.opmask
= 0;
1153 } else if (!lcp
->want_callback
.opmask
) {
1154 log_Printf(LogPHASE
, "Peer NAKd last configured callback\n");
1155 fsm_Close(&lcp
->fsm
);
1159 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
)) {
1160 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1161 lcp
->want_callback
.opmask
= 0;
1163 log_Printf(LogPHASE
, "Peer rejected *required* callback\n");
1164 fsm_Close(&lcp
->fsm
);
1171 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
1172 log_Printf(LogLCP
, "%s\n", request
);
1174 switch (mode_type
) {
1176 if (lcp
->want_mrru
&& IsAccepted(mp
->cfg
.shortseq
)) {
1177 lcp
->his_shortseq
= 1;
1181 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1186 * He's trying to get us to ask for short sequence numbers.
1187 * We ignore the NAK and honour our configuration file instead.
1191 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1192 lcp
->want_shortseq
= 0; /* For when we hit MP */
1198 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
1199 log_Printf(LogLCP
, "%s %s\n", request
,
1200 mp_Enddisc(opt
->data
[0], opt
->data
+ 1, opt
->hdr
.len
- 3));
1201 switch (mode_type
) {
1204 log_Printf(LogLCP
, " ENDDISC rejected - not a physical link\n");
1206 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1207 } else if (!IsAccepted(mp
->cfg
.negenddisc
)) {
1208 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1210 } else if (opt
->hdr
.len
< sizeof p
->dl
->peer
.enddisc
.address
+ 3 &&
1211 opt
->data
[0] <= MAX_ENDDISC_CLASS
) {
1212 p
->dl
->peer
.enddisc
.class = opt
->data
[0];
1213 p
->dl
->peer
.enddisc
.len
= opt
->hdr
.len
- 3;
1214 memcpy(p
->dl
->peer
.enddisc
.address
, opt
->data
+ 1, opt
->hdr
.len
- 3);
1215 p
->dl
->peer
.enddisc
.address
[opt
->hdr
.len
- 3] = '\0';
1216 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1219 if (opt
->data
[0] > MAX_ENDDISC_CLASS
)
1220 log_Printf(LogLCP
, " ENDDISC rejected - unrecognised class %d\n",
1223 log_Printf(LogLCP
, " ENDDISC rejected - local max length is %ld\n",
1224 (long)(sizeof p
->dl
->peer
.enddisc
.address
- 1));
1226 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1230 case MODE_NAK
: /* Treat this as a REJ, we don't vary our disc (yet) */
1232 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1238 sz
= (sizeof desc
- 2) / 2;
1239 if (sz
+ 2 > opt
->hdr
.len
)
1240 sz
= opt
->hdr
.len
- 2;
1242 desc
[0] = sz
? ' ' : '\0';
1243 for (pos
= 0; sz
--; pos
++)
1244 sprintf(desc
+(pos
<<1)+1, "%02x", opt
->data
[pos
]);
1246 log_Printf(LogLCP
, "%s%s\n", request
, desc
);
1248 if (mode_type
== MODE_REQ
) {
1250 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1256 if (mode_type
!= MODE_NOP
) {
1257 if (mode_type
== MODE_REQ
&& p
&& p
->type
== PHYS_DIRECT
&&
1258 p
->dl
->cfg
.callback
.opmask
&& !callback_req
&&
1259 !(p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
))) {
1260 /* We *REQUIRE* that the peer requests callback */
1261 nak
.hdr
.id
= TY_CALLBACK
;
1263 if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) &&
1264 p
->link
.lcp
.want_auth
)
1265 nak
.data
[0] = CALLBACK_AUTH
;
1266 else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
))
1267 nak
.data
[0] = CALLBACK_CBCP
;
1268 else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
))
1269 nak
.data
[0] = CALLBACK_E164
;
1271 log_Printf(LogWARN
, "Cannot insist on auth callback without"
1272 " PAP or CHAP enabled !\n");
1273 nak
.hdr
.len
= 2; /* XXX: Silly ! */
1277 if (mode_type
== MODE_REQ
&& !lcp
->mru_req
) {
1279 phmtu
= p
? physical_DeviceMTU(p
) : 0;
1280 if (phmtu
&& mru
> phmtu
)
1282 if (mru
> lcp
->cfg
.max_mtu
)
1283 mru
= lcp
->cfg
.max_mtu
;
1284 if (mru
< DEF_MRU
) {
1285 /* Don't let the peer use the default MRU */
1286 lcp
->his_mru
= lcp
->cfg
.mtu
&& lcp
->cfg
.mtu
< mru
? lcp
->cfg
.mtu
: mru
;
1287 nak
.hdr
.id
= TY_MRU
;
1289 ua_htons(&lcp
->his_mru
, nak
.data
);
1291 lcp
->mru_req
= 1; /* Don't keep NAK'ing this */
1294 fsm_opt_normalise(dec
);
1298 extern struct mbuf
*
1299 lcp_Input(struct bundle
*bundle __unused
, struct link
*l
, struct mbuf
*bp
)
1301 /* Got PROTO_LCP from link */
1302 m_settype(bp
, MB_LCPIN
);
1303 fsm_Input(&l
->lcp
.fsm
, bp
);