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
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>
56 #include "throughput.h"
58 #include "descriptor.h"
67 #include "slcompress.h"
84 /* for received LQRs */
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
= {
107 LcpInitRestartCounter
,
112 fsm_NullRecvResetReq
,
116 static const char * const lcp_TimerNames
[] =
117 {"LCP restart", "LCP openmode", "LCP stopped"};
120 protoname(unsigned proto
)
122 static const char * const cftypes
[] = {
123 /* Check out the latest ``Assigned numbers'' rfc (1700) */
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
)
162 l
= command_ChooseLink(arg
);
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
);
185 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = %d (max %d), ",
186 lcp
->cfg
.mru
, lcp
->cfg
.max_mru
);
188 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = any (max %d), ",
191 prompt_Printf(arg
->prompt
, "MTU = %d (max %d), ",
192 lcp
->cfg
.mtu
, lcp
->cfg
.max_mtu
);
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, ",
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
));
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
));
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
));
233 /* Generate random number which will be used as magic number */
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];
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
);
258 lcp
->cfg
.max_mru
= MAX_MRU
;
260 lcp
->cfg
.max_mtu
= MAX_MTU
;
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
;
271 lcp
->cfg
.chap80nt
= NEG_ACCEPTED
;
272 lcp
->cfg
.chap80lm
= 0;
273 lcp
->cfg
.chap81
= NEG_ACCEPTED
;
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
);
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
;
293 lcp
->his_lqrperiod
= 0;
294 lcp
->his_acfcomp
= 0;
296 lcp
->his_authtype
= 0;
297 lcp
->his_callback
.opmask
= 0;
298 lcp
->his_shortseq
= 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;
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;
326 } else if (IsEnabled(lcp
->cfg
.pap
)) {
327 lcp
->want_auth
= PROTO_PAP
;
328 lcp
->want_authtype
= 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
));
338 lcp
->want_callback
.opmask
= 0;
339 lcp
->want_lqrperiod
= IsEnabled(lcp
->cfg
.lqr
) ?
340 lcp
->cfg
.lqrperiod
* 100 : 0;
342 lcp
->his_accmap
= lcp
->want_accmap
= 0;
343 lcp
->his_protocomp
= lcp
->want_protocomp
= 1;
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;
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
;
365 fp
->restart
= lcp
->cfg
.fsm
.maxreq
;
368 fp
->restart
= lcp
->cfg
.fsm
.maxtrm
;
377 LcpSendConfigReq(struct fsm
*fp
)
379 /* Send config REQ please */
380 struct physical
*p
= link2physical(fp
->link
);
381 struct lcp
*lcp
= fsm2lcp(fp
);
389 log_Printf(LogERROR
, "%s: LcpSendConfigReq: Not a physical link !\n",
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
)) {
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
) {
436 ua_htons(&proto
, o
->data
);
437 INC_FSM_OPT(TY_AUTHPROTO
, 4, o
);
442 ua_htons(&proto
, o
->data
);
443 o
->data
[2] = lcp
->want_authtype
;
444 INC_FSM_OPT(TY_AUTHPROTO
, 5, o
);
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
,
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
,
497 lcp_SendIdentification(struct lcp
*lcp
)
499 static u_char id
; /* Use a private id */
500 u_char msg
[DEF_MRU
- 3];
504 if (*lcp
->cfg
.ident
== '\0')
507 argv
[0] = lcp
->cfg
.ident
;
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
);
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
);
532 LcpSentTerminateReq(struct fsm
*fp __unused
)
534 /* Term REQ just sent by FSM */
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
);
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;
562 LcpLayerFinish(struct fsm
*fp
)
565 log_Printf(LogLCP
, "%s: LayerFinish\n", fp
->link
->name
);
569 LcpLayerUp(struct fsm
*fp
)
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
);
578 hdlc_StartTimer(&p
->hdlc
);
579 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= lcp
->cfg
.fsm
.maxreq
* 3;
581 lcp_SendIdentification(lcp
);
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
);
595 lcp_Setup(fsm2lcp(fp
), 0);
599 E164ok(struct callback
*cb
, char *req
, int sz
)
601 char list
[sizeof cb
->msg
], *next
;
604 if (!strcmp(cb
->msg
, "*"))
607 strncpy(list
, cb
->msg
, sizeof list
- 1);
608 list
[sizeof list
- 1] = '\0';
609 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ",")) {
611 if (sz
== len
&& !memcmp(list
, req
, sz
))
618 lcp_auth_nak(struct lcp
*lcp
, struct fsm_decode
*dec
)
622 nak
.hdr
.id
= TY_AUTHPROTO
;
624 if (IsAccepted(lcp
->cfg
.pap
)) {
626 nak
.data
[0] = (unsigned char)(PROTO_PAP
>> 8);
627 nak
.data
[1] = (unsigned char)PROTO_PAP
;
633 nak
.data
[0] = (unsigned char)(PROTO_CHAP
>> 8);
634 nak
.data
[1] = (unsigned char)PROTO_CHAP
;
636 if (IsAccepted(lcp
->cfg
.chap05
)) {
640 } else if (IsAccepted(lcp
->cfg
.chap80nt
) ||
641 IsAccepted(lcp
->cfg
.chap80lm
)) {
644 } else if (IsAccepted(lcp
->cfg
.chap81
)) {
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
;
663 u_int32_t magic
, accmap
;
664 u_short mru
, phmtu
, maxmtu
, maxmru
, wantmtu
, wantmru
, proto
;
666 char request
[20], desc
[22];
668 struct physical
*p
= link2physical(fp
->link
);
669 struct fsm_opt
*opt
, nak
;
672 op
= callback_req
= 0;
674 while (end
- cp
>= (int)sizeof(opt
->hdr
)) {
675 if ((opt
= fsm_readopt(&cp
)) == NULL
)
678 snprintf(request
, sizeof request
, " %s[%d]", protoname(opt
->hdr
.id
),
681 switch (opt
->hdr
.id
) {
683 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
684 ua_ntohs(opt
->data
, &mru
);
685 log_Printf(LogLCP
, "%s %u\n", request
, mru
);
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
);
695 /* Push him down to MAX_MRU */
696 lcp
->his_mrru
= MAX_MRU
;
697 nak
.hdr
.id
= TY_MRRU
;
699 ua_htons(&lcp
->his_mrru
, nak
.data
);
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
;
706 ua_htons(&lcp
->his_mrru
, nak
.data
);
715 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
720 if (REJECTED(lcp
, TY_MRRU
))
721 /* Must have changed his mind ! */
722 lcp
->his_reject
&= ~(1 << opt
->hdr
.id
);
725 lcp
->want_mrru
= MAX_MRU
;
726 else if (mru
< MIN_MRU
)
727 lcp
->want_mrru
= MIN_MRU
;
729 lcp
->want_mrru
= mru
;
731 /* else we honour our config and don't send the suggested REQ */
734 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
735 lcp
->want_mrru
= 0; /* Ah well, no multilink :-( */
742 ua_ntohs(opt
->data
, &mru
);
743 log_Printf(LogLCP
, "%s %d\n", request
, mru
);
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
);
757 if (maxmtu
&& mru
> maxmtu
) {
758 lcp
->his_mru
= maxmtu
;
761 ua_htons(&lcp
->his_mru
, nak
.data
);
763 } else if (wantmtu
&& mru
< wantmtu
) {
764 /* Push him up to MTU or MIN_MRU */
765 lcp
->his_mru
= wantmtu
;
768 ua_htons(&lcp
->his_mru
, nak
.data
);
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
;
791 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
797 ua_ntohl(opt
->data
, &accmap
);
798 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)accmap
);
802 lcp
->his_accmap
= accmap
;
806 lcp
->want_accmap
= accmap
;
809 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
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
));
825 if (opt
->hdr
.len
== 4 && IsAccepted(lcp
->cfg
.pap
)) {
826 lcp
->his_auth
= proto
;
827 lcp
->his_authtype
= 0;
829 } else if (!lcp_auth_nak(lcp
, dec
)) {
830 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
836 if ((chap_type
== 0x05 && IsAccepted(lcp
->cfg
.chap05
))
838 || (chap_type
== 0x80 && (IsAccepted(lcp
->cfg
.chap80nt
) ||
839 (IsAccepted(lcp
->cfg
.chap80lm
))))
840 || (chap_type
== 0x81 && IsAccepted(lcp
->cfg
.chap81
))
843 lcp
->his_auth
= proto
;
844 lcp
->his_authtype
= chap_type
;
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");
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
);
866 log_Printf(LogLCP
, "%s 0x%04x - not recognised\n",
868 if (!lcp_auth_nak(lcp
, dec
)) {
869 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
879 if (IsEnabled(lcp
->cfg
.pap
)) {
880 lcp
->want_auth
= PROTO_PAP
;
881 lcp
->want_authtype
= 0;
883 log_Printf(LogLCP
, "Peer will only send PAP (not enabled)\n");
884 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
888 if (chap_type
== 0x05 && IsEnabled(lcp
->cfg
.chap05
)) {
889 lcp
->want_auth
= PROTO_CHAP
;
890 lcp
->want_authtype
= 0x05;
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;
902 if (chap_type
== 0x80) {
903 log_Printf(LogLCP
, "Peer will only send MSCHAP (not available"
905 } else if (chap_type
== 0x81) {
906 log_Printf(LogLCP
, "Peer will only send MSCHAPV2 (not available"
910 log_Printf(LogLCP
, "Peer will only send %s (not %s)\n",
911 Auth2Nam(PROTO_CHAP
, chap_type
),
913 (chap_type
== 0x80 || chap_type
== 0x81) ? "configured" :
916 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
920 /* We've been NAK'd with something we don't understand :-( */
921 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
927 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
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);
938 if (ntohs(req
->proto
) != PROTO_LQR
|| !IsAccepted(lcp
->cfg
.lqr
)) {
940 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
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
);
950 lcp
->want_lqrperiod
= ntohl(req
->period
);
953 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
959 ua_ntohl(opt
->data
, &magic
);
960 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)magic
);
964 if (lcp
->want_magic
) {
965 /* Validate magic number */
966 if (magic
== lcp
->want_magic
) {
969 log_Printf(LogLCP
, "Magic is same (%08lx) - %d times\n",
970 (u_long
)magic
, ++lcp
->LcpFailedMagic
);
971 lcp
->want_magic
= GenerateMagic();
973 ualarm(TICKUNIT
* (4 + 4 * lcp
->LcpFailedMagic
), 0);
974 sigemptyset(&emptyset
);
975 sigsuspend(&emptyset
);
977 lcp
->his_magic
= magic
;
978 lcp
->LcpFailedMagic
= 0;
982 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
987 log_Printf(LogLCP
, " Magic 0x%08lx is NAKed!\n", (u_long
)magic
);
988 lcp
->want_magic
= GenerateMagic();
991 log_Printf(LogLCP
, " Magic 0x%08x is REJected!\n", magic
);
993 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
999 log_Printf(LogLCP
, "%s\n", request
);
1001 switch (mode_type
) {
1003 if (IsAccepted(lcp
->cfg
.protocomp
)) {
1004 lcp
->his_protocomp
= 1;
1008 /* MorningStar before v1.3 needs NAK */
1012 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1018 lcp
->want_protocomp
= 0;
1019 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1025 log_Printf(LogLCP
, "%s\n", request
);
1026 switch (mode_type
) {
1028 if (IsAccepted(lcp
->cfg
.acfcomp
)) {
1029 lcp
->his_acfcomp
= 1;
1033 /* MorningStar before v1.3 needs NAK */
1037 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1043 lcp
->want_acfcomp
= 0;
1044 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1050 log_Printf(LogLCP
, "%s\n", request
);
1051 switch (mode_type
) {
1060 if (opt
->hdr
.len
== 2) {
1064 op
= (int)opt
->data
[0];
1065 sz
= opt
->hdr
.len
- 3;
1069 log_Printf(LogLCP
, "%s Auth\n", request
);
1071 case CALLBACK_DIALSTRING
:
1072 log_Printf(LogLCP
, "%s Dialstring %.*s\n", request
, (int)sz
,
1075 case CALLBACK_LOCATION
:
1076 log_Printf(LogLCP
, "%s Location %.*s\n", request
, (int)sz
, opt
->data
+ 1);
1079 log_Printf(LogLCP
, "%s E.164 (%.*s)\n", request
, (int)sz
, opt
->data
+ 1);
1082 log_Printf(LogLCP
, "%s Name %.*s\n", request
, (int)sz
, opt
->data
+ 1);
1085 log_Printf(LogLCP
, "%s CBCP\n", request
);
1088 log_Printf(LogLCP
, "%s ???\n", request
);
1092 switch (mode_type
) {
1095 if (p
->type
!= PHYS_DIRECT
) {
1097 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1099 nak
.hdr
.id
= opt
->hdr
.id
;
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';
1113 } else if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) &&
1114 p
->link
.lcp
.auth_ineed
) {
1115 nak
.data
[0] = CALLBACK_AUTH
;
1117 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
)) {
1118 nak
.data
[0] = CALLBACK_CBCP
;
1120 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
)) {
1121 nak
.data
[0] = CALLBACK_E164
;
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");
1129 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
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
);
1150 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
)) {
1151 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1152 lcp
->want_callback
.opmask
= 0;
1154 log_Printf(LogPHASE
, "Peer rejected *required* callback\n");
1155 fsm_Close(&lcp
->fsm
);
1162 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
1163 log_Printf(LogLCP
, "%s\n", request
);
1165 switch (mode_type
) {
1167 if (lcp
->want_mrru
&& IsAccepted(mp
->cfg
.shortseq
)) {
1168 lcp
->his_shortseq
= 1;
1172 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1177 * He's trying to get us to ask for short sequence numbers.
1178 * We ignore the NAK and honour our configuration file instead.
1182 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1183 lcp
->want_shortseq
= 0; /* For when we hit MP */
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
) {
1195 log_Printf(LogLCP
, " ENDDISC rejected - not a physical link\n");
1197 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1198 } else if (!IsAccepted(mp
->cfg
.negenddisc
)) {
1199 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
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 ? */
1210 if (opt
->data
[0] > MAX_ENDDISC_CLASS
)
1211 log_Printf(LogLCP
, " ENDDISC rejected - unrecognised class %d\n",
1214 log_Printf(LogLCP
, " ENDDISC rejected - local max length is %ld\n",
1215 (long)(sizeof p
->dl
->peer
.enddisc
.address
- 1));
1217 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1221 case MODE_NAK
: /* Treat this as a REJ, we don't vary our disc (yet) */
1223 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1229 sz
= (sizeof desc
- 2) / 2;
1230 if (sz
+ 2 > opt
->hdr
.len
)
1231 sz
= opt
->hdr
.len
- 2;
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
) {
1241 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
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
;
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
;
1262 log_Printf(LogWARN
, "Cannot insist on auth callback without"
1263 " PAP or CHAP enabled !\n");
1264 nak
.hdr
.len
= 2; /* XXX: Silly ! */
1268 if (mode_type
== MODE_REQ
&& !lcp
->mru_req
) {
1270 phmtu
= p
? physical_DeviceMTU(p
) : 0;
1271 if (phmtu
&& 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
;
1280 ua_htons(&lcp
->his_mru
, nak
.data
);
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
);