Make the way FSM options are processed easier to read by using structures

instead of u_char *.

The changes are cosmetic except:

  RecvConfigAck() now displays the options that are being ACK'd
  Huge (bogus) options sent from the peer won't cause an infinite loop
  SendIdent and ReceiveIdent are displayed consistenlty with other FSM data
  LCP AUTHPROTO options that aren't understood are NAK'd, not REJ'd
This commit is contained in:
Brian Somers 2002-04-16 23:57:09 +00:00
parent 28395f9543
commit ff360cc91b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=94894
12 changed files with 744 additions and 729 deletions

View File

@ -80,7 +80,7 @@
static void CcpSendConfigReq(struct fsm *);
static void CcpSentTerminateReq(struct fsm *);
static void CcpSendTerminateAck(struct fsm *, u_char);
static void CcpDecodeConfig(struct fsm *, u_char *, int, int,
static void CcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
struct fsm_decode *);
static void CcpLayerStart(struct fsm *);
static void CcpLayerFinish(struct fsm *);
@ -276,7 +276,7 @@ ccp_Setup(struct ccp *ccp)
ccp->reset_sent = ccp->last_reset = -1;
ccp->in.algorithm = ccp->out.algorithm = -1;
ccp->in.state = ccp->out.state = NULL;
ccp->in.opt.id = -1;
ccp->in.opt.hdr.id = -1;
ccp->out.opt = NULL;
ccp->his_reject = ccp->my_reject = 0;
ccp->uncompout = ccp->compout = 0;
@ -361,26 +361,26 @@ CcpSendConfigReq(struct fsm *fp)
if (!alloc)
for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next)
if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f)
if ((*o)->val.hdr.id == algorithm[f]->id && (*o)->algorithm == f)
break;
if (alloc || *o == NULL) {
*o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt));
(*o)->val.id = algorithm[f]->id;
(*o)->val.len = 2;
(*o)->val.hdr.id = algorithm[f]->id;
(*o)->val.hdr.len = 2;
(*o)->next = NULL;
(*o)->algorithm = f;
(*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg);
}
if (cp + (*o)->val.len > buff + sizeof buff) {
if (cp + (*o)->val.hdr.len > buff + sizeof buff) {
log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name);
break;
}
memcpy(cp, &(*o)->val, (*o)->val.len);
cp += (*o)->val.len;
memcpy(cp, &(*o)->val, (*o)->val.hdr.len);
cp += (*o)->val.hdr.len;
ccp->my_proto = (*o)->val.id;
ccp->my_proto = (*o)->val.hdr.id;
ccp->out.algorithm = f;
if (alloc)
@ -555,93 +555,79 @@ CcpLayerUp(struct fsm *fp)
}
static void
CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
struct fsm_decode *dec)
{
/* Deal with incoming data */
struct ccp *ccp = fsm2ccp(fp);
int type, length, f;
const char *end;
int f;
const char *disp;
struct fsm_opt *opt;
if (mode_type == MODE_REQ)
ccp->in.algorithm = -1; /* In case we've received two REQs in a row */
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (length == 0) {
log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name);
while (end - cp >= sizeof(opt->hdr)) {
if ((opt = fsm_readopt(&cp)) == NULL)
break;
}
if (length > sizeof(struct lcp_opt)) {
length = sizeof(struct lcp_opt);
log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n",
fp->link->name, length);
}
for (f = NALGORITHMS-1; f > -1; f--)
if (algorithm[f]->id == type)
if (algorithm[f]->id == opt->hdr.id)
break;
end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp);
if (end == NULL)
end = "";
disp = f == -1 ? "" : (*algorithm[f]->Disp)(opt);
if (disp == NULL)
disp = "";
log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end);
log_Printf(LogCCP, " %s[%d] %s\n", protoname(opt->hdr.id),
opt->hdr.len, disp);
if (f == -1) {
/* Don't understand that :-( */
if (mode_type == MODE_REQ) {
ccp->my_reject |= (1 << type);
memcpy(dec->rejend, cp, length);
dec->rejend += length;
ccp->my_reject |= (1 << opt->hdr.id);
fsm_rej(dec, opt);
}
} else {
struct ccp_opt *o;
switch (mode_type) {
case MODE_REQ:
if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) &&
if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) &&
(*algorithm[f]->Usable)(fp) &&
ccp->in.algorithm == -1) {
memcpy(&ccp->in.opt, cp, length);
memcpy(&ccp->in.opt, opt, opt->hdr.len);
switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) {
case MODE_REJ:
memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len);
dec->rejend += ccp->in.opt.len;
fsm_rej(dec, &ccp->in.opt);
break;
case MODE_NAK:
memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len);
dec->nakend += ccp->in.opt.len;
fsm_nak(dec, &ccp->in.opt);
break;
case MODE_ACK:
memcpy(dec->ackend, cp, length);
dec->ackend += length;
ccp->his_proto = type;
fsm_ack(dec, &ccp->in.opt);
ccp->his_proto = opt->hdr.id;
ccp->in.algorithm = f; /* This one'll do :-) */
break;
}
} else {
memcpy(dec->rejend, cp, length);
dec->rejend += length;
}
break;
} else {
fsm_rej(dec, opt);
}
break;
case MODE_NAK:
for (o = ccp->out.opt; o != NULL; o = o->next)
if (o->val.id == cp[0])
if (o->val.hdr.id == opt->hdr.id)
break;
if (o == NULL)
log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent"
" option\n", fp->link->name);
else {
memcpy(&o->val, cp, length);
memcpy(&o->val, opt, opt->hdr.len);
if ((*algorithm[f]->o.Set)(&o->val, &ccp->cfg) == MODE_ACK)
ccp->my_proto = algorithm[f]->id;
else {
ccp->his_reject |= (1 << type);
ccp->my_proto = -1;
ccp->his_reject |= (1 << opt->hdr.id);
ccp->my_proto = -1;
if (algorithm[f]->Required(fp)) {
log_Printf(LogWARN, "%s: Cannot understand peers (required)"
" %s negotiation\n", fp->link->name,
@ -652,33 +638,21 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
}
break;
case MODE_REJ:
ccp->his_reject |= (1 << type);
ccp->my_proto = -1;
ccp->his_reject |= (1 << opt->hdr.id);
ccp->my_proto = -1;
if (algorithm[f]->Required(fp)) {
log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n",
fp->link->name, protoname(algorithm[f]->id));
fsm_Close(&fp->link->lcp.fsm);
}
break;
break;
}
}
plen -= cp[1];
cp += cp[1];
}
if (mode_type != MODE_NOP) {
if (dec->rejend != dec->rej) {
/* rejects are preferred */
dec->ackend = dec->ack;
dec->nakend = dec->nak;
if (ccp->in.state == NULL) {
ccp->his_proto = -1;
ccp->in.algorithm = -1;
}
} else if (dec->nakend != dec->nak) {
/* then NAKs */
dec->ackend = dec->ack;
fsm_opt_normalise(dec);
if (dec->rejend != dec->rej || dec->nakend != dec->nak) {
if (ccp->in.state == NULL) {
ccp->his_proto = -1;
ccp->in.algorithm = -1;

View File

@ -85,7 +85,7 @@ struct ccp_config {
struct ccp_opt {
struct ccp_opt *next;
int algorithm;
struct lcp_opt val;
struct fsm_opt val;
};
struct ccp {
@ -100,7 +100,7 @@ struct ccp {
struct {
int algorithm; /* Algorithm in use */
void *state; /* Returned by implementations Init() */
struct lcp_opt opt; /* Set by implementation's OptInit() */
struct fsm_opt opt; /* Set by implementation's OptInit() */
} in;
struct {
@ -123,12 +123,12 @@ struct ccp {
struct ccp_algorithm {
int id;
int Neg; /* ccp_config neg array item */
const char *(*Disp)(struct lcp_opt *); /* Use result immediately ! */
const char *(*Disp)(struct fsm_opt *); /* Use result immediately ! */
int (*Usable)(struct fsm *); /* Ok to negotiate ? */
int (*Required)(struct fsm *); /* Must negotiate ? */
struct {
int (*Set)(struct lcp_opt *, const struct ccp_config *);
void *(*Init)(struct lcp_opt *);
int (*Set)(struct fsm_opt *, const struct ccp_config *);
void *(*Init)(struct fsm_opt *);
void (*Term)(void *);
void (*Reset)(void *);
struct mbuf *(*Read)(void *, struct ccp *, u_short *, struct mbuf *);
@ -136,9 +136,9 @@ struct ccp_algorithm {
} i;
struct {
int MTUOverhead;
void (*OptInit)(struct lcp_opt *, const struct ccp_config *);
int (*Set)(struct lcp_opt *, const struct ccp_config *);
void *(*Init)(struct lcp_opt *);
void (*OptInit)(struct fsm_opt *, const struct ccp_config *);
int (*Set)(struct fsm_opt *, const struct ccp_config *);
void *(*Init)(struct fsm_opt *);
void (*Term)(void *);
int (*Reset)(void *);
struct mbuf *(*Write)(void *, struct ccp *, struct link *, int, u_short *,

View File

@ -164,7 +164,7 @@
#define NEG_MPPE 54
#define NEG_CHAP81 55
const char Version[] = "3.0.1";
const char Version[] = "3.0.2";
static int ShowCommand(struct cmdargs const *);
static int TerminalCommand(struct cmdargs const *);

View File

@ -436,7 +436,7 @@ DeflateDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
}
static const char *
DeflateDispOpts(struct lcp_opt *o)
DeflateDispOpts(struct fsm_opt *o)
{
static char disp[7]; /* Must be used immediately */
@ -445,17 +445,17 @@ DeflateDispOpts(struct lcp_opt *o)
}
static void
DeflateInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
DeflateInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
{
o->len = 4;
o->hdr.len = 4;
o->data[0] = ((cfg->deflate.out.winsize - 8) << 4) + 8;
o->data[1] = '\0';
}
static int
DeflateSetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
DeflateSetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
{
if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
if (o->hdr.len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
return MODE_REJ;
if ((o->data[0] >> 4) + 8 > 15) {
@ -467,11 +467,11 @@ DeflateSetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
}
static int
DeflateSetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
DeflateSetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
{
int want;
if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
if (o->hdr.len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0')
return MODE_REJ;
want = (o->data[0] >> 4) + 8;
@ -488,7 +488,7 @@ DeflateSetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
}
static void *
DeflateInitInput(struct lcp_opt *o)
DeflateInitInput(struct fsm_opt *o)
{
struct deflate_state *state;
@ -511,7 +511,7 @@ DeflateInitInput(struct lcp_opt *o)
}
static void *
DeflateInitOutput(struct lcp_opt *o)
DeflateInitOutput(struct fsm_opt *o)
{
struct deflate_state *state;

View File

@ -170,7 +170,7 @@ static void
NewState(struct fsm *fp, int new)
{
log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",
fp->link->name, State2Nam(fp->state), State2Nam(new));
fp->link->name, State2Nam(fp->state), State2Nam(new));
if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
timer_Stop(&fp->StoppedTimer);
fp->state = new;
@ -201,8 +201,8 @@ fsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count,
case CODE_CONFIGACK:
case CODE_CONFIGREJ:
case CODE_CONFIGNAK:
(*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);
if (count < sizeof(struct fsmconfig))
(*fp->fn->DecodeConfig)(fp, ptr, ptr + count, MODE_NOP, NULL);
if (count < sizeof(struct fsm_opt_hdr))
log_Printf(fp->LogLevel, " [EMPTY]\n");
break;
}
@ -470,16 +470,29 @@ FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
struct fsm_decode dec;
int plen, flen;
int ackaction = 0;
u_char *cp;
bp = m_pullup(bp);
plen = m_length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",
fp->link->name, plen, flen);
fp->link->name, plen, flen);
m_freem(bp);
return;
}
dec.ackend = dec.ack;
dec.nakend = dec.nak;
dec.rejend = dec.rej;
cp = MBUF_CTOP(bp);
(*fp->fn->DecodeConfig)(fp, cp, cp + flen, MODE_REQ, &dec);
if (flen < sizeof(struct fsm_opt_hdr))
log_Printf(fp->LogLevel, " [EMPTY]\n");
if (dec.nakend == dec.nak && dec.rejend == dec.rej)
ackaction = 1;
/* Check and process easy case */
switch (fp->state) {
case ST_INITIAL:
@ -511,28 +524,12 @@ FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
case ST_STOPPING:
m_freem(bp);
return;
case ST_OPENED:
(*fp->fn->LayerDown)(fp);
break;
}
bp = m_pullup(bp);
dec.ackend = dec.ack;
dec.nakend = dec.nak;
dec.rejend = dec.rej;
(*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);
if (flen < sizeof(struct fsmconfig))
log_Printf(fp->LogLevel, " [EMPTY]\n");
if (dec.nakend == dec.nak && dec.rejend == dec.rej)
ackaction = 1;
switch (fp->state) {
case ST_STOPPED:
FsmInitRestartCounter(fp, FSM_REQ_TIMER);
/* Fall through */
FsmSendConfigReq(fp);
break;
case ST_OPENED:
(*fp->fn->LayerDown)(fp);
FsmSendConfigReq(fp);
break;
}
@ -609,6 +606,26 @@ static void
FsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
/* RCA */
{
struct fsm_decode dec;
int plen, flen;
u_char *cp;
plen = m_length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
m_freem(bp);
return;
}
bp = m_pullup(bp);
dec.ackend = dec.ack;
dec.nakend = dec.nak;
dec.rejend = dec.rej;
cp = MBUF_CTOP(bp);
(*fp->fn->DecodeConfig)(fp, cp, cp + flen, MODE_ACK, &dec);
if (flen < sizeof(struct fsm_opt_hdr))
log_Printf(fp->LogLevel, " [EMPTY]\n");
switch (fp->state) {
case ST_CLOSED:
case ST_STOPPED:
@ -654,6 +671,7 @@ FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
struct fsm_decode dec;
int plen, flen;
u_char *cp;
plen = m_length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
@ -687,8 +705,9 @@ FsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
dec.ackend = dec.ack;
dec.nakend = dec.nak;
dec.rejend = dec.rej;
(*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);
if (flen < sizeof(struct fsmconfig))
cp = MBUF_CTOP(bp);
(*fp->fn->DecodeConfig)(fp, cp, cp + flen, MODE_NAK, &dec);
if (flen < sizeof(struct fsm_opt_hdr))
log_Printf(fp->LogLevel, " [EMPTY]\n");
switch (fp->state) {
@ -782,6 +801,7 @@ FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
{
struct fsm_decode dec;
int plen, flen;
u_char *cp;
plen = m_length(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
@ -817,8 +837,9 @@ FsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
dec.ackend = dec.ack;
dec.nakend = dec.nak;
dec.rejend = dec.rej;
(*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);
if (flen < sizeof(struct fsmconfig))
cp = MBUF_CTOP(bp);
(*fp->fn->DecodeConfig)(fp, cp, cp + flen, MODE_REJ, &dec);
if (flen < sizeof(struct fsm_opt_hdr))
log_Printf(fp->LogLevel, " [EMPTY]\n");
switch (fp->state) {
@ -1052,12 +1073,12 @@ fsm_Input(struct fsm *fp, struct mbuf *bp)
if (lh.id != fp->reqid && codep->check_reqid &&
Enabled(fp->bundle, OPT_IDCHECK)) {
log_Printf(fp->LogLevel, "%s: Recv%s(%d), dropped (expected %d)\n",
fp->link->name, codep->name, lh.id, fp->reqid);
fp->link->name, codep->name, lh.id, fp->reqid);
return;
}
log_Printf(fp->LogLevel, "%s: Recv%s(%d) state = %s\n",
fp->link->name, codep->name, lh.id, State2Nam(fp->state));
fp->link->name, codep->name, lh.id, State2Nam(fp->state));
if (codep->inc_reqid && (lh.id == fp->reqid ||
(!Enabled(fp->bundle, OPT_IDCHECK) && codep->check_reqid)))
@ -1106,3 +1127,80 @@ fsm2initial(struct fsm *fp)
if (fp->state > ST_INITIAL)
fsm_Close(fp);
}
struct fsm_opt *
fsm_readopt(u_char **cp)
{
struct fsm_opt *o = (struct fsm_opt *)*cp;
if (o->hdr.len < sizeof(struct fsm_opt_hdr)) {
log_Printf(LogERROR, "Bad option length %d (out of phase?)\n", o->hdr.len);
return NULL;
}
*cp += o->hdr.len;
if (o->hdr.len > sizeof(struct fsm_opt)) {
o->hdr.len = sizeof(struct fsm_opt);
log_Printf(LogERROR, "Warning: Truncating option length to %d\n",
o->hdr.len);
}
return o;
}
static int
fsm_opt(u_char *opt, int optlen, const struct fsm_opt *o)
{
int cplen = o->hdr.len;
if (optlen < sizeof(struct fsm_opt_hdr))
optlen = 0;
if (cplen > optlen) {
log_Printf(LogERROR, "Can't REJ length %d - trunating to %d\n",
cplen, optlen);
cplen = optlen;
}
memcpy(opt, o, cplen);
if (cplen)
opt[1] = cplen;
return cplen;
}
void
fsm_rej(struct fsm_decode *dec, const struct fsm_opt *o)
{
if (!dec)
return;
dec->rejend += fsm_opt(dec->rejend, FSM_OPTLEN - (dec->rejend - dec->rej), o);
}
void
fsm_ack(struct fsm_decode *dec, const struct fsm_opt *o)
{
if (!dec)
return;
dec->ackend += fsm_opt(dec->ackend, FSM_OPTLEN - (dec->ackend - dec->ack), o);
}
void
fsm_nak(struct fsm_decode *dec, const struct fsm_opt *o)
{
if (!dec)
return;
dec->nakend += fsm_opt(dec->nakend, FSM_OPTLEN - (dec->nakend - dec->nak), o);
}
void
fsm_opt_normalise(struct fsm_decode *dec)
{
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;
}

View File

@ -56,6 +56,8 @@
#define FSM_REQ_TIMER 1
#define FSM_TRM_TIMER 2
#define FSM_OPTLEN 100
struct fsm;
struct fsm_retry {
@ -65,24 +67,24 @@ struct fsm_retry {
};
struct fsm_decode {
u_char ack[100], *ackend;
u_char nak[100], *nakend;
u_char rej[100], *rejend;
u_char ack[FSM_OPTLEN], *ackend;
u_char nak[FSM_OPTLEN], *nakend;
u_char rej[FSM_OPTLEN], *rejend;
};
struct fsm_callbacks {
int (*LayerUp) (struct fsm *); /* Layer is now up (tlu) */
void (*LayerDown) (struct fsm *); /* About to come down (tld) */
void (*LayerStart) (struct fsm *); /* Layer about to start up (tls) */
void (*LayerFinish) (struct fsm *); /* Layer now down (tlf) */
void (*InitRestartCounter) (struct fsm *, int); /* Set fsm timer load */
void (*SendConfigReq) (struct fsm *); /* Send REQ please */
void (*SentTerminateReq) (struct fsm *); /* Term REQ just sent */
void (*SendTerminateAck) (struct fsm *, u_char); /* Send Term ACK please */
void (*DecodeConfig) (struct fsm *, u_char *, int, int, struct fsm_decode *);
/* Deal with incoming data */
int (*RecvResetReq) (struct fsm *fp); /* Reset output */
void (*RecvResetAck) (struct fsm *fp, u_char); /* Reset input */
int (*LayerUp)(struct fsm *); /* Layer is now up (tlu) */
void (*LayerDown)(struct fsm *); /* About to come down (tld) */
void (*LayerStart)(struct fsm *); /* Layer about to start (tls) */
void (*LayerFinish)(struct fsm *); /* Layer now down (tlf) */
void (*InitRestartCounter)(struct fsm *, int);/* Set fsm timer load */
void (*SendConfigReq)(struct fsm *); /* Send REQ please */
void (*SentTerminateReq)(struct fsm *); /* Term REQ just sent */
void (*SendTerminateAck)(struct fsm *, u_char); /* Send Term ACK please */
void (*DecodeConfig)(struct fsm *, u_char *, u_char *, int,
struct fsm_decode *); /* Deal with incoming data */
int (*RecvResetReq)(struct fsm *fp); /* Reset output */
void (*RecvResetAck)(struct fsm *fp, u_char); /* Reset input */
};
struct fsm_parent {
@ -159,12 +161,25 @@ struct fsmheader {
#define CODE_RESETREQ 14 /* Used in CCP */
#define CODE_RESETACK 15 /* Used in CCP */
/* Minimum config req size. This struct is *only* used for it's size */
struct fsmconfig {
u_char type;
u_char length;
struct fsm_opt_hdr {
u_char id;
u_char len;
};
#define MAX_FSM_OPT_LEN 20
struct fsm_opt {
struct fsm_opt_hdr hdr;
u_char data[MAX_FSM_OPT_LEN-2];
};
#define INC_FSM_OPT(ty, length, o) \
do { \
(o)->hdr.id = (ty); \
(o)->hdr.len = (length); \
(o) = (struct fsm_opt *)((u_char *)(o) + (length)); \
} while (0)
extern void fsm_Init(struct fsm *, const char *, u_short, int, int, int,
struct bundle *, struct link *, const struct fsm_parent *,
struct fsm_callbacks *, const char * const [3]);
@ -179,3 +194,8 @@ extern void fsm_NullRecvResetAck(struct fsm *, u_char);
extern void fsm_Reopen(struct fsm *);
extern void fsm2initial(struct fsm *);
extern const char *State2Nam(u_int);
extern struct fsm_opt *fsm_readopt(u_char **);
extern void fsm_rej(struct fsm_decode *, const struct fsm_opt *);
extern void fsm_ack(struct fsm_decode *, const struct fsm_opt *);
extern void fsm_nak(struct fsm_decode *, const struct fsm_opt *);
extern void fsm_opt_normalise(struct fsm_decode *);

View File

@ -114,7 +114,7 @@ static void IpcpInitRestartCounter(struct fsm *, int);
static void IpcpSendConfigReq(struct fsm *);
static void IpcpSentTerminateReq(struct fsm *);
static void IpcpSendTerminateAck(struct fsm *, u_char);
static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
static void IpcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
struct fsm_decode *);
static struct fsm_callbacks ipcp_Callbacks = {
@ -351,9 +351,9 @@ ipcp_Show(struct cmdargs const *arg)
State2Nam(ipcp->fsm.state));
if (ipcp->fsm.state == ST_OPENED) {
prompt_Printf(arg->prompt, " His side: %s, %s\n",
inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
prompt_Printf(arg->prompt, " My side: %s, %s\n",
inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
prompt_Printf(arg->prompt, " Queued packets: %lu\n",
(unsigned long)ipcp_QueueLen(ipcp));
}
@ -364,7 +364,7 @@ ipcp_Show(struct cmdargs const *arg)
ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s",
ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s");
prompt_Printf(arg->prompt, " My Address: %s\n",
ncprange_ntoa(&ipcp->cfg.my_range));
ncprange_ntoa(&ipcp->cfg.my_range));
if (ipcp->cfg.HaveTriggerAddress)
prompt_Printf(arg->prompt, " Trigger address: %s\n",
inet_ntoa(ipcp->cfg.TriggerAddress));
@ -378,7 +378,7 @@ ipcp_Show(struct cmdargs const *arg)
ipcp->cfg.peer_list.src);
else
prompt_Printf(arg->prompt, " His Address: %s\n",
ncprange_ntoa(&ipcp->cfg.peer_range));
ncprange_ntoa(&ipcp->cfg.peer_range));
prompt_Printf(arg->prompt, " DNS: %s",
ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ?
@ -396,7 +396,7 @@ ipcp_Show(struct cmdargs const *arg)
prompt_Printf(arg->prompt, ", %s",
inet_ntoa(ipcp->ns.dns[1]));
prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ",
inet_ntoa(ipcp->cfg.ns.nbns[0]));
inet_ntoa(ipcp->cfg.ns.nbns[0]));
prompt_Printf(arg->prompt, "%s\n\n",
inet_ntoa(ipcp->cfg.ns.nbns[1]));
@ -754,13 +754,13 @@ IpcpSendConfigReq(struct fsm *fp)
struct physical *p = link2physical(fp->link);
struct ipcp *ipcp = fsm2ipcp(fp);
u_char buff[24];
struct lcp_opt *o;
struct fsm_opt *o;
o = (struct lcp_opt *)buff;
o = (struct fsm_opt *)buff;
if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
memcpy(o->data, &ipcp->my_ip.s_addr, 4);
INC_LCP_OPT(TY_IPADDR, 6, o);
INC_FSM_OPT(TY_IPADDR, 6, o);
}
if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
@ -768,7 +768,7 @@ IpcpSendConfigReq(struct fsm *fp)
u_int16_t proto = PROTO_VJCOMP;
ua_htons(&proto, o->data);
INC_LCP_OPT(TY_COMPPROTO, 4, o);
INC_FSM_OPT(TY_COMPPROTO, 4, o);
} else {
struct compreq req;
@ -776,19 +776,19 @@ IpcpSendConfigReq(struct fsm *fp)
req.slots = (ipcp->my_compproto >> 8) & 255;
req.compcid = ipcp->my_compproto & 1;
memcpy(o->data, &req, 4);
INC_LCP_OPT(TY_COMPPROTO, 6, o);
INC_FSM_OPT(TY_COMPPROTO, 6, o);
}
}
if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) {
memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4);
INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
INC_FSM_OPT(TY_PRIMARY_DNS, 6, o);
}
if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4);
INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
INC_FSM_OPT(TY_SECONDARY_DNS, 6, o);
}
}
@ -1033,130 +1033,126 @@ ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec)
}
static void
IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
IpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
struct fsm_decode *dec)
{
/* Deal with incoming PROTO_IPCP */
struct ncpaddr ncpaddr;
struct ipcp *ipcp = fsm2ipcp(fp);
int type, length, gotdnsnak;
int gotdnsnak;
u_int32_t compproto;
struct compreq *pcomp;
struct in_addr ipaddr, dstipaddr, have_ip;
char tbuff[100], tbuff2[100];
struct fsm_opt *opt, nak;
gotdnsnak = 0;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (length == 0) {
log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
while (end - cp >= sizeof(opt->hdr)) {
if ((opt = fsm_readopt(&cp)) == NULL)
break;
}
snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);
snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id),
opt->hdr.len);
switch (type) {
switch (opt->hdr.id) {
case TY_IPADDR: /* RFC1332 */
memcpy(&ipaddr.s_addr, cp + 2, 4);
memcpy(&ipaddr.s_addr, opt->data, 4);
log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
switch (mode_type) {
case MODE_REQ:
ipcp->peer_req = 1;
ipcp_ValidateReq(ipcp, ipaddr, dec);
break;
break;
case MODE_NAK:
if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) {
/* Use address suggested by peer */
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
inet_ntoa(ipcp->my_ip));
log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
ipcp->my_ip = ipaddr;
/* Use address suggested by peer */
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
inet_ntoa(ipcp->my_ip));
log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
ipcp->my_ip = ipaddr;
ncpaddr_setip4(&ncpaddr, ipcp->my_ip);
bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL);
} else {
log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
} else {
log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
"%s: Unacceptable address!\n", inet_ntoa(ipaddr));
fsm_Close(&ipcp->fsm);
}
break;
}
break;
case MODE_REJ:
ipcp->peer_reject |= (1 << type);
break;
ipcp->peer_reject |= (1 << opt->hdr.id);
break;
}
break;
case TY_COMPPROTO:
pcomp = (struct compreq *)(cp + 2);
pcomp = (struct compreq *)opt->data;
compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +
pcomp->compcid;
log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
switch (mode_type) {
case MODE_REQ:
if (!IsAccepted(ipcp->cfg.vj.neg)) {
memcpy(dec->rejend, cp, length);
dec->rejend += length;
} else {
switch (length) {
case 4: /* RFC1172 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
log_Printf(LogWARN, "Peer is speaking RFC1172 compression "
if (!IsAccepted(ipcp->cfg.vj.neg))
fsm_rej(dec, opt);
else {
switch (opt->hdr.len) {
case 4: /* RFC1172 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
log_Printf(LogWARN, "Peer is speaking RFC1172 compression "
"protocol !\n");
ipcp->heis1172 = 1;
ipcp->peer_compproto = compproto;
memcpy(dec->ackend, cp, length);
dec->ackend += length;
} else {
memcpy(dec->nakend, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
memcpy(dec->nakend+2, &pcomp, 2);
dec->nakend += length;
}
break;
case 6: /* RFC1332 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
ipcp->heis1172 = 1;
ipcp->peer_compproto = compproto;
fsm_ack(dec, opt);
} else {
pcomp->proto = htons(PROTO_VJCOMP);
nak.hdr.id = TY_COMPPROTO;
nak.hdr.len = 4;
memcpy(nak.data, &pcomp, 2);
fsm_nak(dec, &nak);
}
break;
case 6: /* RFC1332 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
if (pcomp->slots <= MAX_VJ_STATES
&& pcomp->slots >= MIN_VJ_STATES) {
/* Ok, we can do that */
ipcp->peer_compproto = compproto;
ipcp->heis1172 = 0;
memcpy(dec->ackend, cp, length);
dec->ackend += length;
} else {
ipcp->peer_compproto = compproto;
ipcp->heis1172 = 0;
fsm_ack(dec, opt);
} else {
/* Get as close as we can to what he wants */
ipcp->heis1172 = 0;
memcpy(dec->nakend, cp, 2);
pcomp->slots = pcomp->slots < MIN_VJ_STATES ?
ipcp->heis1172 = 0;
pcomp->slots = pcomp->slots < MIN_VJ_STATES ?
MIN_VJ_STATES : MAX_VJ_STATES;
memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
dec->nakend += length;
nak.hdr.id = TY_COMPPROTO;
nak.hdr.len = 4;
memcpy(nak.data, &pcomp, 2);
fsm_nak(dec, &nak);
}
} else {
} else {
/* What we really want */
memcpy(dec->nakend, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
pcomp->slots = DEF_VJ_STATES;
pcomp->compcid = 1;
memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
dec->nakend += length;
}
break;
default:
memcpy(dec->rejend, cp, length);
dec->rejend += length;
break;
}
}
break;
pcomp->proto = htons(PROTO_VJCOMP);
pcomp->slots = DEF_VJ_STATES;
pcomp->compcid = 1;
nak.hdr.id = TY_COMPPROTO;
nak.hdr.len = 6;
memcpy(nak.data, &pcomp, sizeof pcomp);
fsm_nak(dec, &nak);
}
break;
default:
fsm_rej(dec, opt);
break;
}
}
break;
case MODE_NAK:
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
if (pcomp->slots > MAX_VJ_STATES)
pcomp->slots = MAX_VJ_STATES;
else if (pcomp->slots < MIN_VJ_STATES)
@ -1165,51 +1161,49 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
pcomp->compcid;
} else
compproto = 0;
log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
tbuff, ipcp->my_compproto, compproto);
log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
tbuff, ipcp->my_compproto, compproto);
ipcp->my_compproto = compproto;
break;
break;
case MODE_REJ:
ipcp->peer_reject |= (1 << type);
break;
ipcp->peer_reject |= (1 << opt->hdr.id);
break;
}
break;
case TY_IPADDRS: /* RFC1172 */
memcpy(&ipaddr.s_addr, cp + 2, 4);
memcpy(&dstipaddr.s_addr, cp + 6, 4);
memcpy(&ipaddr.s_addr, opt->data, 4);
memcpy(&dstipaddr.s_addr, opt->data + 4, 4);
snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
switch (mode_type) {
case MODE_REQ:
memcpy(dec->rejend, cp, length);
dec->rejend += length;
break;
fsm_rej(dec, opt);
break;
case MODE_NAK:
case MODE_REJ:
break;
break;
}
break;
case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */
case TY_SECONDARY_DNS:
memcpy(&ipaddr.s_addr, cp + 2, 4);
memcpy(&ipaddr.s_addr, opt->data, 4);
log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
switch (mode_type) {
case MODE_REQ:
if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
memcpy(dec->rejend, cp, length);
dec->rejend += length;
break;
ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
fsm_rej(dec, opt);
break;
}
have_ip = ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1];
have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1];
if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
ipaddr.s_addr == ipcp->ns.dns[1].s_addr) {
/* Swap 'em 'round */
ipcp->ns.dns[0] = ipcp->ns.dns[1];
@ -1217,86 +1211,81 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
have_ip = ipcp->ns.dns[0];
}
if (ipaddr.s_addr != have_ip.s_addr) {
/*
* The client has got the DNS stuff wrong (first request) so
* we'll tell 'em how it is
*/
memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */
memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
dec->nakend += length;
} else {
/*
* Otherwise they have it right (this time) so we send a ack packet
* back confirming it... end of story
*/
memcpy(dec->ackend, cp, length);
dec->ackend += length;
if (ipaddr.s_addr != have_ip.s_addr) {
/*
* The client has got the DNS stuff wrong (first request) so
* we'll tell 'em how it is
*/
nak.hdr.id = opt->hdr.id;
nak.hdr.len = 6;
memcpy(nak.data, &have_ip.s_addr, 4);
fsm_nak(dec, &nak);
} else {
/*
* Otherwise they have it right (this time) so we send a ack packet
* back confirming it... end of story
*/
fsm_ack(dec, opt);
}
break;
break;
case MODE_NAK:
if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
gotdnsnak = 1;
memcpy(&ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr,
cp + 2, 4);
}
break;
memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr,
opt->data, 4);
}
break;
case MODE_REJ: /* Can't do much, stop asking */
ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
break;
ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
break;
}
break;
case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */
case TY_SECONDARY_NBNS:
memcpy(&ipaddr.s_addr, cp + 2, 4);
memcpy(&ipaddr.s_addr, opt->data, 4);
log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
switch (mode_type) {
case MODE_REQ:
have_ip.s_addr =
ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
have_ip.s_addr =
ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
if (have_ip.s_addr == INADDR_ANY) {
log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
memcpy(dec->rejend, cp, length);
dec->rejend += length;
break;
log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
fsm_rej(dec, opt);
break;
}
if (ipaddr.s_addr != have_ip.s_addr) {
memcpy(dec->nakend, cp, 2);
memcpy(dec->nakend+2, &have_ip.s_addr, length);
dec->nakend += length;
} else {
memcpy(dec->ackend, cp, length);
dec->ackend += length;
}
break;
if (ipaddr.s_addr != have_ip.s_addr) {
nak.hdr.id = opt->hdr.id;
nak.hdr.len = 6;
memcpy(nak.data, &have_ip.s_addr, 4);
fsm_nak(dec, &nak);
} else
fsm_ack(dec, opt);
break;
case MODE_NAK:
log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
break;
log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id);
break;
case MODE_REJ:
log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
break;
log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id);
break;
}
break;
default:
if (mode_type != MODE_NOP) {
ipcp->my_reject |= (1 << type);
memcpy(dec->rejend, cp, length);
dec->rejend += length;
ipcp->my_reject |= (1 << opt->hdr.id);
fsm_rej(dec, opt);
}
break;
}
plen -= length;
cp += length;
}
if (gotdnsnak) {
@ -1328,13 +1317,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
ipaddr.s_addr = INADDR_ANY;
ipcp_ValidateReq(ipcp, ipaddr, dec);
}
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;
fsm_opt_normalise(dec);
}
}

View File

@ -85,7 +85,7 @@ static void ipv6cp_InitRestartCounter(struct fsm *, int);
static void ipv6cp_SendConfigReq(struct fsm *);
static void ipv6cp_SentTerminateReq(struct fsm *);
static void ipv6cp_SendTerminateAck(struct fsm *, u_char);
static void ipv6cp_DecodeConfig(struct fsm *, u_char *, int, int,
static void ipv6cp_DecodeConfig(struct fsm *, u_char *, u_char *, int,
struct fsm_decode *);
static struct fsm_callbacks ipv6cp_Callbacks = {
@ -233,9 +233,9 @@ ipv6cp_Show(struct cmdargs const *arg)
State2Nam(ipv6cp->fsm.state));
if (ipv6cp->fsm.state == ST_OPENED) {
prompt_Printf(arg->prompt, " His side: %s\n",
ncpaddr_ntoa(&ipv6cp->hisaddr));
ncpaddr_ntoa(&ipv6cp->hisaddr));
prompt_Printf(arg->prompt, " My side: %s\n",
ncpaddr_ntoa(&ipv6cp->myaddr));
ncpaddr_ntoa(&ipv6cp->myaddr));
prompt_Printf(arg->prompt, " Queued packets: %lu\n",
(unsigned long)ipv6cp_QueueLen(ipv6cp));
}
@ -455,13 +455,13 @@ ipv6cp_SendConfigReq(struct fsm *fp)
struct physical *p = link2physical(fp->link);
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
u_char buff[6];
struct lcp_opt *o;
struct fsm_opt *o;
o = (struct lcp_opt *)buff;
o = (struct fsm_opt *)buff;
if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) {
memcpy(o->data, &ipv6cp->my_token, 4);
INC_LCP_OPT(TY_TOKEN, 6, o);
INC_FSM_OPT(TY_TOKEN, 6, o);
}
fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
@ -496,61 +496,56 @@ static void
ipv6cp_ValidateToken(struct ipv6cp *ipv6cp, u_int32_t token,
struct fsm_decode *dec)
{
struct fsm_opt opt;
if (token != 0 && token != ipv6cp->my_token)
ipv6cp->peer_token = token;
if (token == ipv6cp->peer_token) {
*dec->ackend++ = TY_TOKEN;
*dec->ackend++ = 6;
memcpy(dec->ackend, &ipv6cp->peer_token, 4);
dec->ackend += 4;
} else {
*dec->nakend++ = TY_TOKEN;
*dec->nakend++ = 6;
memcpy(dec->nakend, &ipv6cp->peer_token, 4);
dec->nakend += 4;
}
opt.hdr.id = TY_TOKEN;
opt.hdr.len = 6;
memcpy(opt.data, &ipv6cp->peer_token, 4);
if (token == ipv6cp->peer_token)
fsm_ack(dec, &opt);
else
fsm_nak(dec, &opt);
}
static void
ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
struct fsm_decode *dec)
{
/* Deal with incoming PROTO_IPV6CP */
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
int type, length, n;
int n;
char tbuff[100];
u_int32_t token;
struct fsm_opt *opt;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (length == 0) {
log_Printf(LogIPV6CP, "%s: IPV6CP size zero\n", fp->link->name);
while (end - cp >= sizeof(opt->hdr)) {
if ((opt = fsm_readopt(&cp)) == NULL)
break;
}
snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);
snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id),
opt->hdr.len);
switch (type) {
switch (opt->hdr.id) {
case TY_TOKEN:
memcpy(&token, cp + 2, 4);
memcpy(&token, opt->data, 4);
log_Printf(LogIPV6CP, "%s 0x%08lx\n", tbuff, (unsigned long)token);
switch (mode_type) {
case MODE_REQ:
ipv6cp->peer_tokenreq = 1;
ipv6cp_ValidateToken(ipv6cp, token, dec);
break;
break;
case MODE_NAK:
if (token == 0) {
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
"0x00000000: Unacceptable token!\n");
fsm_Close(&ipv6cp->fsm);
} else if (token == ipv6cp->peer_token)
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
"0x%08lx: Unacceptable token!\n", (unsigned long)token);
else if (token != ipv6cp->my_token) {
n = 100;
@ -561,35 +556,32 @@ ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
}
if (n == 0) {
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
"0x00000000: Unacceptable token!\n");
fsm_Close(&ipv6cp->fsm);
} else {
log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n",
log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n",
tbuff, (unsigned long)ipv6cp->my_token,
(unsigned long)token);
ipv6cp->my_token = token;
bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL);
}
}
break;
break;
case MODE_REJ:
ipv6cp->his_reject |= (1 << type);
break;
ipv6cp->his_reject |= (1 << opt->hdr.id);
break;
}
break;
default:
if (mode_type != MODE_NOP) {
ipv6cp->my_reject |= (1 << type);
memcpy(dec->rejend, cp, length);
dec->rejend += length;
ipv6cp->my_reject |= (1 << opt->hdr.id);
fsm_rej(dec, opt);
}
break;
}
plen -= length;
cp += length;
}
if (mode_type != MODE_NOP) {
@ -606,13 +598,7 @@ ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
}
ipv6cp_ValidateToken(ipv6cp, 0, dec);
}
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;
fsm_opt_normalise(dec);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -123,20 +123,6 @@ struct lcp {
#define TY_SHORTSEQ 18 /* Want short seqs (12bit) please (see mp.h) */
#define TY_ENDDISC 19 /* Endpoint discriminator */
#define MAX_LCP_OPT_LEN 20
struct lcp_opt {
u_char id;
u_char len;
u_char data[MAX_LCP_OPT_LEN-2];
};
#define INC_LCP_OPT(ty, length, o) \
do { \
(o)->id = (ty); \
(o)->len = (length); \
(o) = (struct lcp_opt *)((char *)(o) + (length)); \
} while (0)
struct mbuf;
struct link;
struct bundle;

View File

@ -364,7 +364,7 @@ MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
}
static const char *
MPPEDispOpts(struct lcp_opt *o)
MPPEDispOpts(struct fsm_opt *o)
{
static char buf[70];
u_int32_t val;
@ -460,11 +460,11 @@ MPPE_ConfigVal(const struct ccp_config *cfg)
* What options should we use for our first configure request
*/
static void
MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
MPPEInitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
{
u_int32_t mval;
o->len = 6;
o->hdr.len = 6;
if (!MPPE_MasterKeyValid) {
log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
@ -481,7 +481,7 @@ MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
* Our CCP request was NAK'd with the given options
*/
static int
MPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
MPPESetOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
{
u_int32_t mval, peer;
@ -519,7 +519,7 @@ MPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
* The peer has requested the given options
*/
static int
MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
MPPESetOptsInput(struct fsm_opt *o, const struct ccp_config *cfg)
{
u_int32_t mval, peer;
int res = MODE_ACK;
@ -588,7 +588,7 @@ MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
}
static struct mppe_state *
MPPE_InitState(struct lcp_opt *o)
MPPE_InitState(struct fsm_opt *o)
{
struct mppe_state *mp;
u_int32_t val;
@ -622,7 +622,7 @@ MPPE_InitState(struct lcp_opt *o)
}
static void *
MPPEInitInput(struct lcp_opt *o)
MPPEInitInput(struct fsm_opt *o)
{
struct mppe_state *mip;
@ -668,7 +668,7 @@ MPPEInitInput(struct lcp_opt *o)
}
static void *
MPPEInitOutput(struct lcp_opt *o)
MPPEInitOutput(struct fsm_opt *o)
{
struct mppe_state *mop;

View File

@ -151,7 +151,7 @@ Pred1ResetOutput(void *v)
}
static void *
Pred1InitInput(struct lcp_opt *o)
Pred1InitInput(struct fsm_opt *o)
{
struct pred1_state *state;
state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
@ -161,7 +161,7 @@ Pred1InitInput(struct lcp_opt *o)
}
static void *
Pred1InitOutput(struct lcp_opt *o)
Pred1InitOutput(struct fsm_opt *o)
{
struct pred1_state *state;
state = (struct pred1_state *)malloc(sizeof(struct pred1_state));
@ -294,32 +294,22 @@ Pred1DictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *bp)
}
static const char *
Pred1DispOpts(struct lcp_opt *o)
Pred1DispOpts(struct fsm_opt *o)
{
return NULL;
}
static void
Pred1InitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
Pred1InitOptsOutput(struct fsm_opt *o, const struct ccp_config *cfg)
{
o->len = 2;
o->hdr.len = 2;
}
static int
Pred1SetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
Pred1SetOpts(struct fsm_opt *o, const struct ccp_config *cfg)
{
if (o->len != 2) {
o->len = 2;
return MODE_NAK;
}
return MODE_ACK;
}
static int
Pred1SetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
{
if (o->len != 2) {
o->len = 2;
if (o->hdr.len != 2) {
o->hdr.len = 2;
return MODE_NAK;
}
return MODE_ACK;
@ -332,7 +322,7 @@ const struct ccp_algorithm Pred1Algorithm = {
ccp_DefaultUsable,
ccp_DefaultRequired,
{
Pred1SetOptsInput,
Pred1SetOpts,
Pred1InitInput,
Pred1Term,
Pred1ResetInput,
@ -342,7 +332,7 @@ const struct ccp_algorithm Pred1Algorithm = {
{
0,
Pred1InitOptsOutput,
Pred1SetOptsOutput,
Pred1SetOpts,
Pred1InitOutput,
Pred1Term,
Pred1ResetOutput,