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"};
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
< 0 || proto
> sizeof cftypes
/ sizeof *cftypes
||
151 cftypes
[proto
] == NULL
)
152 return HexStr(proto
, NULL
, 0);
154 return cftypes
[proto
];
158 lcp_ReportStatus(struct cmdargs
const *arg
)
163 l
= command_ChooseLink(arg
);
166 prompt_Printf(arg
->prompt
, "%s: %s [%s]\n", l
->name
, lcp
->fsm
.name
,
167 State2Nam(lcp
->fsm
.state
));
168 prompt_Printf(arg
->prompt
,
169 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
170 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
171 lcp
->his_mru
, (u_long
)lcp
->his_accmap
,
172 lcp
->his_protocomp
? "on" : "off",
173 lcp
->his_acfcomp
? "on" : "off",
174 (u_long
)lcp
->his_magic
, lcp
->his_mrru
,
175 lcp
->his_shortseq
? "on" : "off", lcp
->his_reject
);
176 prompt_Printf(arg
->prompt
,
177 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
178 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
179 lcp
->want_mru
, (u_long
)lcp
->want_accmap
,
180 lcp
->want_protocomp
? "on" : "off",
181 lcp
->want_acfcomp
? "on" : "off",
182 (u_long
)lcp
->want_magic
, lcp
->want_mrru
,
183 lcp
->want_shortseq
? "on" : "off", lcp
->my_reject
);
186 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = %d (max %d), ",
187 lcp
->cfg
.mru
, lcp
->cfg
.max_mru
);
189 prompt_Printf(arg
->prompt
, "\n Defaults: MRU = any (max %d), ",
192 prompt_Printf(arg
->prompt
, "MTU = %d (max %d), ",
193 lcp
->cfg
.mtu
, lcp
->cfg
.max_mtu
);
195 prompt_Printf(arg
->prompt
, "MTU = any (max %d), ", lcp
->cfg
.max_mtu
);
196 prompt_Printf(arg
->prompt
, "ACCMAP = %08lx\n", (u_long
)lcp
->cfg
.accmap
);
197 prompt_Printf(arg
->prompt
, " LQR period = %us, ",
199 prompt_Printf(arg
->prompt
, "Open Mode = %s",
200 lcp
->cfg
.openmode
== OPEN_PASSIVE
? "passive" : "active");
201 if (lcp
->cfg
.openmode
> 0)
202 prompt_Printf(arg
->prompt
, " (delay %ds)", lcp
->cfg
.openmode
);
203 prompt_Printf(arg
->prompt
, "\n FSM retry = %us, max %u Config"
204 " REQ%s, %u Term REQ%s\n", lcp
->cfg
.fsm
.timeout
,
205 lcp
->cfg
.fsm
.maxreq
, lcp
->cfg
.fsm
.maxreq
== 1 ? "" : "s",
206 lcp
->cfg
.fsm
.maxtrm
, lcp
->cfg
.fsm
.maxtrm
== 1 ? "" : "s");
207 prompt_Printf(arg
->prompt
, " Ident: %s\n", lcp
->cfg
.ident
);
208 prompt_Printf(arg
->prompt
, "\n Negotiation:\n");
209 prompt_Printf(arg
->prompt
, " ACFCOMP = %s\n",
210 command_ShowNegval(lcp
->cfg
.acfcomp
));
211 prompt_Printf(arg
->prompt
, " CHAP = %s\n",
212 command_ShowNegval(lcp
->cfg
.chap05
));
214 prompt_Printf(arg
->prompt
, " CHAP80 = %s\n",
215 command_ShowNegval(lcp
->cfg
.chap80nt
));
216 prompt_Printf(arg
->prompt
, " LANMan = %s\n",
217 command_ShowNegval(lcp
->cfg
.chap80lm
));
218 prompt_Printf(arg
->prompt
, " CHAP81 = %s\n",
219 command_ShowNegval(lcp
->cfg
.chap81
));
221 prompt_Printf(arg
->prompt
, " LQR = %s\n",
222 command_ShowNegval(lcp
->cfg
.lqr
));
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
;
277 lcp
->cfg
.pap
= NEG_ACCEPTED
;
278 lcp
->cfg
.protocomp
= NEG_ENABLED
|NEG_ACCEPTED
;
279 *lcp
->cfg
.ident
= '\0';
281 lcp_Setup(lcp
, lcp
->cfg
.openmode
);
285 lcp_Setup(struct lcp
*lcp
, int openmode
)
287 struct physical
*p
= link2physical(lcp
->fsm
.link
);
289 lcp
->fsm
.open_mode
= openmode
;
291 lcp
->his_mru
= DEF_MRU
;
294 lcp
->his_lqrperiod
= 0;
295 lcp
->his_acfcomp
= 0;
297 lcp
->his_authtype
= 0;
298 lcp
->his_callback
.opmask
= 0;
299 lcp
->his_shortseq
= 0;
302 if ((lcp
->want_mru
= lcp
->cfg
.mru
) == 0)
303 lcp
->want_mru
= DEF_MRU
;
304 lcp
->want_mrru
= lcp
->fsm
.bundle
->ncp
.mp
.cfg
.mrru
;
305 lcp
->want_shortseq
= IsEnabled(lcp
->fsm
.bundle
->ncp
.mp
.cfg
.shortseq
) ? 1 : 0;
306 lcp
->want_acfcomp
= IsEnabled(lcp
->cfg
.acfcomp
) ? 1 : 0;
308 if (lcp
->fsm
.parent
) {
309 lcp
->his_accmap
= 0xffffffff;
310 lcp
->want_accmap
= lcp
->cfg
.accmap
;
311 lcp
->his_protocomp
= 0;
312 lcp
->want_protocomp
= IsEnabled(lcp
->cfg
.protocomp
) ? 1 : 0;
313 lcp
->want_magic
= GenerateMagic();
315 if (IsEnabled(lcp
->cfg
.chap05
)) {
316 lcp
->want_auth
= PROTO_CHAP
;
317 lcp
->want_authtype
= 0x05;
319 } else if (IsEnabled(lcp
->cfg
.chap80nt
) ||
320 IsEnabled(lcp
->cfg
.chap80lm
)) {
321 lcp
->want_auth
= PROTO_CHAP
;
322 lcp
->want_authtype
= 0x80;
323 } else if (IsEnabled(lcp
->cfg
.chap81
)) {
324 lcp
->want_auth
= PROTO_CHAP
;
325 lcp
->want_authtype
= 0x81;
327 } else if (IsEnabled(lcp
->cfg
.pap
)) {
328 lcp
->want_auth
= PROTO_PAP
;
329 lcp
->want_authtype
= 0;
332 lcp
->want_authtype
= 0;
335 if (p
->type
!= PHYS_DIRECT
)
336 memcpy(&lcp
->want_callback
, &p
->dl
->cfg
.callback
,
337 sizeof(struct callback
));
339 lcp
->want_callback
.opmask
= 0;
340 lcp
->want_lqrperiod
= IsEnabled(lcp
->cfg
.lqr
) ?
341 lcp
->cfg
.lqrperiod
* 100 : 0;
343 lcp
->his_accmap
= lcp
->want_accmap
= 0;
344 lcp
->his_protocomp
= lcp
->want_protocomp
= 1;
347 lcp
->want_authtype
= 0;
348 lcp
->want_callback
.opmask
= 0;
349 lcp
->want_lqrperiod
= 0;
352 lcp
->his_reject
= lcp
->my_reject
= 0;
353 lcp
->auth_iwait
= lcp
->auth_ineed
= 0;
354 lcp
->LcpFailedMagic
= 0;
358 LcpInitRestartCounter(struct fsm
*fp
, int what
)
360 /* Set fsm timer load */
361 struct lcp
*lcp
= fsm2lcp(fp
);
363 fp
->FsmTimer
.load
= lcp
->cfg
.fsm
.timeout
* SECTICKS
;
366 fp
->restart
= lcp
->cfg
.fsm
.maxreq
;
369 fp
->restart
= lcp
->cfg
.fsm
.maxtrm
;
378 LcpSendConfigReq(struct fsm
*fp
)
380 /* Send config REQ please */
381 struct physical
*p
= link2physical(fp
->link
);
382 struct lcp
*lcp
= fsm2lcp(fp
);
390 log_Printf(LogERROR
, "%s: LcpSendConfigReq: Not a physical link !\n",
395 o
= (struct fsm_opt
*)buff
;
396 if (!physical_IsSync(p
)) {
397 if (lcp
->want_acfcomp
&& !REJECTED(lcp
, TY_ACFCOMP
))
398 INC_FSM_OPT(TY_ACFCOMP
, 2, o
);
400 if (lcp
->want_protocomp
&& !REJECTED(lcp
, TY_PROTOCOMP
))
401 INC_FSM_OPT(TY_PROTOCOMP
, 2, o
);
403 if (!REJECTED(lcp
, TY_ACCMAP
)) {
404 ua_htonl(&lcp
->want_accmap
, o
->data
);
405 INC_FSM_OPT(TY_ACCMAP
, 6, o
);
409 maxmru
= p
? physical_DeviceMTU(p
) : 0;
410 if (lcp
->cfg
.max_mru
&& (!maxmru
|| maxmru
> lcp
->cfg
.max_mru
))
411 maxmru
= lcp
->cfg
.max_mru
;
412 if (maxmru
&& lcp
->want_mru
> maxmru
) {
413 log_Printf(LogWARN
, "%s: Reducing configured MRU from %u to %u\n",
414 fp
->link
->name
, lcp
->want_mru
, maxmru
);
415 lcp
->want_mru
= maxmru
;
417 if (!REJECTED(lcp
, TY_MRU
)) {
418 ua_htons(&lcp
->want_mru
, o
->data
);
419 INC_FSM_OPT(TY_MRU
, 4, o
);
422 if (lcp
->want_magic
&& !REJECTED(lcp
, TY_MAGICNUM
)) {
423 ua_htonl(&lcp
->want_magic
, o
->data
);
424 INC_FSM_OPT(TY_MAGICNUM
, 6, o
);
427 if (lcp
->want_lqrperiod
&& !REJECTED(lcp
, TY_QUALPROTO
)) {
429 ua_htons(&proto
, o
->data
);
430 ua_htonl(&lcp
->want_lqrperiod
, o
->data
+ 2);
431 INC_FSM_OPT(TY_QUALPROTO
, 8, o
);
434 switch (lcp
->want_auth
) {
437 ua_htons(&proto
, o
->data
);
438 INC_FSM_OPT(TY_AUTHPROTO
, 4, o
);
443 ua_htons(&proto
, o
->data
);
444 o
->data
[2] = lcp
->want_authtype
;
445 INC_FSM_OPT(TY_AUTHPROTO
, 5, o
);
449 if (!REJECTED(lcp
, TY_CALLBACK
)) {
450 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) {
451 *o
->data
= CALLBACK_AUTH
;
452 INC_FSM_OPT(TY_CALLBACK
, 3, o
);
453 } else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
)) {
454 *o
->data
= CALLBACK_CBCP
;
455 INC_FSM_OPT(TY_CALLBACK
, 3, o
);
456 } else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
)) {
457 int sz
= strlen(lcp
->want_callback
.msg
);
459 if (sz
> sizeof o
->data
- 1) {
460 sz
= sizeof o
->data
- 1;
461 log_Printf(LogWARN
, "Truncating E164 data to %d octets (oops!)\n", sz
);
463 *o
->data
= CALLBACK_E164
;
464 memcpy(o
->data
+ 1, lcp
->want_callback
.msg
, sz
);
465 INC_FSM_OPT(TY_CALLBACK
, sz
+ 3, o
);
469 if (lcp
->want_mrru
&& !REJECTED(lcp
, TY_MRRU
)) {
470 ua_htons(&lcp
->want_mrru
, o
->data
);
471 INC_FSM_OPT(TY_MRRU
, 4, o
);
473 if (lcp
->want_shortseq
&& !REJECTED(lcp
, TY_SHORTSEQ
))
474 INC_FSM_OPT(TY_SHORTSEQ
, 2, o
);
477 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
478 if (mp
->cfg
.enddisc
.class != 0 && IsEnabled(mp
->cfg
.negenddisc
) &&
479 !REJECTED(lcp
, TY_ENDDISC
)) {
480 *o
->data
= mp
->cfg
.enddisc
.class;
481 memcpy(o
->data
+1, mp
->cfg
.enddisc
.address
, mp
->cfg
.enddisc
.len
);
482 INC_FSM_OPT(TY_ENDDISC
, mp
->cfg
.enddisc
.len
+ 3, o
);
485 fsm_Output(fp
, CODE_CONFIGREQ
, fp
->reqid
, buff
, (u_char
*)o
- buff
,
490 lcp_SendProtoRej(struct lcp
*lcp
, u_char
*option
, int count
)
492 /* Don't understand `option' */
493 fsm_Output(&lcp
->fsm
, CODE_PROTOREJ
, lcp
->fsm
.reqid
, option
, count
,
498 lcp_SendIdentification(struct lcp
*lcp
)
500 static u_char id
; /* Use a private id */
501 u_char msg
[DEF_MRU
- 3];
505 if (*lcp
->cfg
.ident
== '\0')
508 argv
[0] = lcp
->cfg
.ident
;
511 command_Expand(exp
, 1, argv
, lcp
->fsm
.bundle
, 1, getpid());
513 ua_htonl(&lcp
->want_magic
, msg
);
514 strncpy(msg
+ 4, exp
[0], sizeof msg
- 5);
515 msg
[sizeof msg
- 1] = '\0';
517 fsm_Output(&lcp
->fsm
, CODE_IDENT
, id
++, msg
, 4 + strlen(msg
+ 4), MB_LCPOUT
);
518 log_Printf(LogLCP
, " MAGICNUM %08x\n", lcp
->want_magic
);
519 log_Printf(LogLCP
, " TEXT %s\n", msg
+ 4);
521 command_Free(1, exp
);
526 lcp_RecvIdentification(struct lcp
*lcp
, char *data
)
528 log_Printf(LogLCP
, " MAGICNUM %08x\n", lcp
->his_magic
);
529 log_Printf(LogLCP
, " TEXT %s\n", data
);
533 LcpSentTerminateReq(struct fsm
*fp
)
535 /* Term REQ just sent by FSM */
539 LcpSendTerminateAck(struct fsm
*fp
, u_char id
)
541 /* Send Term ACK please */
542 struct physical
*p
= link2physical(fp
->link
);
544 if (p
&& p
->dl
->state
== DATALINK_CBCP
)
545 cbcp_ReceiveTerminateReq(p
);
547 fsm_Output(fp
, CODE_TERMACK
, id
, NULL
, 0, MB_LCPOUT
);
551 LcpLayerStart(struct fsm
*fp
)
553 /* We're about to start up ! */
554 struct lcp
*lcp
= fsm2lcp(fp
);
556 log_Printf(LogLCP
, "%s: LayerStart\n", fp
->link
->name
);
557 lcp
->LcpFailedMagic
= 0;
558 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= lcp
->cfg
.fsm
.maxreq
* 3;
563 LcpLayerFinish(struct fsm
*fp
)
566 log_Printf(LogLCP
, "%s: LayerFinish\n", fp
->link
->name
);
570 LcpLayerUp(struct fsm
*fp
)
573 struct physical
*p
= link2physical(fp
->link
);
574 struct lcp
*lcp
= fsm2lcp(fp
);
576 log_Printf(LogLCP
, "%s: LayerUp\n", fp
->link
->name
);
577 physical_SetAsyncParams(p
, lcp
->want_accmap
, lcp
->his_accmap
);
579 hdlc_StartTimer(&p
->hdlc
);
580 fp
->more
.reqs
= fp
->more
.naks
= fp
->more
.rejs
= lcp
->cfg
.fsm
.maxreq
* 3;
582 lcp_SendIdentification(lcp
);
588 LcpLayerDown(struct fsm
*fp
)
590 /* About to come down */
591 struct physical
*p
= link2physical(fp
->link
);
593 log_Printf(LogLCP
, "%s: LayerDown\n", fp
->link
->name
);
594 hdlc_StopTimer(&p
->hdlc
);
596 lcp_Setup(fsm2lcp(fp
), 0);
600 E164ok(struct callback
*cb
, char *req
, int sz
)
602 char list
[sizeof cb
->msg
], *next
;
605 if (!strcmp(cb
->msg
, "*"))
608 strncpy(list
, cb
->msg
, sizeof list
- 1);
609 list
[sizeof list
- 1] = '\0';
610 for (next
= strtok(list
, ","); next
; next
= strtok(NULL
, ",")) {
612 if (sz
== len
&& !memcmp(list
, req
, sz
))
619 lcp_auth_nak(struct lcp
*lcp
, struct fsm_decode
*dec
)
623 nak
.hdr
.id
= TY_AUTHPROTO
;
625 if (IsAccepted(lcp
->cfg
.pap
)) {
627 nak
.data
[0] = (unsigned char)(PROTO_PAP
>> 8);
628 nak
.data
[1] = (unsigned char)PROTO_PAP
;
634 nak
.data
[0] = (unsigned char)(PROTO_CHAP
>> 8);
635 nak
.data
[1] = (unsigned char)PROTO_CHAP
;
637 if (IsAccepted(lcp
->cfg
.chap05
)) {
641 } else if (IsAccepted(lcp
->cfg
.chap80nt
) ||
642 IsAccepted(lcp
->cfg
.chap80lm
)) {
645 } else if (IsAccepted(lcp
->cfg
.chap81
)) {
657 LcpDecodeConfig(struct fsm
*fp
, u_char
*cp
, u_char
*end
, int mode_type
,
658 struct fsm_decode
*dec
)
660 /* Deal with incoming PROTO_LCP */
661 struct lcp
*lcp
= fsm2lcp(fp
);
662 int sz
, 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
;
671 sz
= op
= callback_req
= 0;
673 while (end
- cp
>= sizeof(opt
->hdr
)) {
674 if ((opt
= fsm_readopt(&cp
)) == NULL
)
677 snprintf(request
, sizeof request
, " %s[%d]", protoname(opt
->hdr
.id
),
680 switch (opt
->hdr
.id
) {
682 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
683 ua_ntohs(opt
->data
, &mru
);
684 log_Printf(LogLCP
, "%s %u\n", request
, mru
);
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
);
694 /* Push him down to MAX_MRU */
695 lcp
->his_mrru
= MAX_MRU
;
696 nak
.hdr
.id
= TY_MRRU
;
698 ua_htons(&lcp
->his_mrru
, nak
.data
);
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
;
705 ua_htons(&lcp
->his_mrru
, nak
.data
);
714 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
719 if (REJECTED(lcp
, TY_MRRU
))
720 /* Must have changed his mind ! */
721 lcp
->his_reject
&= ~(1 << opt
->hdr
.id
);
724 lcp
->want_mrru
= MAX_MRU
;
725 else if (mru
< MIN_MRU
)
726 lcp
->want_mrru
= MIN_MRU
;
728 lcp
->want_mrru
= mru
;
730 /* else we honour our config and don't send the suggested REQ */
733 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
734 lcp
->want_mrru
= 0; /* Ah well, no multilink :-( */
741 ua_ntohs(opt
->data
, &mru
);
742 log_Printf(LogLCP
, "%s %d\n", request
, mru
);
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
);
756 if (maxmtu
&& mru
> maxmtu
) {
757 lcp
->his_mru
= maxmtu
;
760 ua_htons(&lcp
->his_mru
, nak
.data
);
762 } else if (wantmtu
&& mru
< wantmtu
) {
763 /* Push him up to MTU or MIN_MRU */
764 lcp
->his_mru
= wantmtu
;
767 ua_htons(&lcp
->his_mru
, nak
.data
);
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
;
790 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
796 ua_ntohl(opt
->data
, &accmap
);
797 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)accmap
);
801 lcp
->his_accmap
= accmap
;
805 lcp
->want_accmap
= accmap
;
808 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
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
));
824 if (opt
->hdr
.len
== 4 && IsAccepted(lcp
->cfg
.pap
)) {
825 lcp
->his_auth
= proto
;
826 lcp
->his_authtype
= 0;
828 } else if (!lcp_auth_nak(lcp
, dec
)) {
829 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
835 if ((chap_type
== 0x05 && IsAccepted(lcp
->cfg
.chap05
))
837 || (chap_type
== 0x80 && (IsAccepted(lcp
->cfg
.chap80nt
) ||
838 (IsAccepted(lcp
->cfg
.chap80lm
))))
839 || (chap_type
== 0x81 && IsAccepted(lcp
->cfg
.chap81
))
842 lcp
->his_auth
= proto
;
843 lcp
->his_authtype
= chap_type
;
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");
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
);
865 log_Printf(LogLCP
, "%s 0x%04x - not recognised\n",
867 if (!lcp_auth_nak(lcp
, dec
)) {
868 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
878 if (IsEnabled(lcp
->cfg
.pap
)) {
879 lcp
->want_auth
= PROTO_PAP
;
880 lcp
->want_authtype
= 0;
882 log_Printf(LogLCP
, "Peer will only send PAP (not enabled)\n");
883 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
887 if (chap_type
== 0x05 && IsEnabled(lcp
->cfg
.chap05
)) {
888 lcp
->want_auth
= PROTO_CHAP
;
889 lcp
->want_authtype
= 0x05;
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;
901 if (chap_type
== 0x80) {
902 log_Printf(LogLCP
, "Peer will only send MSCHAP (not available"
904 } else if (chap_type
== 0x81) {
905 log_Printf(LogLCP
, "Peer will only send MSCHAPV2 (not available"
909 log_Printf(LogLCP
, "Peer will only send %s (not %s)\n",
910 Auth2Nam(PROTO_CHAP
, chap_type
),
912 (chap_type
== 0x80 || chap_type
== 0x81) ? "configured" :
915 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
919 /* We've been NAK'd with something we don't understand :-( */
920 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
926 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
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);
937 if (ntohs(req
->proto
) != PROTO_LQR
|| !IsAccepted(lcp
->cfg
.lqr
)) {
939 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
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
);
949 lcp
->want_lqrperiod
= ntohl(req
->period
);
952 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
958 ua_ntohl(opt
->data
, &magic
);
959 log_Printf(LogLCP
, "%s 0x%08lx\n", request
, (u_long
)magic
);
963 if (lcp
->want_magic
) {
964 /* Validate magic number */
965 if (magic
== lcp
->want_magic
) {
968 log_Printf(LogLCP
, "Magic is same (%08lx) - %d times\n",
969 (u_long
)magic
, ++lcp
->LcpFailedMagic
);
970 lcp
->want_magic
= GenerateMagic();
972 ualarm(TICKUNIT
* (4 + 4 * lcp
->LcpFailedMagic
), 0);
973 sigemptyset(&emptyset
);
974 sigsuspend(&emptyset
);
976 lcp
->his_magic
= magic
;
977 lcp
->LcpFailedMagic
= 0;
981 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
986 log_Printf(LogLCP
, " Magic 0x%08lx is NAKed!\n", (u_long
)magic
);
987 lcp
->want_magic
= GenerateMagic();
990 log_Printf(LogLCP
, " Magic 0x%08x is REJected!\n", magic
);
992 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
998 log_Printf(LogLCP
, "%s\n", request
);
1000 switch (mode_type
) {
1002 if (IsAccepted(lcp
->cfg
.protocomp
)) {
1003 lcp
->his_protocomp
= 1;
1007 /* MorningStar before v1.3 needs NAK */
1011 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1017 lcp
->want_protocomp
= 0;
1018 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1024 log_Printf(LogLCP
, "%s\n", request
);
1025 switch (mode_type
) {
1027 if (IsAccepted(lcp
->cfg
.acfcomp
)) {
1028 lcp
->his_acfcomp
= 1;
1032 /* MorningStar before v1.3 needs NAK */
1036 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1042 lcp
->want_acfcomp
= 0;
1043 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1049 log_Printf(LogLCP
, "%s\n", request
);
1050 switch (mode_type
) {
1059 if (opt
->hdr
.len
== 2)
1062 op
= (int)opt
->data
[0];
1063 sz
= opt
->hdr
.len
- 3;
1066 log_Printf(LogLCP
, "%s Auth\n", request
);
1068 case CALLBACK_DIALSTRING
:
1069 log_Printf(LogLCP
, "%s Dialstring %.*s\n", request
, sz
,
1072 case CALLBACK_LOCATION
:
1073 log_Printf(LogLCP
, "%s Location %.*s\n", request
, sz
, opt
->data
+ 1);
1076 log_Printf(LogLCP
, "%s E.164 (%.*s)\n", request
, sz
, opt
->data
+ 1);
1079 log_Printf(LogLCP
, "%s Name %.*s\n", request
, sz
, opt
->data
+ 1);
1082 log_Printf(LogLCP
, "%s CBCP\n", request
);
1085 log_Printf(LogLCP
, "%s ???\n", request
);
1089 switch (mode_type
) {
1092 if (p
->type
!= PHYS_DIRECT
) {
1094 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1096 nak
.hdr
.id
= opt
->hdr
.id
;
1098 if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(op
)) &&
1099 (op
!= CALLBACK_AUTH
|| p
->link
.lcp
.want_auth
) &&
1100 (op
!= CALLBACK_E164
||
1101 E164ok(&p
->dl
->cfg
.callback
, opt
->data
+ 1, sz
))) {
1102 lcp
->his_callback
.opmask
= CALLBACK_BIT(op
);
1103 if (sz
> sizeof lcp
->his_callback
.msg
- 1) {
1104 sz
= sizeof lcp
->his_callback
.msg
- 1;
1105 log_Printf(LogWARN
, "Truncating option arg to %d octets\n", sz
);
1107 memcpy(lcp
->his_callback
.msg
, opt
->data
+ 1, sz
);
1108 lcp
->his_callback
.msg
[sz
] = '\0';
1110 } else if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) &&
1111 p
->link
.lcp
.auth_ineed
) {
1112 nak
.data
[0] = CALLBACK_AUTH
;
1114 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
)) {
1115 nak
.data
[0] = CALLBACK_CBCP
;
1117 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
)) {
1118 nak
.data
[0] = CALLBACK_E164
;
1120 } else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) {
1121 log_Printf(LogWARN
, "Cannot insist on auth callback without"
1122 " PAP or CHAP enabled !\n");
1126 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1131 /* We don't do what he NAKs with, we do things in our preferred order */
1132 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
))
1133 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_AUTH
);
1134 else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
))
1135 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_CBCP
);
1136 else if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
))
1137 lcp
->want_callback
.opmask
&= ~CALLBACK_BIT(CALLBACK_E164
);
1138 if (lcp
->want_callback
.opmask
== CALLBACK_BIT(CALLBACK_NONE
)) {
1139 log_Printf(LogPHASE
, "Peer NAKd all callbacks, trying none\n");
1140 lcp
->want_callback
.opmask
= 0;
1141 } else if (!lcp
->want_callback
.opmask
) {
1142 log_Printf(LogPHASE
, "Peer NAKd last configured callback\n");
1143 fsm_Close(&lcp
->fsm
);
1147 if (lcp
->want_callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
)) {
1148 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1149 lcp
->want_callback
.opmask
= 0;
1151 log_Printf(LogPHASE
, "Peer rejected *required* callback\n");
1152 fsm_Close(&lcp
->fsm
);
1159 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
1160 log_Printf(LogLCP
, "%s\n", request
);
1162 switch (mode_type
) {
1164 if (lcp
->want_mrru
&& IsAccepted(mp
->cfg
.shortseq
)) {
1165 lcp
->his_shortseq
= 1;
1169 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1174 * He's trying to get us to ask for short sequence numbers.
1175 * We ignore the NAK and honour our configuration file instead.
1179 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1180 lcp
->want_shortseq
= 0; /* For when we hit MP */
1186 mp
= &lcp
->fsm
.bundle
->ncp
.mp
;
1187 log_Printf(LogLCP
, "%s %s\n", request
,
1188 mp_Enddisc(opt
->data
[0], opt
->data
+ 1, opt
->hdr
.len
- 3));
1189 switch (mode_type
) {
1192 log_Printf(LogLCP
, " ENDDISC rejected - not a physical link\n");
1194 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1195 } else if (!IsAccepted(mp
->cfg
.negenddisc
)) {
1196 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1198 } else if (opt
->hdr
.len
- 3 < sizeof p
->dl
->peer
.enddisc
.address
&&
1199 opt
->data
[0] <= MAX_ENDDISC_CLASS
) {
1200 p
->dl
->peer
.enddisc
.class = opt
->data
[0];
1201 p
->dl
->peer
.enddisc
.len
= opt
->hdr
.len
- 3;
1202 memcpy(p
->dl
->peer
.enddisc
.address
, opt
->data
+ 1, opt
->hdr
.len
- 3);
1203 p
->dl
->peer
.enddisc
.address
[opt
->hdr
.len
- 3] = '\0';
1204 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1207 if (opt
->data
[0] > MAX_ENDDISC_CLASS
)
1208 log_Printf(LogLCP
, " ENDDISC rejected - unrecognised class %d\n",
1211 log_Printf(LogLCP
, " ENDDISC rejected - local max length is %ld\n",
1212 (long)(sizeof p
->dl
->peer
.enddisc
.address
- 1));
1214 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1218 case MODE_NAK
: /* Treat this as a REJ, we don't vary our disc (yet) */
1220 lcp
->his_reject
|= (1 << opt
->hdr
.id
);
1226 sz
= (sizeof desc
- 2) / 2;
1227 if (sz
> opt
->hdr
.len
- 2)
1228 sz
= opt
->hdr
.len
- 2;
1230 desc
[0] = sz
? ' ' : '\0';
1231 for (pos
= 0; sz
--; pos
++)
1232 sprintf(desc
+(pos
<<1)+1, "%02x", opt
->data
[pos
]);
1234 log_Printf(LogLCP
, "%s%s\n", request
, desc
);
1236 if (mode_type
== MODE_REQ
) {
1238 lcp
->my_reject
|= (1 << opt
->hdr
.id
);
1244 if (mode_type
!= MODE_NOP
) {
1245 if (mode_type
== MODE_REQ
&& p
&& p
->type
== PHYS_DIRECT
&&
1246 p
->dl
->cfg
.callback
.opmask
&& !callback_req
&&
1247 !(p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_NONE
))) {
1248 /* We *REQUIRE* that the peer requests callback */
1249 nak
.hdr
.id
= TY_CALLBACK
;
1251 if ((p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_AUTH
)) &&
1252 p
->link
.lcp
.want_auth
)
1253 nak
.data
[0] = CALLBACK_AUTH
;
1254 else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_CBCP
))
1255 nak
.data
[0] = CALLBACK_CBCP
;
1256 else if (p
->dl
->cfg
.callback
.opmask
& CALLBACK_BIT(CALLBACK_E164
))
1257 nak
.data
[0] = CALLBACK_E164
;
1259 log_Printf(LogWARN
, "Cannot insist on auth callback without"
1260 " PAP or CHAP enabled !\n");
1261 nak
.hdr
.len
= 2; /* XXX: Silly ! */
1265 if (mode_type
== MODE_REQ
&& !lcp
->mru_req
) {
1267 phmtu
= p
? physical_DeviceMTU(p
) : 0;
1268 if (phmtu
&& mru
> phmtu
)
1270 if (mru
> lcp
->cfg
.max_mtu
)
1271 mru
= lcp
->cfg
.max_mtu
;
1272 if (mru
< DEF_MRU
) {
1273 /* Don't let the peer use the default MRU */
1274 lcp
->his_mru
= lcp
->cfg
.mtu
&& lcp
->cfg
.mtu
< mru
? lcp
->cfg
.mtu
: mru
;
1275 nak
.hdr
.id
= TY_MRU
;
1277 ua_htons(&lcp
->his_mru
, nak
.data
);
1279 lcp
->mru_req
= 1; /* Don't keep NAK'ing this */
1282 fsm_opt_normalise(dec
);
1286 extern struct mbuf
*
1287 lcp_Input(struct bundle
*bundle
, struct link
*l
, struct mbuf
*bp
)
1289 /* Got PROTO_LCP from link */
1290 m_settype(bp
, MB_LCPIN
);
1291 fsm_Input(&l
->lcp
.fsm
, bp
);