1995-01-31 06:29:58 +00:00
|
|
|
/*
|
|
|
|
* PPP Link Control Protocol (LCP) Module
|
|
|
|
*
|
|
|
|
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
|
|
|
|
*
|
|
|
|
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms are permitted
|
|
|
|
* provided that the above copyright notice and this paragraph are
|
|
|
|
* duplicated in all such forms and that any documentation,
|
|
|
|
* advertising materials, and other materials related to such
|
|
|
|
* distribution and use acknowledge that the software was developed
|
|
|
|
* by the Internet Initiative Japan, Inc. The name of the
|
|
|
|
* IIJ may not be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1999-08-28 01:35:59 +00:00
|
|
|
* $FreeBSD$
|
1995-05-30 03:57:47 +00:00
|
|
|
*
|
1995-01-31 06:29:58 +00:00
|
|
|
*/
|
1998-05-21 21:49:08 +00:00
|
|
|
|
1999-01-28 01:56:34 +00:00
|
|
|
#include <sys/param.h>
|
1998-01-21 02:15:33 +00:00
|
|
|
#include <netinet/in.h>
|
1998-05-21 21:49:08 +00:00
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <sys/un.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
|
1997-09-22 02:51:24 +00:00
|
|
|
#include <signal.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
1998-06-27 23:48:54 +00:00
|
|
|
#include <string.h>
|
1997-10-26 01:04:02 +00:00
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
#include "layer.h"
|
1998-09-04 18:26:00 +00:00
|
|
|
#include "ua.h"
|
1998-06-15 19:06:25 +00:00
|
|
|
#include "defs.h"
|
1997-11-22 03:37:54 +00:00
|
|
|
#include "command.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "mbuf.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "timer.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "fsm.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "iplist.h"
|
|
|
|
#include "throughput.h"
|
1999-05-08 11:07:56 +00:00
|
|
|
#include "proto.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "descriptor.h"
|
|
|
|
#include "lqr.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
#include "hdlc.h"
|
2000-07-19 02:10:35 +00:00
|
|
|
#include "lcp.h"
|
1996-01-11 17:48:59 +00:00
|
|
|
#include "ccp.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "async.h"
|
|
|
|
#include "link.h"
|
|
|
|
#include "physical.h"
|
|
|
|
#include "prompt.h"
|
|
|
|
#include "slcompress.h"
|
|
|
|
#include "ipcp.h"
|
|
|
|
#include "filter.h"
|
|
|
|
#include "mp.h"
|
|
|
|
#include "chat.h"
|
1995-02-26 12:18:08 +00:00
|
|
|
#include "auth.h"
|
1997-10-26 01:04:02 +00:00
|
|
|
#include "chap.h"
|
1998-08-07 18:42:51 +00:00
|
|
|
#include "cbcp.h"
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "datalink.h"
|
1999-01-28 01:56:34 +00:00
|
|
|
#ifndef NORADIUS
|
|
|
|
#include "radius.h"
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
#include "bundle.h"
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-12-03 10:23:54 +00:00
|
|
|
/* for received LQRs */
|
|
|
|
struct lqrreq {
|
|
|
|
u_char type;
|
|
|
|
u_char length;
|
|
|
|
u_short proto; /* Quality protocol */
|
1998-06-27 23:48:54 +00:00
|
|
|
u_int32_t period; /* Reporting interval */
|
1997-12-03 10:23:54 +00:00
|
|
|
};
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int LcpLayerUp(struct fsm *);
|
1997-06-09 03:27:43 +00:00
|
|
|
static void LcpLayerDown(struct fsm *);
|
|
|
|
static void LcpLayerStart(struct fsm *);
|
|
|
|
static void LcpLayerFinish(struct fsm *);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
static void LcpInitRestartCounter(struct fsm *, int);
|
1998-05-21 21:49:08 +00:00
|
|
|
static void LcpSendConfigReq(struct fsm *);
|
|
|
|
static void LcpSentTerminateReq(struct fsm *);
|
|
|
|
static void LcpSendTerminateAck(struct fsm *, u_char);
|
|
|
|
static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
|
|
|
|
struct fsm_decode *);
|
|
|
|
|
|
|
|
static struct fsm_callbacks lcp_Callbacks = {
|
|
|
|
LcpLayerUp,
|
|
|
|
LcpLayerDown,
|
|
|
|
LcpLayerStart,
|
|
|
|
LcpLayerFinish,
|
|
|
|
LcpInitRestartCounter,
|
|
|
|
LcpSendConfigReq,
|
|
|
|
LcpSentTerminateReq,
|
|
|
|
LcpSendTerminateAck,
|
|
|
|
LcpDecodeConfig,
|
|
|
|
fsm_NullRecvResetReq,
|
|
|
|
fsm_NullRecvResetAck
|
|
|
|
};
|
|
|
|
|
1999-12-27 11:54:57 +00:00
|
|
|
static const char * const lcp_TimerNames[] =
|
1998-05-21 21:49:08 +00:00
|
|
|
{"LCP restart", "LCP openmode", "LCP stopped"};
|
1995-01-31 06:29:58 +00:00
|
|
|
|
2000-03-14 01:46:54 +00:00
|
|
|
static const char *
|
|
|
|
protoname(int proto)
|
|
|
|
{
|
|
|
|
static const char * const cftypes[] = {
|
|
|
|
/* Check out the latest ``Assigned numbers'' rfc (1700) */
|
|
|
|
NULL,
|
|
|
|
"MRU", /* 1: Maximum-Receive-Unit */
|
|
|
|
"ACCMAP", /* 2: Async-Control-Character-Map */
|
|
|
|
"AUTHPROTO", /* 3: Authentication-Protocol */
|
|
|
|
"QUALPROTO", /* 4: Quality-Protocol */
|
|
|
|
"MAGICNUM", /* 5: Magic-Number */
|
|
|
|
"RESERVED", /* 6: RESERVED */
|
|
|
|
"PROTOCOMP", /* 7: Protocol-Field-Compression */
|
|
|
|
"ACFCOMP", /* 8: Address-and-Control-Field-Compression */
|
|
|
|
"FCSALT", /* 9: FCS-Alternatives */
|
|
|
|
"SDP", /* 10: Self-Describing-Pad */
|
|
|
|
"NUMMODE", /* 11: Numbered-Mode */
|
|
|
|
"MULTIPROC", /* 12: Multi-Link-Procedure */
|
|
|
|
"CALLBACK", /* 13: Callback */
|
|
|
|
"CONTIME", /* 14: Connect-Time */
|
|
|
|
"COMPFRAME", /* 15: Compound-Frames */
|
|
|
|
"NDE", /* 16: Nominal-Data-Encapsulation */
|
|
|
|
"MRRU", /* 17: Multilink-MRRU */
|
|
|
|
"SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
|
|
|
|
"ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
|
|
|
|
"PROPRIETRY", /* 20: Proprietary */
|
|
|
|
"DCEID", /* 21: DCE-Identifier */
|
|
|
|
"MULTIPP", /* 22: Multi-Link-Plus-Procedure */
|
|
|
|
"LDBACP", /* 23: Link Discriminator for BACP */
|
|
|
|
};
|
|
|
|
|
|
|
|
if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes ||
|
|
|
|
cftypes[proto] == NULL)
|
|
|
|
return HexStr(proto, NULL, 0);
|
|
|
|
|
|
|
|
return cftypes[proto];
|
|
|
|
}
|
1997-11-14 15:39:15 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
int
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp_ReportStatus(struct cmdargs const *arg)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
struct link *l;
|
|
|
|
struct lcp *lcp;
|
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
l = command_ChooseLink(arg);
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp = &l->lcp;
|
|
|
|
|
|
|
|
prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
|
|
|
|
State2Nam(lcp->fsm.state));
|
|
|
|
prompt_Printf(arg->prompt,
|
|
|
|
" his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
|
|
|
|
" MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
|
|
|
|
lcp->his_mru, (u_long)lcp->his_accmap,
|
|
|
|
lcp->his_protocomp ? "on" : "off",
|
|
|
|
lcp->his_acfcomp ? "on" : "off",
|
|
|
|
(u_long)lcp->his_magic, lcp->his_mrru,
|
|
|
|
lcp->his_shortseq ? "on" : "off", lcp->his_reject);
|
|
|
|
prompt_Printf(arg->prompt,
|
|
|
|
" my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
|
|
|
|
" MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
|
|
|
|
lcp->want_mru, (u_long)lcp->want_accmap,
|
|
|
|
lcp->want_protocomp ? "on" : "off",
|
|
|
|
lcp->want_acfcomp ? "on" : "off",
|
|
|
|
(u_long)lcp->want_magic, lcp->want_mrru,
|
|
|
|
lcp->want_shortseq ? "on" : "off", lcp->my_reject);
|
|
|
|
|
|
|
|
prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru);
|
|
|
|
prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
|
|
|
|
prompt_Printf(arg->prompt, " LQR period = %us, ",
|
|
|
|
lcp->cfg.lqrperiod);
|
|
|
|
prompt_Printf(arg->prompt, "Open Mode = %s",
|
|
|
|
lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
|
|
|
|
if (lcp->cfg.openmode > 0)
|
|
|
|
prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
|
|
|
|
" REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
|
|
|
|
lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
|
|
|
|
lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
|
2000-07-19 02:10:35 +00:00
|
|
|
prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, "\n Negotiation:\n");
|
|
|
|
prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.acfcomp));
|
|
|
|
prompt_Printf(arg->prompt, " CHAP = %s\n",
|
1999-02-18 00:52:15 +00:00
|
|
|
command_ShowNegval(lcp->cfg.chap05));
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
prompt_Printf(arg->prompt, " MSCHAP = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.chap80nt));
|
|
|
|
prompt_Printf(arg->prompt, " LANMan = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.chap80lm));
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
prompt_Printf(arg->prompt, " LQR = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.lqr));
|
|
|
|
prompt_Printf(arg->prompt, " PAP = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.pap));
|
|
|
|
prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
|
|
|
|
command_ShowNegval(lcp->cfg.protocomp));
|
|
|
|
|
1997-06-09 03:27:43 +00:00
|
|
|
return 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-01-11 17:50:49 +00:00
|
|
|
static u_int32_t
|
1997-11-22 03:37:54 +00:00
|
|
|
GenerateMagic(void)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Generate random number which will be used as magic number */
|
1997-10-26 01:04:02 +00:00
|
|
|
randinit();
|
1998-05-21 21:49:08 +00:00
|
|
|
return random();
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp_SetupCallbacks(struct lcp *lcp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->fsm.fn = &lcp_Callbacks;
|
|
|
|
lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
|
|
|
|
lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
|
|
|
|
lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
void
|
|
|
|
lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
|
|
|
|
const struct fsm_parent *parent)
|
|
|
|
{
|
|
|
|
/* Initialise ourselves */
|
|
|
|
int mincode = parent ? 1 : LCP_MINMPCODE;
|
1995-01-31 06:29:58 +00:00
|
|
|
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
|
1998-05-21 21:49:08 +00:00
|
|
|
bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
|
|
|
|
|
|
|
|
lcp->cfg.mru = DEF_MRU;
|
|
|
|
lcp->cfg.accmap = 0;
|
|
|
|
lcp->cfg.openmode = 1;
|
|
|
|
lcp->cfg.lqrperiod = DEF_LQRPERIOD;
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
lcp->cfg.fsm.timeout = DEF_FSMRETRY;
|
|
|
|
lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
|
|
|
|
lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->cfg.chap05 = NEG_ACCEPTED;
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
lcp->cfg.chap80nt = NEG_ACCEPTED;
|
|
|
|
lcp->cfg.chap80lm = NEG_ACCEPTED;
|
|
|
|
#endif
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->cfg.lqr = NEG_ACCEPTED;
|
|
|
|
lcp->cfg.pap = NEG_ACCEPTED;
|
|
|
|
lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
|
2000-07-19 02:10:35 +00:00
|
|
|
*lcp->cfg.ident = '\0';
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
lcp_Setup(lcp, lcp->cfg.openmode);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
void
|
|
|
|
lcp_Setup(struct lcp *lcp, int openmode)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->fsm.open_mode = openmode;
|
|
|
|
|
1998-09-09 00:03:09 +00:00
|
|
|
lcp->his_mru = lcp->fsm.bundle->cfg.mtu;
|
|
|
|
if (!lcp->his_mru || lcp->his_mru > DEF_MRU)
|
|
|
|
lcp->his_mru = DEF_MRU;
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_mrru = 0;
|
|
|
|
lcp->his_magic = 0;
|
|
|
|
lcp->his_lqrperiod = 0;
|
|
|
|
lcp->his_acfcomp = 0;
|
|
|
|
lcp->his_auth = 0;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->his_authtype = 0;
|
1998-08-07 18:42:51 +00:00
|
|
|
lcp->his_callback.opmask = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_shortseq = 0;
|
|
|
|
|
|
|
|
lcp->want_mru = lcp->cfg.mru;
|
|
|
|
lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
|
|
|
|
lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
|
|
|
|
lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
|
|
|
|
|
|
|
|
if (lcp->fsm.parent) {
|
1998-08-07 18:42:51 +00:00
|
|
|
struct physical *p = link2physical(lcp->fsm.link);
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_accmap = 0xffffffff;
|
|
|
|
lcp->want_accmap = lcp->cfg.accmap;
|
|
|
|
lcp->his_protocomp = 0;
|
|
|
|
lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
|
|
|
|
lcp->want_magic = GenerateMagic();
|
1999-02-18 00:52:15 +00:00
|
|
|
|
|
|
|
if (IsEnabled(lcp->cfg.chap05)) {
|
|
|
|
lcp->want_auth = PROTO_CHAP;
|
|
|
|
lcp->want_authtype = 0x05;
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
} else if (IsEnabled(lcp->cfg.chap80nt) ||
|
|
|
|
IsEnabled(lcp->cfg.chap80lm)) {
|
|
|
|
lcp->want_auth = PROTO_CHAP;
|
|
|
|
lcp->want_authtype = 0x80;
|
|
|
|
#endif
|
|
|
|
} else if (IsEnabled(lcp->cfg.pap)) {
|
|
|
|
lcp->want_auth = PROTO_PAP;
|
|
|
|
lcp->want_authtype = 0;
|
|
|
|
} else {
|
|
|
|
lcp->want_auth = 0;
|
|
|
|
lcp->want_authtype = 0;
|
|
|
|
}
|
|
|
|
|
1998-08-07 18:42:51 +00:00
|
|
|
if (p->type != PHYS_DIRECT)
|
|
|
|
memcpy(&lcp->want_callback, &p->dl->cfg.callback, sizeof(struct callback));
|
|
|
|
else
|
|
|
|
lcp->want_callback.opmask = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
|
|
|
|
lcp->cfg.lqrperiod * 100 : 0;
|
|
|
|
} else {
|
|
|
|
lcp->his_accmap = lcp->want_accmap = 0;
|
|
|
|
lcp->his_protocomp = lcp->want_protocomp = 1;
|
|
|
|
lcp->want_magic = 0;
|
|
|
|
lcp->want_auth = 0;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->want_authtype = 0;
|
1998-08-07 18:42:51 +00:00
|
|
|
lcp->want_callback.opmask = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_lqrperiod = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
lcp->his_reject = lcp->my_reject = 0;
|
|
|
|
lcp->auth_iwait = lcp->auth_ineed = 0;
|
|
|
|
lcp->LcpFailedMagic = 0;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static void
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
LcpInitRestartCounter(struct fsm *fp, int what)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Set fsm timer load */
|
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
1997-12-03 10:23:54 +00:00
|
|
|
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
|
|
|
|
switch (what) {
|
|
|
|
case FSM_REQ_TIMER:
|
|
|
|
fp->restart = lcp->cfg.fsm.maxreq;
|
|
|
|
break;
|
|
|
|
case FSM_TRM_TIMER:
|
|
|
|
fp->restart = lcp->cfg.fsm.maxtrm;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fp->restart = 1;
|
|
|
|
break;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
LcpSendConfigReq(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Send config REQ please */
|
|
|
|
struct physical *p = link2physical(fp->link);
|
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
|
|
|
u_char buff[200];
|
|
|
|
struct lcp_opt *o;
|
|
|
|
struct mp *mp;
|
1998-09-04 18:26:00 +00:00
|
|
|
u_int16_t proto;
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
if (!p) {
|
|
|
|
log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
|
|
|
|
fp->link->name);
|
|
|
|
return;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
o = (struct lcp_opt *)buff;
|
|
|
|
if (!physical_IsSync(p)) {
|
1997-12-03 10:23:54 +00:00
|
|
|
if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_ACFCOMP, 2, o);
|
1997-12-03 10:23:54 +00:00
|
|
|
|
|
|
|
if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_PROTOCOMP, 2, o);
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!REJECTED(lcp, TY_ACCMAP)) {
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_htonl(&lcp->want_accmap, o->data);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_ACCMAP, 6, o);
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (!REJECTED(lcp, TY_MRU)) {
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_htons(&lcp->want_mru, o->data);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_MRU, 4, o);
|
|
|
|
}
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_htonl(&lcp->want_magic, o->data);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_MAGICNUM, 6, o);
|
|
|
|
}
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
|
1998-09-04 18:26:00 +00:00
|
|
|
proto = PROTO_LQR;
|
|
|
|
ua_htons(&proto, o->data);
|
|
|
|
ua_htonl(&lcp->want_lqrperiod, o->data + 2);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_QUALPROTO, 8, o);
|
|
|
|
}
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
switch (lcp->want_auth) {
|
|
|
|
case PROTO_PAP:
|
1998-09-04 18:26:00 +00:00
|
|
|
proto = PROTO_PAP;
|
|
|
|
ua_htons(&proto, o->data);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_AUTHPROTO, 4, o);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case PROTO_CHAP:
|
1998-09-04 18:26:00 +00:00
|
|
|
proto = PROTO_CHAP;
|
|
|
|
ua_htons(&proto, o->data);
|
1999-02-18 00:52:15 +00:00
|
|
|
o->data[2] = lcp->want_authtype;
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_AUTHPROTO, 5, o);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1998-08-07 18:42:51 +00:00
|
|
|
if (!REJECTED(lcp, TY_CALLBACK)) {
|
|
|
|
if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
|
|
|
|
*o->data = CALLBACK_AUTH;
|
|
|
|
INC_LCP_OPT(TY_CALLBACK, 3, o);
|
|
|
|
} else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
|
|
|
|
*o->data = CALLBACK_CBCP;
|
|
|
|
INC_LCP_OPT(TY_CALLBACK, 3, o);
|
|
|
|
} else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
|
|
|
|
int sz = strlen(lcp->want_callback.msg);
|
|
|
|
|
|
|
|
if (sz > sizeof o->data - 1) {
|
|
|
|
sz = sizeof o->data - 1;
|
|
|
|
log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
|
|
|
|
}
|
|
|
|
*o->data = CALLBACK_E164;
|
|
|
|
memcpy(o->data + 1, lcp->want_callback.msg, sz);
|
|
|
|
INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_htons(&lcp->want_mrru, o->data);
|
1998-05-21 21:49:08 +00:00
|
|
|
INC_LCP_OPT(TY_MRRU, 4, o);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
|
|
|
|
INC_LCP_OPT(TY_SHORTSEQ, 2, o);
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
mp = &lcp->fsm.bundle->ncp.mp;
|
1999-06-09 16:54:04 +00:00
|
|
|
if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
|
|
|
|
!REJECTED(lcp, TY_ENDDISC)) {
|
1998-05-21 21:49:08 +00:00
|
|
|
*o->data = mp->cfg.enddisc.class;
|
|
|
|
memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
|
|
|
|
INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
|
|
|
|
MB_LCPOUT);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
void
|
|
|
|
lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Don't understand `option' */
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
|
|
|
|
MB_LCPOUT);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
2000-07-19 02:10:35 +00:00
|
|
|
int
|
|
|
|
lcp_SendIdentification(struct lcp *lcp)
|
|
|
|
{
|
|
|
|
static u_char id; /* Use a private id */
|
|
|
|
u_char msg[DEF_MRU - 3];
|
|
|
|
const char *argv[2];
|
|
|
|
char *exp[2];
|
|
|
|
|
|
|
|
if (*lcp->cfg.ident == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
argv[0] = lcp->cfg.ident;
|
|
|
|
argv[1] = NULL;
|
|
|
|
|
|
|
|
command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
|
|
|
|
|
|
|
|
ua_htonl(&lcp->want_magic, msg);
|
|
|
|
strncpy(msg + 4, exp[0], sizeof msg - 5);
|
|
|
|
msg[sizeof msg - 1] = '\0';
|
|
|
|
|
|
|
|
log_Printf(LogLCP, "Sending ident magic %08x text %s\n", lcp->want_magic,
|
|
|
|
msg + 4);
|
|
|
|
fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
|
|
|
|
|
|
|
|
free(exp[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lcp_RecvIdentification(struct lcp *lcp, char *data)
|
|
|
|
{
|
|
|
|
log_Printf(LogLCP, "Received ident: %s\n", data);
|
|
|
|
}
|
|
|
|
|
1995-02-26 12:18:08 +00:00
|
|
|
static void
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
LcpSentTerminateReq(struct fsm *fp)
|
1995-02-26 12:18:08 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Term REQ just sent by FSM */
|
1995-02-26 12:18:08 +00:00
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
LcpSendTerminateAck(struct fsm *fp, u_char id)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Send Term ACK please */
|
1998-08-07 18:42:51 +00:00
|
|
|
struct physical *p = link2physical(fp->link);
|
|
|
|
|
|
|
|
if (p && p->dl->state == DATALINK_CBCP)
|
|
|
|
cbcp_ReceiveTerminateReq(p);
|
|
|
|
|
1999-06-02 15:59:09 +00:00
|
|
|
fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
LcpLayerStart(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* We're about to start up ! */
|
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->LcpFailedMagic = 0;
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
LcpLayerFinish(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* We're now down */
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static int
|
|
|
|
LcpLayerUp(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* We're now up */
|
|
|
|
struct physical *p = link2physical(fp->link);
|
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
|
1998-05-21 21:49:08 +00:00
|
|
|
async_SetLinkParams(&p->async, lcp);
|
|
|
|
lqr_Start(lcp);
|
|
|
|
hdlc_StartTimer(&p->hdlc);
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
|
|
|
|
|
2000-07-19 02:10:35 +00:00
|
|
|
lcp_SendIdentification(lcp);
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
return 1;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
static void
|
|
|
|
LcpLayerDown(struct fsm *fp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* About to come down */
|
|
|
|
struct physical *p = link2physical(fp->link);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
|
1998-05-21 21:49:08 +00:00
|
|
|
hdlc_StopTimer(&p->hdlc);
|
|
|
|
lqr_StopTimer(p);
|
1998-06-25 22:33:31 +00:00
|
|
|
lcp_Setup(fsm2lcp(fp), 0);
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1998-08-07 18:42:51 +00:00
|
|
|
static int
|
|
|
|
E164ok(struct callback *cb, char *req, int sz)
|
|
|
|
{
|
|
|
|
char list[sizeof cb->msg], *next;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!strcmp(cb->msg, "*"))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
strncpy(list, cb->msg, sizeof list - 1);
|
|
|
|
list[sizeof list - 1] = '\0';
|
|
|
|
for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
|
|
|
|
len = strlen(next);
|
|
|
|
if (sz == len && !memcmp(list, req, sz))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
static void
|
1998-05-21 21:49:08 +00:00
|
|
|
LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
|
|
|
|
struct fsm_decode *dec)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Deal with incoming PROTO_LCP */
|
|
|
|
struct lcp *lcp = fsm2lcp(fp);
|
1998-08-07 18:42:51 +00:00
|
|
|
int type, length, sz, pos, op, callback_req;
|
1998-05-21 21:49:08 +00:00
|
|
|
u_int32_t magic, accmap;
|
1998-06-27 23:48:54 +00:00
|
|
|
u_short mtu, mru, proto;
|
1995-01-31 06:29:58 +00:00
|
|
|
struct lqrreq *req;
|
1997-12-03 10:23:54 +00:00
|
|
|
char request[20], desc[22];
|
1998-05-21 21:49:08 +00:00
|
|
|
struct mp *mp;
|
|
|
|
struct physical *p = link2physical(fp->link);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1999-08-08 17:36:10 +00:00
|
|
|
sz = op = callback_req = 0;
|
1998-08-07 18:42:51 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
while (plen >= sizeof(struct fsmconfig)) {
|
|
|
|
type = *cp;
|
|
|
|
length = cp[1];
|
1997-12-03 10:23:54 +00:00
|
|
|
|
2000-03-14 01:46:54 +00:00
|
|
|
snprintf(request, sizeof request, " %s[%d]", protoname(type), length);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1998-08-07 18:42:51 +00:00
|
|
|
if (length < 2) {
|
|
|
|
log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
switch (type) {
|
1998-05-21 21:49:08 +00:00
|
|
|
case TY_MRRU:
|
|
|
|
mp = &lcp->fsm.bundle->ncp.mp;
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohs(cp + 2, &mru);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s %u\n", request, mru);
|
|
|
|
|
|
|
|
switch (mode_type) {
|
|
|
|
case MODE_REQ:
|
|
|
|
if (mp->cfg.mrru) {
|
|
|
|
if (REJECTED(lcp, TY_MRRU))
|
|
|
|
/* Ignore his previous reject so that we REQ next time */
|
|
|
|
lcp->his_reject &= ~(1 << type);
|
|
|
|
|
2000-06-24 23:37:14 +00:00
|
|
|
if (mru < MIN_MRU) {
|
|
|
|
/* Push him up to MIN_MRU */
|
|
|
|
lcp->his_mrru = MIN_MRU;
|
1998-09-04 18:26:00 +00:00
|
|
|
memcpy(dec->nakend, cp, 2);
|
|
|
|
ua_htons(&lcp->his_mrru, dec->nakend + 2);
|
1998-05-21 21:49:08 +00:00
|
|
|
dec->nakend += 4;
|
|
|
|
} else {
|
2000-06-24 23:37:14 +00:00
|
|
|
lcp->his_mrru = mru;
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->ackend, cp, 4);
|
|
|
|
dec->ackend += 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
goto reqreject;
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
|
|
|
if (mp->cfg.mrru) {
|
|
|
|
if (REJECTED(lcp, TY_MRRU))
|
|
|
|
/* Must have changed his mind ! */
|
|
|
|
lcp->his_reject &= ~(1 << type);
|
|
|
|
|
|
|
|
if (mru > MAX_MRU)
|
|
|
|
lcp->want_mrru = MAX_MRU;
|
|
|
|
else if (mru < MIN_MRU)
|
|
|
|
lcp->want_mrru = MIN_MRU;
|
|
|
|
else
|
|
|
|
lcp->want_mrru = mru;
|
|
|
|
}
|
|
|
|
/* else we honour our config and don't send the suggested REQ */
|
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
|
|
|
lcp->his_reject |= (1 << type);
|
|
|
|
lcp->want_mrru = 0; /* Ah well, no multilink :-( */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_MRU:
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohs(cp + 2, &mru);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s %d\n", request, mru);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
mtu = lcp->fsm.bundle->cfg.mtu;
|
|
|
|
if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) {
|
|
|
|
/* Push him up to MTU or MIN_MRU */
|
|
|
|
lcp->his_mru = mru < mtu ? mtu : MIN_MRU;
|
1998-09-04 18:26:00 +00:00
|
|
|
memcpy(dec->nakend, cp, 2);
|
|
|
|
ua_htons(&lcp->his_mru, dec->nakend + 2);
|
1998-05-21 21:49:08 +00:00
|
|
|
dec->nakend += 4;
|
|
|
|
} else {
|
|
|
|
lcp->his_mru = mtu ? mtu : mru;
|
|
|
|
memcpy(dec->ackend, cp, 4);
|
|
|
|
dec->ackend += 4;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (mru > MAX_MRU)
|
|
|
|
lcp->want_mru = MAX_MRU;
|
|
|
|
else if (mru < MIN_MRU)
|
|
|
|
lcp->want_mru = MIN_MRU;
|
|
|
|
else
|
|
|
|
lcp->want_mru = mru;
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_ACCMAP:
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohl(cp + 2, &accmap);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_accmap = accmap;
|
1999-04-11 08:51:04 +00:00
|
|
|
memcpy(dec->ackend, cp, 6);
|
|
|
|
dec->ackend += 6;
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
1999-04-11 08:51:04 +00:00
|
|
|
lcp->want_accmap = accmap;
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
1999-04-11 08:51:04 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_AUTHPROTO:
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohs(cp + 2, &proto);
|
1999-02-18 00:52:15 +00:00
|
|
|
log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
|
|
|
|
Auth2Nam(proto, length > 4 ? cp[4] : 0));
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
|
|
|
switch (proto) {
|
|
|
|
case PROTO_PAP:
|
|
|
|
if (length != 4) {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, " Bad length!\n");
|
1995-01-31 06:29:58 +00:00
|
|
|
goto reqreject;
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
if (IsAccepted(lcp->cfg.pap)) {
|
|
|
|
lcp->his_auth = proto;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->his_authtype = 0;
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
1999-02-18 00:52:15 +00:00
|
|
|
} else if (IsAccepted(lcp->cfg.chap05)) {
|
1998-05-21 21:49:08 +00:00
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 5;
|
|
|
|
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
|
|
|
|
*dec->nakend++ = (unsigned char) PROTO_CHAP;
|
|
|
|
*dec->nakend++ = 0x05;
|
1999-02-18 00:52:15 +00:00
|
|
|
#ifdef HAVE_DES
|
|
|
|
} else if (IsAccepted(lcp->cfg.chap80nt) ||
|
|
|
|
IsAccepted(lcp->cfg.chap80lm)) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 5;
|
|
|
|
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
|
|
|
|
*dec->nakend++ = (unsigned char) PROTO_CHAP;
|
|
|
|
*dec->nakend++ = 0x80;
|
|
|
|
#endif
|
1995-01-31 06:29:58 +00:00
|
|
|
} else
|
|
|
|
goto reqreject;
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case PROTO_CHAP:
|
1999-02-18 00:52:15 +00:00
|
|
|
if (length != 5) {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, " Bad length!\n");
|
1995-01-31 06:29:58 +00:00
|
|
|
goto reqreject;
|
|
|
|
}
|
1999-02-18 00:52:15 +00:00
|
|
|
if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05))
|
1997-09-25 00:52:37 +00:00
|
|
|
#ifdef HAVE_DES
|
1999-02-18 00:52:15 +00:00
|
|
|
|| (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
|
|
|
|
(IsAccepted(lcp->cfg.chap80lm))))
|
1997-09-25 00:52:37 +00:00
|
|
|
#endif
|
1999-02-18 00:52:15 +00:00
|
|
|
) {
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_auth = proto;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->his_authtype = cp[4];
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
1998-10-17 12:28:02 +00:00
|
|
|
} else {
|
|
|
|
#ifndef HAVE_DES
|
1999-02-18 00:52:15 +00:00
|
|
|
if (cp[4] == 0x80)
|
|
|
|
log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
|
|
|
|
else
|
1998-10-17 12:28:02 +00:00
|
|
|
#endif
|
1999-02-18 00:52:15 +00:00
|
|
|
if (cp[4] != 0x05)
|
|
|
|
log_Printf(LogWARN, "%s not supported\n",
|
|
|
|
Auth2Nam(PROTO_CHAP, cp[4]));
|
|
|
|
|
|
|
|
if (IsAccepted(lcp->cfg.chap05)) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 5;
|
|
|
|
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
|
|
|
|
*dec->nakend++ = (unsigned char) PROTO_CHAP;
|
|
|
|
*dec->nakend++ = 0x05;
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
} else if (IsAccepted(lcp->cfg.chap80nt) ||
|
|
|
|
IsAccepted(lcp->cfg.chap80lm)) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 5;
|
|
|
|
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
|
|
|
|
*dec->nakend++ = (unsigned char) PROTO_CHAP;
|
|
|
|
*dec->nakend++ = 0x80;
|
|
|
|
#endif
|
|
|
|
} else if (IsAccepted(lcp->cfg.pap)) {
|
1998-10-17 12:28:02 +00:00
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 4;
|
|
|
|
*dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
|
|
|
|
*dec->nakend++ = (unsigned char) PROTO_PAP;
|
|
|
|
} else
|
|
|
|
goto reqreject;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
default:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
|
1997-12-07 23:55:29 +00:00
|
|
|
request, proto);
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->nakend, cp, length);
|
|
|
|
dec->nakend += length;
|
1997-08-25 00:29:32 +00:00
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
1997-12-07 23:55:29 +00:00
|
|
|
switch (proto) {
|
|
|
|
case PROTO_PAP:
|
1999-02-18 00:52:15 +00:00
|
|
|
if (IsEnabled(lcp->cfg.pap)) {
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_auth = PROTO_PAP;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->want_authtype = 0;
|
|
|
|
} else {
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
|
|
|
|
lcp->his_reject |= (1 << type);
|
1997-12-07 23:55:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROTO_CHAP:
|
1999-02-18 00:52:15 +00:00
|
|
|
if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) {
|
|
|
|
lcp->want_auth = PROTO_CHAP;
|
|
|
|
lcp->want_authtype = 0x05;
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
} else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
|
|
|
|
IsEnabled(lcp->cfg.chap80lm))) {
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_auth = PROTO_CHAP;
|
1999-02-18 00:52:15 +00:00
|
|
|
lcp->want_authtype = 0x80;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifndef HAVE_DES
|
|
|
|
if (cp[4] == 0x80)
|
|
|
|
log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
|
|
|
|
" without DES)\n");
|
|
|
|
else
|
|
|
|
#endif
|
Allow control over the number of ConfigREQ & TermREQ attempts
that are made in each of the FSMs (LCP, CCP & IPCP) and the
number of REQs/Challenges for PAP/CHAP by accepting more arguments
in the ``set {c,ip,l}cpretry'' and ``set {ch,p}apretry'' commands.
Change the non-convergence thresholds to 3 times the number of configured
REQ tries (rather than the previous fixed ``10''). We now notice
repeated NAKs and REJs rather than just REQs.
Don't suggest that CHAP 0x05 isn't supported when it's not configured.
Fix some bugs that expose themselves with smaller numbers of retries:
o Handle instantaneous disconnects (set device /dev/null) correctly
by stopping all fsm timers in fsm2initial.
o Don't forget to uu_unlock() devices that are files but are not
ttys (set device /dev/zero).
Fix a *HORRENDOUS* bug in RFC1661 (already fixed for an Open event in state
``Closed''):
According to the state transition table, a RCR+ or RCR- received in
the ``Stopped'' state are supposed to InitRestartCounter, SendConfigReq
and SendConfig{Ack,Nak}. However, in ``Stopped'', we haven't yet
done a TLS (or the last thing we did is a TLF). We must therefore
do the TLS at this point !
This was never noticed before because LCP and CCP used not use
LayerStart() for anything interesting, and IPCP tends to go into
Stopped then get a Down because of an LCP RTR rather than getting a
RCR again.
1999-02-26 21:28:14 +00:00
|
|
|
log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
|
|
|
|
Auth2Nam(PROTO_CHAP, cp[4]),
|
|
|
|
#ifdef HAVE_DES
|
|
|
|
cp[4] == 0x80 ? "configured" :
|
|
|
|
#endif
|
|
|
|
"supported");
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1997-12-07 23:55:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* We've been NAK'd with something we don't understand :-( */
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1997-12-07 23:55:29 +00:00
|
|
|
break;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_QUALPROTO:
|
1998-05-21 21:49:08 +00:00
|
|
|
req = (struct lqrreq *)cp;
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, "%s proto %x, interval %lums\n",
|
|
|
|
request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
|
1995-01-31 06:29:58 +00:00
|
|
|
goto reqreject;
|
|
|
|
else {
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_lqrperiod = ntohl(req->period);
|
1998-06-27 23:48:54 +00:00
|
|
|
if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
|
|
|
|
lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
|
1998-05-21 21:49:08 +00:00
|
|
|
req->period = htonl(lcp->his_lqrperiod);
|
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_MAGICNUM:
|
1998-09-04 18:26:00 +00:00
|
|
|
ua_ntohl(cp + 2, &magic);
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_magic) {
|
1997-06-01 03:43:26 +00:00
|
|
|
/* Validate magic number */
|
1998-05-21 21:49:08 +00:00
|
|
|
if (magic == lcp->want_magic) {
|
|
|
|
log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
|
|
|
|
(u_long)magic, ++lcp->LcpFailedMagic);
|
|
|
|
lcp->want_magic = GenerateMagic();
|
|
|
|
memcpy(dec->nakend, cp, 6);
|
|
|
|
dec->nakend += 6;
|
|
|
|
ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
|
1997-09-22 02:51:24 +00:00
|
|
|
sigpause(0);
|
1997-08-25 00:29:32 +00:00
|
|
|
} else {
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_magic = magic;
|
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
|
|
|
lcp->LcpFailedMagic = 0;
|
1997-08-25 00:29:32 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
} else {
|
|
|
|
goto reqreject;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
|
|
|
|
lcp->want_magic = GenerateMagic();
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
|
|
|
|
lcp->want_magic = 0;
|
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_PROTOCOMP:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s\n", request);
|
1995-01-31 06:29:58 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (IsAccepted(lcp->cfg.protocomp)) {
|
|
|
|
lcp->his_protocomp = 1;
|
|
|
|
memcpy(dec->ackend, cp, 2);
|
|
|
|
dec->ackend += 2;
|
1997-08-25 00:29:32 +00:00
|
|
|
} else {
|
1995-01-31 06:29:58 +00:00
|
|
|
#ifdef OLDMST
|
1999-05-09 20:02:29 +00:00
|
|
|
/* MorningStar before v1.3 needs NAK */
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->nakend, cp, 2);
|
|
|
|
dec->nakend += 2;
|
1995-01-31 06:29:58 +00:00
|
|
|
#else
|
1998-05-21 21:49:08 +00:00
|
|
|
goto reqreject;
|
1995-01-31 06:29:58 +00:00
|
|
|
#endif
|
1997-08-25 00:29:32 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_protocomp = 0;
|
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_ACFCOMP:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s\n", request);
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (IsAccepted(lcp->cfg.acfcomp)) {
|
|
|
|
lcp->his_acfcomp = 1;
|
|
|
|
memcpy(dec->ackend, cp, 2);
|
|
|
|
dec->ackend += 2;
|
1997-08-25 00:29:32 +00:00
|
|
|
} else {
|
1995-01-31 06:29:58 +00:00
|
|
|
#ifdef OLDMST
|
1999-05-09 20:02:29 +00:00
|
|
|
/* MorningStar before v1.3 needs NAK */
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->nakend, cp, 2);
|
|
|
|
dec->nakend += 2;
|
1995-01-31 06:29:58 +00:00
|
|
|
#else
|
1998-05-21 21:49:08 +00:00
|
|
|
goto reqreject;
|
1995-01-31 06:29:58 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->want_acfcomp = 0;
|
|
|
|
lcp->his_reject |= (1 << type);
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
case TY_SDP:
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s\n", request);
|
|
|
|
switch (mode_type) {
|
|
|
|
case MODE_REQ:
|
|
|
|
case MODE_NAK:
|
|
|
|
case MODE_REJ:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1998-08-07 18:42:51 +00:00
|
|
|
case TY_CALLBACK:
|
|
|
|
if (length == 2)
|
|
|
|
op = CALLBACK_NONE;
|
|
|
|
else
|
|
|
|
op = (int)cp[2];
|
|
|
|
sz = length - 3;
|
|
|
|
switch (op) {
|
|
|
|
case CALLBACK_AUTH:
|
|
|
|
log_Printf(LogLCP, "%s Auth\n", request);
|
|
|
|
break;
|
|
|
|
case CALLBACK_DIALSTRING:
|
|
|
|
log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
|
|
|
|
break;
|
|
|
|
case CALLBACK_LOCATION:
|
|
|
|
log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
|
|
|
|
break;
|
|
|
|
case CALLBACK_E164:
|
|
|
|
log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
|
|
|
|
break;
|
|
|
|
case CALLBACK_NAME:
|
|
|
|
log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
|
|
|
|
break;
|
|
|
|
case CALLBACK_CBCP:
|
|
|
|
log_Printf(LogLCP, "%s CBCP\n", request);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log_Printf(LogLCP, "%s ???\n", request);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mode_type) {
|
|
|
|
case MODE_REQ:
|
|
|
|
callback_req = 1;
|
|
|
|
if (p->type != PHYS_DIRECT)
|
|
|
|
goto reqreject;
|
|
|
|
if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
|
|
|
|
(op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
|
|
|
|
(op != CALLBACK_E164 ||
|
|
|
|
E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
|
|
|
|
lcp->his_callback.opmask = CALLBACK_BIT(op);
|
|
|
|
if (sz > sizeof lcp->his_callback.msg - 1) {
|
|
|
|
sz = sizeof lcp->his_callback.msg - 1;
|
|
|
|
log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
|
|
|
|
}
|
|
|
|
memcpy(lcp->his_callback.msg, cp + 3, sz);
|
|
|
|
lcp->his_callback.msg[sz] = '\0';
|
|
|
|
memcpy(dec->ackend, cp, sz + 3);
|
|
|
|
dec->ackend += sz + 3;
|
|
|
|
} else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
|
|
|
|
p->link.lcp.auth_ineed) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 3;
|
|
|
|
*dec->nakend++ = CALLBACK_AUTH;
|
|
|
|
} else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 3;
|
|
|
|
*dec->nakend++ = CALLBACK_CBCP;
|
|
|
|
} else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 3;
|
|
|
|
*dec->nakend++ = CALLBACK_E164;
|
|
|
|
} else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
|
|
|
|
log_Printf(LogWARN, "Cannot insist on auth callback without"
|
|
|
|
" PAP or CHAP enabled !\n");
|
|
|
|
*dec->nakend++ = *cp;
|
|
|
|
*dec->nakend++ = 2;
|
|
|
|
} else
|
|
|
|
goto reqreject;
|
|
|
|
break;
|
|
|
|
case MODE_NAK:
|
1999-01-12 21:50:20 +00:00
|
|
|
/* We don't do what he NAKs with, we do things in our preferred order */
|
1998-08-07 18:42:51 +00:00
|
|
|
if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
|
|
|
|
lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
|
|
|
|
else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
|
|
|
|
lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
|
|
|
|
else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
|
|
|
|
lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
|
|
|
|
if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
|
|
|
|
log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
|
|
|
|
lcp->want_callback.opmask = 0;
|
|
|
|
} else if (!lcp->want_callback.opmask) {
|
|
|
|
log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
|
|
|
|
fsm_Close(&lcp->fsm);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_REJ:
|
|
|
|
if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
|
|
|
|
lcp->his_reject |= (1 << type);
|
|
|
|
lcp->want_callback.opmask = 0;
|
|
|
|
} else {
|
|
|
|
log_Printf(LogPHASE, "Peer rejected *required* callback\n");
|
|
|
|
fsm_Close(&lcp->fsm);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case TY_SHORTSEQ:
|
|
|
|
mp = &lcp->fsm.bundle->ncp.mp;
|
|
|
|
log_Printf(LogLCP, "%s\n", request);
|
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
switch (mode_type) {
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REQ:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
|
|
|
|
lcp->his_shortseq = 1;
|
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
|
|
|
} else
|
|
|
|
goto reqreject;
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_NAK:
|
1998-05-21 21:49:08 +00:00
|
|
|
/*
|
|
|
|
* He's trying to get us to ask for short sequence numbers.
|
|
|
|
* We ignore the NAK and honour our configuration file instead.
|
|
|
|
*/
|
|
|
|
break;
|
1995-01-31 06:29:58 +00:00
|
|
|
case MODE_REJ:
|
1998-05-21 21:49:08 +00:00
|
|
|
lcp->his_reject |= (1 << type);
|
|
|
|
lcp->want_shortseq = 0; /* For when we hit MP */
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
case TY_ENDDISC:
|
1999-06-09 20:27:26 +00:00
|
|
|
mp = &lcp->fsm.bundle->ncp.mp;
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s %s\n", request,
|
|
|
|
mp_Enddisc(cp[2], cp + 3, length - 3));
|
|
|
|
switch (mode_type) {
|
|
|
|
case MODE_REQ:
|
|
|
|
if (!p) {
|
|
|
|
log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
|
|
|
|
goto reqreject;
|
1999-06-09 16:54:04 +00:00
|
|
|
} else if (!IsAccepted(mp->cfg.negenddisc))
|
|
|
|
goto reqreject;
|
|
|
|
else if (length-3 < sizeof p->dl->peer.enddisc.address &&
|
1998-05-21 21:49:08 +00:00
|
|
|
cp[2] <= MAX_ENDDISC_CLASS) {
|
|
|
|
p->dl->peer.enddisc.class = cp[2];
|
|
|
|
p->dl->peer.enddisc.len = length-3;
|
|
|
|
memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
|
|
|
|
p->dl->peer.enddisc.address[length - 3] = '\0';
|
|
|
|
/* XXX: If mp->active, compare and NAK with mp->peer ? */
|
|
|
|
memcpy(dec->ackend, cp, length);
|
|
|
|
dec->ackend += length;
|
|
|
|
} else {
|
|
|
|
if (cp[2] > MAX_ENDDISC_CLASS)
|
|
|
|
log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
|
|
|
|
cp[2]);
|
|
|
|
else
|
1998-06-27 23:48:54 +00:00
|
|
|
log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
|
|
|
|
(long)(sizeof p->dl->peer.enddisc.address - 1));
|
1998-05-21 21:49:08 +00:00
|
|
|
goto reqreject;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1999-06-09 16:54:04 +00:00
|
|
|
case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
|
1998-05-21 21:49:08 +00:00
|
|
|
case MODE_REJ:
|
|
|
|
lcp->his_reject |= (1 << type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1995-01-31 06:29:58 +00:00
|
|
|
default:
|
1997-12-24 09:29:17 +00:00
|
|
|
sz = (sizeof desc - 2) / 2;
|
1997-12-03 10:23:54 +00:00
|
|
|
if (sz > length - 2)
|
|
|
|
sz = length - 2;
|
|
|
|
pos = 0;
|
|
|
|
desc[0] = sz ? ' ' : '\0';
|
|
|
|
for (pos = 0; sz--; pos++)
|
|
|
|
sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
|
|
|
|
|
1998-05-21 21:49:08 +00:00
|
|
|
log_Printf(LogLCP, "%s%s\n", request, desc);
|
1997-12-03 10:23:54 +00:00
|
|
|
|
1997-11-08 00:28:11 +00:00
|
|
|
if (mode_type == MODE_REQ) {
|
1997-12-03 10:23:54 +00:00
|
|
|
reqreject:
|
1998-05-21 21:49:08 +00:00
|
|
|
if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
|
|
|
|
length = sizeof dec->rej - (dec->rejend - dec->rej);
|
|
|
|
log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
|
1997-12-03 10:23:54 +00:00
|
|
|
cp[1], length);
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
memcpy(dec->rejend, cp, length);
|
|
|
|
dec->rejend += length;
|
|
|
|
lcp->my_reject |= (1 << type);
|
1997-12-03 10:23:54 +00:00
|
|
|
if (length != cp[1])
|
1998-05-21 21:49:08 +00:00
|
|
|
length = 0; /* force our way out of the loop */
|
1995-02-26 12:18:08 +00:00
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
plen -= length;
|
|
|
|
cp += length;
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
|
|
|
|
if (mode_type != MODE_NOP) {
|
1998-08-07 18:42:51 +00:00
|
|
|
if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
|
|
|
|
p->dl->cfg.callback.opmask && !callback_req &&
|
|
|
|
!(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
|
|
|
|
/* We *REQUIRE* that the peer requests callback */
|
|
|
|
*dec->nakend++ = TY_CALLBACK;
|
|
|
|
*dec->nakend++ = 3;
|
|
|
|
if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
|
|
|
|
p->link.lcp.auth_ineed)
|
|
|
|
*dec->nakend++ = CALLBACK_AUTH;
|
|
|
|
else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
|
|
|
|
*dec->nakend++ = CALLBACK_CBCP;
|
|
|
|
else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
|
|
|
|
*dec->nakend++ = CALLBACK_E164;
|
|
|
|
else {
|
|
|
|
log_Printf(LogWARN, "Cannot insist on auth callback without"
|
|
|
|
" PAP or CHAP enabled !\n");
|
|
|
|
dec->nakend[-1] = 2; /* XXX: Silly ! */
|
|
|
|
}
|
|
|
|
}
|
1998-05-21 21:49:08 +00:00
|
|
|
if (dec->rejend != dec->rej) {
|
|
|
|
/* rejects are preferred */
|
|
|
|
dec->ackend = dec->ack;
|
|
|
|
dec->nakend = dec->nak;
|
|
|
|
} else if (dec->nakend != dec->nak)
|
|
|
|
/* then NAKs */
|
|
|
|
dec->ackend = dec->ack;
|
|
|
|
}
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|
|
|
|
|
1999-05-08 11:07:56 +00:00
|
|
|
extern struct mbuf *
|
|
|
|
lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
1995-01-31 06:29:58 +00:00
|
|
|
{
|
1998-05-21 21:49:08 +00:00
|
|
|
/* Got PROTO_LCP from link */
|
1999-12-20 20:29:47 +00:00
|
|
|
m_settype(bp, MB_LCPIN);
|
1999-05-08 11:07:56 +00:00
|
|
|
fsm_Input(&l->lcp.fsm, bp);
|
|
|
|
return NULL;
|
1995-01-31 06:29:58 +00:00
|
|
|
}
|