diff options
author | brian <brian@cvs.openbsd.org> | 2001-06-19 10:25:02 +0000 |
---|---|---|
committer | brian <brian@cvs.openbsd.org> | 2001-06-19 10:25:02 +0000 |
commit | bdb5d3ad89ed58714216e13c2f6ccc4625b47be4 (patch) | |
tree | 50a12a535c06c37138b9a154d483f75d6a63c6bb /usr.sbin/ppp | |
parent | 6e8a8159f93a1ad9c4faab0f84ef596f639136b6 (diff) |
Handle hardware-imposed MTU/MRU limitations.
Add an optional ``max'' specifier to ``set m[rt]u'', ie.
``set mtu max 1492'' for PPPoE.
Bump the ppp version number.
Add support for stateful MPPE (microsoft encryption) providing
encryption compatibility with Windows 2000. Stateful encryption
uses less CPU but is bad on lossy transports.
The ``set mppe'' command has been expanded. If it's used with any
arguments, ppp will insist on encryption, closing LCP if the other
end refuses.
Sponsored by: Monzoon Networks AG and FreeBSD Services Limited
Diffstat (limited to 'usr.sbin/ppp')
28 files changed, 877 insertions, 284 deletions
diff --git a/usr.sbin/ppp/ppp/atm.c b/usr.sbin/ppp/ppp/atm.c index 902c5c85f3d..d234786459e 100644 --- a/usr.sbin/ppp/ppp/atm.c +++ b/usr.sbin/ppp/ppp/atm.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: atm.c,v 1.3 2001/01/29 08:47:43 brian Exp $ + * $OpenBSD: atm.c,v 1.4 2001/06/19 10:24:49 brian Exp $ */ #include <sys/types.h> @@ -122,6 +122,7 @@ atm_device2iov(struct device *d, struct iovec *iov, int *niov, static const struct device baseatmdevice = { ATM_DEVICE, "atm", + 0, { CD_NOTREQUIRED, 0 }, NULL, NULL, diff --git a/usr.sbin/ppp/ppp/bundle.c b/usr.sbin/ppp/ppp/bundle.c index fcb713b3df4..c26d9cf0f0d 100644 --- a/usr.sbin/ppp/ppp/bundle.c +++ b/usr.sbin/ppp/ppp/bundle.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: bundle.c,v 1.56 2001/04/05 02:24:04 brian Exp $ + * $OpenBSD: bundle.c,v 1.57 2001/06/19 10:24:49 brian Exp $ */ #include <sys/param.h> @@ -802,7 +802,6 @@ bundle_Create(const char *prefix, int type, int unit) log_Printf(LogPHASE, "Using interface: %s\n", ifname); bundle.bandwidth = 0; - bundle.mtu = 1500; bundle.routing_seq = 0; bundle.phase = PHASE_DEAD; bundle.CleaningUp = 0; @@ -821,7 +820,6 @@ bundle_Create(const char *prefix, int type, int unit) bundle.cfg.opt = OPT_SROUTES | OPT_IDCHECK | OPT_LOOPBACK | OPT_TCPMSSFIXUP | OPT_THROUGHPUT | OPT_UTMP; *bundle.cfg.label = '\0'; - bundle.cfg.mtu = DEF_MTU; bundle.cfg.ifqueue = DEF_IFQUEUE; bundle.cfg.choked.timeout = CHOKED_TIMEOUT; bundle.phys_type.all = type; @@ -1096,11 +1094,6 @@ bundle_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, "\n"); } else prompt_Printf(arg->prompt, "disabled\n"); - prompt_Printf(arg->prompt, " MTU: "); - if (arg->bundle->cfg.mtu) - prompt_Printf(arg->prompt, "%d\n", arg->bundle->cfg.mtu); - else - prompt_Printf(arg->prompt, "unspecified\n"); prompt_Printf(arg->prompt, " sendpipe: "); if (arg->bundle->ncp.ipcp.cfg.sendpipe > 0) @@ -1826,7 +1819,7 @@ bundle_CalculateBandwidth(struct bundle *bundle) int sp; bundle->bandwidth = 0; - bundle->mtu = 0; + bundle->iface->mtu = 0; for (dl = bundle->links; dl; dl = dl->next) if (dl->state == DATALINK_OPEN) { if ((sp = dl->mp.bandwidth) == 0 && @@ -1836,7 +1829,7 @@ bundle_CalculateBandwidth(struct bundle *bundle) else bundle->bandwidth += sp; if (!bundle->ncp.mp.active) { - bundle->mtu = dl->physical->link.lcp.his_mru; + bundle->iface->mtu = dl->physical->link.lcp.his_mru; break; } } @@ -1845,16 +1838,16 @@ bundle_CalculateBandwidth(struct bundle *bundle) bundle->bandwidth = 115200; /* Shrug */ if (bundle->ncp.mp.active) - bundle->mtu = bundle->ncp.mp.peer_mrru; - else if (!bundle->mtu) - bundle->mtu = 1500; + bundle->iface->mtu = bundle->ncp.mp.peer_mrru; + else if (!bundle->iface->mtu) + bundle->iface->mtu = DEF_MRU; #ifndef NORADIUS if (bundle->radius.valid && bundle->radius.mtu && - bundle->radius.mtu < bundle->mtu) { + bundle->radius.mtu < bundle->iface->mtu) { log_Printf(LogLCP, "Reducing MTU to radius value %lu\n", bundle->radius.mtu); - bundle->mtu = bundle->radius.mtu; + bundle->iface->mtu = bundle->radius.mtu; } #endif diff --git a/usr.sbin/ppp/ppp/bundle.h b/usr.sbin/ppp/ppp/bundle.h index f5f6bb64ab1..ed70c58ff31 100644 --- a/usr.sbin/ppp/ppp/bundle.h +++ b/usr.sbin/ppp/ppp/bundle.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: bundle.h,v 1.20 2001/04/05 02:24:05 brian Exp $ + * $OpenBSD: bundle.h,v 1.21 2001/06/19 10:24:50 brian Exp $ */ #define PHASE_DEAD 0 /* Link is dead */ @@ -73,7 +73,6 @@ struct bundle { } dev; u_long bandwidth; /* struct tuninfo speed */ - int mtu; /* struct tuninfo MTU */ struct iface *iface; /* Interface information */ int routing_seq; /* The current routing sequence number */ @@ -103,7 +102,6 @@ struct bundle { } auth; unsigned opt; /* Uses OPT_ bits from above */ char label[50]; /* last thing `load'ed */ - u_short mtu; /* Required interface MTU */ u_short ifqueue; /* Interface queue size */ struct { diff --git a/usr.sbin/ppp/ppp/ccp.c b/usr.sbin/ppp/ppp/ccp.c index 35bbb9dc7ab..db3eceb3b58 100644 --- a/usr.sbin/ppp/ppp/ccp.c +++ b/usr.sbin/ppp/ppp/ccp.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: ccp.c,v 1.19 2001/06/13 21:33:40 brian Exp $ + * $OpenBSD: ccp.c,v 1.20 2001/06/19 10:24:50 brian Exp $ */ #include <sys/param.h> @@ -82,7 +82,7 @@ static void CcpLayerFinish(struct fsm *); static int CcpLayerUp(struct fsm *); static void CcpLayerDown(struct fsm *); static void CcpInitRestartCounter(struct fsm *, int); -static void CcpRecvResetReq(struct fsm *); +static int CcpRecvResetReq(struct fsm *); static void CcpRecvResetAck(struct fsm *, u_char); static struct fsm_callbacks ccp_Callbacks = { @@ -150,8 +150,10 @@ static const struct ccp_algorithm * const algorithm[] = { int ccp_ReportStatus(struct cmdargs const *arg) { + struct ccp_opt **o; struct link *l; struct ccp *ccp; + int f; l = command_ChooseLink(arg); ccp = &l->ccp; @@ -166,6 +168,19 @@ ccp_ReportStatus(struct cmdargs const *arg) ccp->compin, ccp->uncompin); } + if (ccp->in.algorithm != -1) + prompt_Printf(arg->prompt, "\n Input Options: %s\n", + (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt)); + + if (ccp->out.algorithm != -1) { + o = &ccp->out.opt; + for (f = 0; f < ccp->out.algorithm; f++) + if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) + o = &(*o)->next; + prompt_Printf(arg->prompt, " Output Options: %s\n", + (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val)); + } + prompt_Printf(arg->prompt, "\n Defaults: "); prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config" " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout, @@ -174,16 +189,36 @@ ccp_ReportStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, " deflate windows: "); prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); - prompt_Printf(arg->prompt, " DEFLATE: %s\n", +#ifdef HAVE_DES + prompt_Printf(arg->prompt, " MPPE: "); + if (ccp->cfg.mppe.keybits) + prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); + else + prompt_Printf(arg->prompt, "any bits, "); + switch (ccp->cfg.mppe.state) { + case MPPE_STATEFUL: + prompt_Printf(arg->prompt, "statefull"); + break; + case MPPE_STATELESS: + prompt_Printf(arg->prompt, "stateless"); + break; + case MPPE_ANYSTATE: + prompt_Printf(arg->prompt, "any state"); + break; + } + prompt_Printf(arg->prompt, "%s\n", + ccp->cfg.mppe.required ? ", required" : ""); +#endif + + prompt_Printf(arg->prompt, "\n DEFLATE: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); prompt_Printf(arg->prompt, " DEFLATE24: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); #ifdef HAVE_DES - prompt_Printf(arg->prompt, " MPPE: %s", + prompt_Printf(arg->prompt, " MPPE: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); - prompt_Printf(arg->prompt, " (Key Size = %d-bits)\n", ccp->cfg.mppe.keybits); #endif return 0; } @@ -215,7 +250,9 @@ ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; #ifdef HAVE_DES - ccp->cfg.mppe.keybits = 128; + ccp->cfg.mppe.keybits = 0; + ccp->cfg.mppe.state = MPPE_ANYSTATE; + ccp->cfg.mppe.required = 0; ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED; #endif @@ -238,6 +275,30 @@ ccp_Setup(struct ccp *ccp) ccp->uncompin = ccp->compin = 0; } +/* + * Is ccp *REQUIRED* ? + * We ask each of the configured ccp protocols if they're required and + * return TRUE if they are. + * + * It's not possible for the peer to reject a required ccp protocol + * without our state machine bringing the supporting lcp layer down. + * + * If ccp is required but not open, the NCP layer should not push + * any data into the link. + */ +int +ccp_Required(struct ccp *ccp) +{ + int f; + + for (f = 0; f < NALGORITHMS; f++) + if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && + (*algorithm[f]->Required)(&ccp->fsm)) + return 1; + + return 0; +} + static void CcpInitRestartCounter(struct fsm *fp, int what) { @@ -332,13 +393,14 @@ CcpSendTerminateAck(struct fsm *fp, u_char id) fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); } -static void +static int CcpRecvResetReq(struct fsm *fp) { /* Got a reset REQ, reset outgoing dictionary */ struct ccp *ccp = fsm2ccp(fp); - if (ccp->out.state != NULL) - (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); + if (ccp->out.state == NULL) + return 1; + return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); } static void @@ -397,6 +459,12 @@ CcpLayerFinish(struct fsm *fp) free(ccp->out.opt); ccp->out.opt = next; } + + if (ccp_Required(ccp)) { + if (fp->link->lcp.fsm.state == ST_OPENED) + log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); + fsm_Close(&fp->link->lcp.fsm); + } } /* Called when CCP has reached the OPEN state */ @@ -531,17 +599,28 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, " option\n", fp->link->name); else { memcpy(&o->val, cp, length); - if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) + 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; + if (algorithm[f]->Required(fp)) { + log_Printf(LogWARN, "%s: Cannot understand peers (required)" + " %s negotiation\n", fp->link->name, + protoname(algorithm[f]->id)); + fsm_Close(&fp->link->lcp.fsm); + } } } break; case MODE_REJ: ccp->his_reject |= (1 << type); 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; } } @@ -618,17 +697,26 @@ static struct mbuf * ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, int pri, u_short *proto) { - if (PROTO_COMPRESSIBLE(*proto) && l->ccp.fsm.state == ST_OPENED && - l->ccp.out.state != NULL) { - bp = (*algorithm[l->ccp.out.algorithm]->o.Write) - (l->ccp.out.state, &l->ccp, l, pri, proto, bp); - switch (*proto) { - case PROTO_ICOMPD: - m_settype(bp, MB_ICOMPDOUT); - break; - case PROTO_COMPD: - m_settype(bp, MB_COMPDOUT); - break; + if (PROTO_COMPRESSIBLE(*proto)) { + if (l->ccp.fsm.state != ST_OPENED) { + if (ccp_Required(&l->ccp)) { + /* The NCP layer shouldn't have let this happen ! */ + log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" + " required CCP layer\n", l->name); + m_freem(bp); + bp = NULL; + } + } else if (l->ccp.out.state != NULL) { + bp = (*algorithm[l->ccp.out.algorithm]->o.Write) + (l->ccp.out.state, &l->ccp, l, pri, proto, bp); + switch (*proto) { + case PROTO_ICOMPD: + m_settype(bp, MB_ICOMPDOUT); + break; + case PROTO_COMPD: + m_settype(bp, MB_COMPDOUT); + break; + } } } @@ -706,9 +794,15 @@ ccp_SetOpenMode(struct ccp *ccp) } int -ccp_IsUsable(struct fsm *fp) +ccp_DefaultUsable(struct fsm *fp) { return 1; } +int +ccp_DefaultRequired(struct fsm *fp) +{ + return 0; +} + struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; diff --git a/usr.sbin/ppp/ppp/ccp.h b/usr.sbin/ppp/ppp/ccp.h index 56c15f5d631..49918eb703d 100644 --- a/usr.sbin/ppp/ppp/ccp.h +++ b/usr.sbin/ppp/ppp/ccp.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: ccp.h,v 1.9 2001/06/13 21:33:40 brian Exp $ + * $OpenBSD: ccp.h,v 1.10 2001/06/19 10:24:50 brian Exp $ */ #define CCP_MAXCODE CODE_RESETACK @@ -54,6 +54,14 @@ #define CCP_NEG_TOTAL 3 #endif +#ifdef HAVE_DES +enum mppe_negstate { + MPPE_ANYSTATE, + MPPE_STATELESS, + MPPE_STATEFUL +}; +#endif + struct mbuf; struct link; @@ -66,6 +74,8 @@ struct ccp_config { #ifdef HAVE_DES struct { int keybits; + enum mppe_negstate state; + unsigned required : 1; } mppe; #endif struct fsm_retry fsm; /* How often/frequently to resend requests */ @@ -115,6 +125,7 @@ struct ccp_algorithm { int Neg; /* ccp_config neg array item */ const char *(*Disp)(struct lcp_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 *); @@ -125,10 +136,10 @@ struct ccp_algorithm { } i; struct { void (*OptInit)(struct lcp_opt *, const struct ccp_config *); - int (*Set)(struct lcp_opt *); + int (*Set)(struct lcp_opt *, const struct ccp_config *); void *(*Init)(struct lcp_opt *); void (*Term)(void *); - void (*Reset)(void *); + int (*Reset)(void *); struct mbuf *(*Write)(void *, struct ccp *, struct link *, int, u_short *, struct mbuf *); } o; @@ -137,6 +148,7 @@ struct ccp_algorithm { extern void ccp_Init(struct ccp *, struct bundle *, struct link *, const struct fsm_parent *); extern void ccp_Setup(struct ccp *); +extern int ccp_Required(struct ccp *); extern void ccp_SendResetReq(struct fsm *); extern struct mbuf *ccp_Input(struct bundle *, struct link *, struct mbuf *); @@ -144,6 +156,7 @@ extern int ccp_ReportStatus(struct cmdargs const *); extern u_short ccp_Proto(struct ccp *); extern void ccp_SetupCallbacks(struct ccp *); extern int ccp_SetOpenMode(struct ccp *); -extern int ccp_IsUsable(struct fsm *); +extern int ccp_DefaultUsable(struct fsm *); +extern int ccp_DefaultRequired(struct fsm *); extern struct layer ccplayer; diff --git a/usr.sbin/ppp/ppp/command.c b/usr.sbin/ppp/ppp/command.c index eabf36e0167..2dc0d17c6df 100644 --- a/usr.sbin/ppp/ppp/command.c +++ b/usr.sbin/ppp/ppp/command.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: command.c,v 1.59 2001/06/13 21:33:40 brian Exp $ + * $OpenBSD: command.c,v 1.60 2001/06/19 10:24:51 brian Exp $ */ #include <sys/param.h> @@ -135,7 +135,7 @@ #define VAR_URGENTPORTS 33 #define VAR_LOGOUT 34 #define VAR_IFQUEUE 35 -#define VAR_KEYBITS 36 +#define VAR_MPPE 36 /* ``accept|deny|disable|enable'' masks */ #define NEG_HISMASK (1) @@ -159,7 +159,7 @@ #define NEG_MPPE 54 #define NEG_CHAP81 55 -const char Version[] = "2.3.1"; +const char Version[] = "2.3.2"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); @@ -1489,6 +1489,7 @@ SetVariable(struct cmdargs const *arg) { long long_val, param = (long)arg->cmd->args; int mode, dummyint, f, first; + u_short *change; const char *argp; struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ const char *err = NULL; @@ -1609,20 +1610,43 @@ SetVariable(struct cmdargs const *arg) break; #ifdef HAVE_DES - case VAR_KEYBITS: - if (arg->argc > arg->argn) { - l->ccp.cfg.mppe.keybits = atoi(arg->argv[arg->argn]); - if (l->ccp.cfg.mppe.keybits != 40 && - l->ccp.cfg.mppe.keybits != 56 && - l->ccp.cfg.mppe.keybits != 128 ) { - log_Printf(LogWARN, "%d: Invalid bits number\n", - l->ccp.cfg.mppe.keybits); - l->ccp.cfg.mppe.keybits = 40; + case VAR_MPPE: + if (arg->argc > arg->argn + 2) + return -1; + + if (arg->argc == arg->argn) { + l->ccp.cfg.mppe.keybits = 0; + l->ccp.cfg.mppe.state = MPPE_ANYSTATE; + l->ccp.cfg.mppe.required = 0; + break; + } + + if (!strcmp(argp, "*")) + long_val = 0; + else { + long_val = atol(argp); + if (long_val != 40 && long_val != 56 && long_val != 128) { + log_Printf(LogWARN, "%s: Invalid bits value\n", argp); + return -1; } - } else { - err = "No bits number pecified\n"; - log_Printf(LogWARN, err); } + + if (arg->argc == arg->argn + 2) { + if (!strcmp(arg->argv[arg->argn + 1], "*")) + l->ccp.cfg.mppe.state = MPPE_ANYSTATE; + else if (!strcasecmp(arg->argv[arg->argn + 1], "stateless")) + l->ccp.cfg.mppe.state = MPPE_STATELESS; + else if (!strcasecmp(arg->argv[arg->argn + 1], "statefull")) + l->ccp.cfg.mppe.state = MPPE_STATEFUL; + else { + log_Printf(LogWARN, "%s: Invalid state value\n", + arg->argv[arg->argn + 1]); + return -1; + } + } else + l->ccp.cfg.mppe.state = MPPE_ANYSTATE; + l->ccp.cfg.mppe.keybits = long_val; + l->ccp.cfg.mppe.required = 1; break; #endif @@ -1678,9 +1702,36 @@ SetVariable(struct cmdargs const *arg) break; case VAR_MRU: - long_val = atol(argp); + switch(arg->argc - arg->argn) { + case 1: + if (argp[strspn(argp, "0123456789")] != '\0') + return -1; + case 0: + long_val = atol(argp); + change = &l->lcp.cfg.mru; + if (long_val > l->lcp.cfg.max_mru) { + log_Printf(LogWARN, "MRU %ld: too large - max set to %d\n", long_val, + l->lcp.cfg.max_mru); + return 1; + } + break; + case 2: + if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) + return -1; + long_val = atol(arg->argv[arg->argn + 1]); + change = &l->lcp.cfg.max_mru; + if (long_val > MAX_MRU) { + log_Printf(LogWARN, "MRU %ld: too large - maximum is %d\n", long_val, + MAX_MRU); + return 1; + } + break; + default: + return -1; + } + if (long_val == 0) - l->lcp.cfg.mru = DEF_MRU; + *change = DEF_MRU; else if (long_val < MIN_MRU) { log_Printf(LogWARN, "MRU %ld: too small - min %d\n", long_val, MIN_MRU); return 1; @@ -1688,11 +1739,40 @@ SetVariable(struct cmdargs const *arg) log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); return 1; } else - l->lcp.cfg.mru = long_val; + *change = long_val; + if (l->lcp.cfg.mru > *change) + l->lcp.cfg.mru = *change; break; case VAR_MTU: - long_val = atol(argp); + switch(arg->argc - arg->argn) { + case 1: + if (argp[strspn(argp, "0123456789")] != '\0') + return -1; + case 0: + long_val = atol(argp); + change = &l->lcp.cfg.mtu; + if (long_val > l->lcp.cfg.max_mtu) { + log_Printf(LogWARN, "MTU %ld: too large - max set to %d\n", long_val, + l->lcp.cfg.max_mtu); + return 1; + } + break; + case 2: + if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) + return -1; + long_val = atol(arg->argv[arg->argn + 1]); + change = &l->lcp.cfg.max_mtu; + if (long_val > MAX_MTU) { + log_Printf(LogWARN, "MTU %ld: too large - maximum is %d\n", long_val, + MAX_MTU); + return 1; + } + break; + default: + return -1; + } + if (long_val && long_val < MIN_MTU) { log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); return 1; @@ -1700,7 +1780,9 @@ SetVariable(struct cmdargs const *arg) log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); return 1; } else - arg->bundle->cfg.mtu = long_val; + *change = long_val; + if (l->lcp.cfg.mtu > *change) + l->lcp.cfg.mtu = *change; break; case VAR_OPENMODE: @@ -2022,8 +2104,8 @@ static struct cmdtab const SetCommands[] = { (const void *) VAR_WINSIZE}, #ifdef HAVE_DES {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, - "MPPE key size", "set mppe {40|56|128}", - (const void *) VAR_KEYBITS}, + "MPPE key size and state", "set mppe [40|56|128|* [statefull|stateless|*]]", + (const void *) VAR_MPPE}, #endif {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, "physical device name", "set device|line device-name[,device-name]", @@ -2064,9 +2146,9 @@ static struct cmdtab const SetCommands[] = { {"mrru", NULL, SetVariable, LOCAL_AUTH, "MRRU value", "set mrru value", (const void *)VAR_MRRU}, {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, - "MRU value", "set mru value", (const void *)VAR_MRU}, - {"mtu", NULL, SetVariable, LOCAL_AUTH, - "interface MTU value", "set mtu value", (const void *)VAR_MTU}, + "MRU value", "set mru [max[imum]] [value]", (const void *)VAR_MRU}, + {"mtu", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, + "interface MTU value", "set mtu [max[imum]] [value]", (const void *)VAR_MTU}, {"nbns", NULL, SetVariable, LOCAL_AUTH, "NetBIOS Name Server", "set nbns pri-addr [sec-addr]", (const void *)VAR_NBNS}, {"openmode", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, "open mode", diff --git a/usr.sbin/ppp/ppp/deflate.c b/usr.sbin/ppp/ppp/deflate.c index 2181b1fb9ec..0e9281db0f9 100644 --- a/usr.sbin/ppp/ppp/deflate.c +++ b/usr.sbin/ppp/ppp/deflate.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: deflate.c,v 1.11 2001/02/04 22:53:13 brian Exp $ + * $OpenBSD: deflate.c,v 1.12 2001/06/19 10:24:51 brian Exp $ */ #include <sys/types.h> @@ -57,7 +57,7 @@ static u_char EMPTY_BLOCK[4] = { 0x00, 0x00, 0xff, 0xff }; #define DEFLATE_CHUNK_LEN (1536 - sizeof(struct mbuf)) -static void +static int DeflateResetOutput(void *v) { struct deflate_state *state = (struct deflate_state *)v; @@ -66,6 +66,8 @@ DeflateResetOutput(void *v) state->uncomp_rec = 0; deflateReset(&state->cx); log_Printf(LogCCP, "Deflate: Output channel reset\n"); + + return 1; /* Ask FSM to ACK */ } static struct mbuf * @@ -451,7 +453,7 @@ DeflateInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) } static int -DeflateSetOptsOutput(struct lcp_opt *o) +DeflateSetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0') return MODE_REJ; @@ -554,7 +556,8 @@ const struct ccp_algorithm PppdDeflateAlgorithm = { TY_PPPD_DEFLATE, /* Older versions of pppd expected this ``type'' */ CCP_NEG_DEFLATE24, DeflateDispOpts, - ccp_IsUsable, + ccp_DefaultUsable, + ccp_DefaultRequired, { DeflateSetOptsInput, DeflateInitInput, @@ -577,7 +580,8 @@ const struct ccp_algorithm DeflateAlgorithm = { TY_DEFLATE, /* rfc 1979 */ CCP_NEG_DEFLATE, DeflateDispOpts, - ccp_IsUsable, + ccp_DefaultUsable, + ccp_DefaultRequired, { DeflateSetOptsInput, DeflateInitInput, diff --git a/usr.sbin/ppp/ppp/ether.c b/usr.sbin/ppp/ppp/ether.c index 79896af287e..cbc07f39df2 100644 --- a/usr.sbin/ppp/ppp/ether.c +++ b/usr.sbin/ppp/ppp/ether.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: ether.c,v 1.10 2001/06/04 16:09:28 brian Exp $ + * $OpenBSD: ether.c,v 1.11 2001/06/19 10:24:52 brian Exp $ */ #include <sys/param.h> @@ -285,6 +285,7 @@ ether_AwaitCarrier(struct physical *p) static const struct device baseetherdevice = { ETHER_DEVICE, "ether", + 1492, { CD_REQUIRED, DEF_ETHERCDDELAY }, ether_AwaitCarrier, ether_RemoveFromSet, @@ -675,16 +676,6 @@ ether_Create(struct physical *p) if (dev) { physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); - /* Moan about (and fix) invalid LCP configurations */ - if (p->link.lcp.cfg.mru > 1492) { - log_Printf(LogWARN, "%s: Reducing MRU to 1492\n", p->link.name); - p->link.lcp.cfg.mru = 1492; - } - if (p->dl->bundle->cfg.mtu > 1492) { - log_Printf(LogWARN, "%s: Reducing MTU to 1492\n", p->link.name); - p->dl->bundle->cfg.mtu = 1492; - } - if (path != NULL) { /* Mark the interface as UP if it's not already */ diff --git a/usr.sbin/ppp/ppp/exec.c b/usr.sbin/ppp/ppp/exec.c index 187999e2b1d..ff681b4ce40 100644 --- a/usr.sbin/ppp/ppp/exec.c +++ b/usr.sbin/ppp/ppp/exec.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: exec.c,v 1.15 2000/08/18 00:02:11 brian Exp $ + * $OpenBSD: exec.c,v 1.16 2001/06/19 10:24:52 brian Exp $ */ #include <sys/param.h> @@ -68,6 +68,7 @@ static struct device execdevice = { EXEC_DEVICE, "exec", + 0, { CD_NOTREQUIRED, 0 }, NULL, NULL, diff --git a/usr.sbin/ppp/ppp/fsm.c b/usr.sbin/ppp/ppp/fsm.c index 39444667ba2..687e1753ff8 100644 --- a/usr.sbin/ppp/ppp/fsm.c +++ b/usr.sbin/ppp/ppp/fsm.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: fsm.c,v 1.17 2001/06/13 21:33:41 brian Exp $ + * $OpenBSD: fsm.c,v 1.18 2001/06/19 10:24:52 brian Exp $ */ #include <sys/param.h> @@ -978,14 +978,15 @@ FsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) static void FsmRecvResetReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp) { - (*fp->fn->RecvResetReq)(fp); - /* - * All sendable compressed packets are queued in the first (lowest - * priority) modem output queue.... dump 'em to the priority queue - * so that they arrive at the peer before our ResetAck. - */ - link_SequenceQueue(fp->link); - fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0, MB_CCPOUT); + if ((*fp->fn->RecvResetReq)(fp)) { + /* + * All sendable compressed packets are queued in the first (lowest + * priority) modem output queue.... dump 'em to the priority queue + * so that they arrive at the peer before our ResetAck. + */ + link_SequenceQueue(fp->link); + fsm_Output(fp, CODE_RESETACK, lhp->id, NULL, 0, MB_CCPOUT); + } m_freem(bp); } @@ -1050,11 +1051,12 @@ fsm_Input(struct fsm *fp, struct mbuf *bp) (*codep->recv)(fp, &lh, bp); } -void +int fsm_NullRecvResetReq(struct fsm *fp) { log_Printf(fp->LogLevel, "%s: Oops - received unexpected reset req\n", fp->link->name); + return 1; } void diff --git a/usr.sbin/ppp/ppp/fsm.h b/usr.sbin/ppp/ppp/fsm.h index f9ee7d9f046..200dc15d1dd 100644 --- a/usr.sbin/ppp/ppp/fsm.h +++ b/usr.sbin/ppp/ppp/fsm.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: fsm.h,v 1.7 2001/06/13 21:33:41 brian Exp $ + * $OpenBSD: fsm.h,v 1.8 2001/06/19 10:24:53 brian Exp $ */ /* @@ -81,7 +81,7 @@ struct fsm_callbacks { 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 */ - void (*RecvResetReq) (struct fsm *fp); /* Reset output */ + int (*RecvResetReq) (struct fsm *fp); /* Reset output */ void (*RecvResetAck) (struct fsm *fp, u_char); /* Reset input */ }; @@ -174,7 +174,7 @@ extern void fsm_Up(struct fsm *); extern void fsm_Down(struct fsm *); extern void fsm_Input(struct fsm *, struct mbuf *); extern void fsm_Close(struct fsm *); -extern void fsm_NullRecvResetReq(struct fsm *); +extern int fsm_NullRecvResetReq(struct fsm *); extern void fsm_NullRecvResetAck(struct fsm *, u_char); extern void fsm_Reopen(struct fsm *); extern void fsm2initial(struct fsm *); diff --git a/usr.sbin/ppp/ppp/i4b.c b/usr.sbin/ppp/ppp/i4b.c index 3409962eadd..4ad4ba93807 100644 --- a/usr.sbin/ppp/ppp/i4b.c +++ b/usr.sbin/ppp/ppp/i4b.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: i4b.c,v 1.4 2000/08/16 13:53:58 brian Exp $ + * $OpenBSD: i4b.c,v 1.5 2001/06/19 10:24:53 brian Exp $ */ #include <sys/param.h> @@ -293,6 +293,7 @@ i4b_device2iov(struct device *d, struct iovec *iov, int *niov, static struct device basei4bdevice = { I4B_DEVICE, "i4b", + 0, { CD_REQUIRED, DEF_I4BCDDELAY }, i4b_AwaitCarrier, NULL, diff --git a/usr.sbin/ppp/ppp/iface.c b/usr.sbin/ppp/ppp/iface.c index a27f7ee4666..5cc07d90441 100644 --- a/usr.sbin/ppp/ppp/iface.c +++ b/usr.sbin/ppp/ppp/iface.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: iface.c,v 1.16 2001/06/04 16:09:28 brian Exp $ + * $OpenBSD: iface.c,v 1.17 2001/06/19 10:24:54 brian Exp $ */ #include <sys/param.h> @@ -163,8 +163,9 @@ iface_Create(const char *name) return NULL; } iface->name = strdup(name); - iface->flags = ifm->ifm_flags; iface->index = ifm->ifm_index; + iface->flags = ifm->ifm_flags; + iface->mtu = 0; iface->in_addrs = 0; iface->in_addr = NULL; } @@ -540,7 +541,7 @@ iface_Show(struct cmdargs const *arg) if_flags[f].value); flags &= ~if_flags[f].flag; } - prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", arg->bundle->mtu, + prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", iface->mtu, iface->in_addrs, iface->in_addrs == 1 ? "" : "es"); for (f = 0; f < iface->in_addrs; f++) { diff --git a/usr.sbin/ppp/ppp/iface.h b/usr.sbin/ppp/ppp/iface.h index 16b2e55f8bf..0b703ddf6e3 100644 --- a/usr.sbin/ppp/ppp/iface.h +++ b/usr.sbin/ppp/ppp/iface.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: iface.h,v 1.6 2001/03/28 09:52:56 brian Exp $ + * $OpenBSD: iface.h,v 1.7 2001/06/19 10:24:54 brian Exp $ */ struct ifa_msghdr; @@ -39,6 +39,7 @@ struct iface { char *name; /* Interface name (malloc'd) */ int index; /* Interface index */ int flags; /* Interface flags (IFF_*) */ + int mtu; /* struct tuninfo MTU */ int in_addrs; /* How many in_addr's */ struct iface_addr *in_addr; /* Array of addresses (malloc'd) */ diff --git a/usr.sbin/ppp/ppp/ip.c b/usr.sbin/ppp/ppp/ip.c index 87f4f4dc1ba..8961534286e 100644 --- a/usr.sbin/ppp/ppp/ip.c +++ b/usr.sbin/ppp/ppp/ip.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: ip.c,v 1.32 2001/06/13 21:33:41 brian Exp $ + * $OpenBSD: ip.c,v 1.33 2001/06/19 10:24:54 brian Exp $ */ #include <sys/param.h> @@ -906,6 +906,14 @@ ip_PushPacket(struct link *l, struct bundle *bundle) if (ipcp->fsm.state != ST_OPENED) return 0; + /* + * If ccp is not open but is required, do nothing. + */ + if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { + log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); + return 0; + } + queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; do { if (queue->top) { diff --git a/usr.sbin/ppp/ppp/lcp.c b/usr.sbin/ppp/ppp/lcp.c index bf2e59daa17..2d261c789b1 100644 --- a/usr.sbin/ppp/ppp/lcp.c +++ b/usr.sbin/ppp/ppp/lcp.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: lcp.c,v 1.25 2001/06/13 21:33:41 brian Exp $ + * $OpenBSD: lcp.c,v 1.26 2001/06/19 10:24:55 brian Exp $ */ #include <sys/param.h> @@ -177,7 +177,13 @@ lcp_ReportStatus(struct cmdargs const *arg) (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, "\n Defaults: MRU = %d (max %d), ", + lcp->cfg.mru, lcp->cfg.max_mru); + if (lcp->cfg.mtu) + prompt_Printf(arg->prompt, "MTU = %d (max %d), ", + lcp->cfg.mtu, lcp->cfg.max_mtu); + else + prompt_Printf(arg->prompt, "MTU = any (max %d), ", lcp->cfg.max_mtu); prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap); prompt_Printf(arg->prompt, " LQR period = %us, ", lcp->cfg.lqrperiod); @@ -241,6 +247,9 @@ lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l, bundle, l, parent, &lcp_Callbacks, lcp_TimerNames); lcp->cfg.mru = DEF_MRU; + lcp->cfg.max_mru = MAX_MRU; + lcp->cfg.mtu = 0; + lcp->cfg.max_mtu = MAX_MTU; lcp->cfg.accmap = 0; lcp->cfg.openmode = 1; lcp->cfg.lqrperiod = DEF_LQRPERIOD; @@ -266,11 +275,12 @@ lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l, void lcp_Setup(struct lcp *lcp, int openmode) { + struct physical *p = link2physical(lcp->fsm.link); + int phmtu = p ? physical_DeviceMTU(p) : 0; + lcp->fsm.open_mode = openmode; - lcp->his_mru = lcp->fsm.bundle->cfg.mtu; - if (!lcp->his_mru || lcp->his_mru > DEF_MRU) - lcp->his_mru = DEF_MRU; + lcp->his_mru = DEF_MRU; lcp->his_mrru = 0; lcp->his_magic = 0; lcp->his_lqrperiod = 0; @@ -281,13 +291,13 @@ lcp_Setup(struct lcp *lcp, int openmode) lcp->his_shortseq = 0; lcp->want_mru = lcp->cfg.mru; + if (phmtu && lcp->want_mru > phmtu) + lcp->want_mru = phmtu; 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) { - struct physical *p = link2physical(lcp->fsm.link); - lcp->his_accmap = 0xffffffff; lcp->want_accmap = lcp->cfg.accmap; lcp->his_protocomp = 0; @@ -592,15 +602,15 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, { /* Deal with incoming PROTO_LCP */ struct lcp *lcp = fsm2lcp(fp); - int type, length, sz, pos, op, callback_req; + int type, length, sz, pos, op, callback_req, mru_req; u_int32_t magic, accmap; - u_short mtu, mru, proto; + u_short mru, phmtu, proto; struct lqrreq *req; char request[20], desc[22]; struct mp *mp; struct physical *p = link2physical(fp->link); - sz = op = callback_req = 0; + sz = op = callback_req = mru_req = 0; while (plen >= sizeof(struct fsmconfig)) { type = *cp; @@ -626,7 +636,13 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, /* Ignore his previous reject so that we REQ next time */ lcp->his_reject &= ~(1 << type); - if (mru < MIN_MRU) { + if (mru > MAX_MRU) { + /* Push him down to MAX_MRU */ + lcp->his_mrru = MAX_MRU; + memcpy(dec->nakend, cp, 2); + ua_htons(&lcp->his_mrru, dec->nakend + 2); + dec->nakend += 4; + } else if (mru < MIN_MRU) { /* Push him up to MIN_MRU */ lcp->his_mrru = MIN_MRU; memcpy(dec->nakend, cp, 2); @@ -664,28 +680,41 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, break; case TY_MRU: + mru_req = 1; ua_ntohs(cp + 2, &mru); log_Printf(LogLCP, "%s %d\n", request, mru); switch (mode_type) { case MODE_REQ: - mtu = lcp->fsm.bundle->cfg.mtu; - if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) { + phmtu = p ? physical_DeviceMTU(p) : 0; + if (phmtu && mru > phmtu) { + lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : phmtu; + memcpy(dec->nakend, cp, 2); + ua_htons(&lcp->his_mru, dec->nakend + 2); + dec->nakend += 4; + } if (mru > lcp->cfg.max_mtu) { + lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : lcp->cfg.max_mtu; + memcpy(dec->nakend, cp, 2); + ua_htons(&lcp->his_mru, dec->nakend + 2); + dec->nakend += 4; + } else if (mru < MIN_MRU || mru < lcp->cfg.mtu) { /* Push him up to MTU or MIN_MRU */ - lcp->his_mru = mru < mtu ? mtu : MIN_MRU; + lcp->his_mru = mru < lcp->cfg.mtu ? lcp->cfg.mtu : MIN_MRU; memcpy(dec->nakend, cp, 2); ua_htons(&lcp->his_mru, dec->nakend + 2); dec->nakend += 4; } else { - lcp->his_mru = mtu ? mtu : mru; + lcp->his_mru = lcp->cfg.mtu ? lcp->cfg.mtu : mru; memcpy(dec->ackend, cp, 4); dec->ackend += 4; } break; case MODE_NAK: - if (mru > MAX_MRU) - lcp->want_mru = MAX_MRU; - else if (mru < MIN_MRU) + if (mru > lcp->cfg.max_mru) { + lcp->want_mru = lcp->cfg.max_mru; + if (p && lcp->want_mru > physical_DeviceMTU(p)) + lcp->want_mru = physical_DeviceMTU(p); + } else if (mru < MIN_MRU) lcp->want_mru = MIN_MRU; else lcp->want_mru = mru; @@ -1217,6 +1246,22 @@ reqreject: dec->nakend[-1] = 2; /* XXX: Silly ! */ } } + if (mode_type == MODE_REQ && !mru_req) { + mru = DEF_MRU; + phmtu = p ? physical_DeviceMTU(p) : 0; + if (phmtu && mru > phmtu) + mru = phmtu; + if (mru > lcp->cfg.max_mtu) + mru = lcp->cfg.max_mtu; + if (mru < DEF_MRU) { + /* Don't let the peer use the default MRU */ + lcp->his_mru = lcp->cfg.mtu && lcp->cfg.mtu < mru ? lcp->cfg.mtu : mru; + *dec->nakend++ = TY_MRU; + *dec->nakend++ = 4; + ua_htons(&lcp->his_mru, dec->nakend); + dec->nakend += 2; + } + } if (dec->rejend != dec->rej) { /* rejects are preferred */ dec->ackend = dec->ack; diff --git a/usr.sbin/ppp/ppp/lcp.h b/usr.sbin/ppp/ppp/lcp.h index b9ab2bc7cb0..505634ca7d7 100644 --- a/usr.sbin/ppp/ppp/lcp.h +++ b/usr.sbin/ppp/ppp/lcp.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: lcp.h,v 1.9 2001/06/13 21:33:41 brian Exp $ + * $OpenBSD: lcp.h,v 1.10 2001/06/19 10:24:55 brian Exp $ */ /* callback::opmask values */ @@ -82,6 +82,9 @@ struct lcp { struct { u_short mru; /* Preferred MRU value */ + u_short max_mru; /* Preferred MRU value */ + u_short mtu; /* Preferred MTU */ + u_short max_mtu; /* Preferred MTU */ u_int32_t accmap; /* Initial ACCMAP value */ int openmode; /* when to start CFG REQs */ u_int32_t lqrperiod; /* LQR frequency (seconds) */ diff --git a/usr.sbin/ppp/ppp/mppe.c b/usr.sbin/ppp/ppp/mppe.c index 97e03a6edff..b2e4392fbd2 100644 --- a/usr.sbin/ppp/ppp/mppe.c +++ b/usr.sbin/ppp/ppp/mppe.c @@ -23,13 +23,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: mppe.c,v 1.5 2001/02/04 22:53:13 brian Exp $ + * $OpenBSD: mppe.c,v 1.6 2001/06/19 10:24:56 brian Exp $ */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <termios.h> #ifdef __FreeBSD__ #include <sha.h> @@ -61,23 +62,53 @@ * draft-ietf-pppext-mppe-keys-02.txt */ +#define MPPE_OPT_STATELESS 0x1000000 +#define MPPE_OPT_COMPRESSED 0x01 +#define MPPE_OPT_40BIT 0x20 +#define MPPE_OPT_56BIT 0x80 +#define MPPE_OPT_128BIT 0x40 +#define MPPE_OPT_BITMASK 0xe0 +#define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK) + +#define MPPE_FLUSHED 0x8000 +#define MPPE_ENCRYPTED 0x1000 +#define MPPE_HEADER_BITMASK 0xf000 +#define MPPE_HEADER_FLAG 0x00ff +#define MPPE_HEADER_FLAGMASK 0x00ff +#define MPPE_HEADER_FLAGSHIFT 8 + struct mppe_state { - int cohnum; - int keylen; /* 8 or 16 bytes */ - int keybits; /* 40, 56 or 128 bits */ - char sesskey[MPPE_KEY_LEN]; - char mastkey[MPPE_KEY_LEN]; - RC4_KEY rc4key; + unsigned stateless : 1; + unsigned flushnext : 1; + unsigned flushrequired : 1; + int cohnum; + int keylen; /* 8 or 16 bytes */ + int keybits; /* 40, 56 or 128 bits */ + char sesskey[MPPE_KEY_LEN]; + char mastkey[MPPE_KEY_LEN]; + RC4_KEY rc4key; }; int MPPE_MasterKeyValid = 0; int MPPE_IsServer = 0; char MPPE_MasterKey[MPPE_KEY_LEN]; -static void +/* + * The peer has missed a packet. Mark the next output frame to be FLUSHED + */ +static int MPPEResetOutput(void *v) { - log_Printf(LogCCP, "MPPE: Output channel reset\n"); + struct mppe_state *mop = (struct mppe_state *)v; + + if (mop->stateless) + log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n"); + else { + log_Printf(LogCCP, "MPPE: Output channel reset\n"); + mop->flushnext = 1; + } + + return 0; /* Ask FSM not to ACK */ } static void @@ -112,17 +143,18 @@ MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, { struct mppe_state *mop = (struct mppe_state *)v; struct mbuf *mo; - u_short nproto; - int ilen; + u_short nproto, prefix; + int dictinit, ilen, len; char *rp; - log_Printf(LogCCP, "MPPE: Output\n"); - ilen = m_length(mp); + dictinit = 0; log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); if (*proto < 0x21 && *proto > 0xFA) { log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); + ccp->compout += ilen; + ccp->uncompout += ilen; return mp; } @@ -132,12 +164,32 @@ MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, mo = m_get(4, MB_CCPOUT); mo->m_next = mp; - /* Init RC4 keys */ - RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); + rp = MBUF_CTOP(mo); + prefix = MPPE_ENCRYPTED | mop->cohnum; + + if (mop->stateless || + (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { + /* Change our key */ + log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum); + MPPEKeyChange(mop); + dictinit = 1; + } + + if (mop->stateless || mop->flushnext) { + prefix |= MPPE_FLUSHED; + dictinit = 1; + mop->flushnext = 0; + } + + if (dictinit) { + /* Initialise our dictionary */ + log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n", + mop->cohnum); + RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); + } /* Set MPPE packet prefix */ - rp = MBUF_CTOP(mo); - *(u_short *)rp = htons(0x9000 | mop->cohnum); + *(u_short *)rp = htons(prefix); /* Save encrypted protocol number */ nproto = htons(*proto); @@ -147,15 +199,17 @@ MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, rp = MBUF_CTOP(mp); RC4(&mop->rc4key, ilen, rp, rp); - /* Rotate keys */ - MPPEKeyChange(mop); - mop->cohnum ++; mop->cohnum &= 0xFFF; + mop->cohnum++; + mop->cohnum &= ~MPPE_HEADER_BITMASK; - /* Chage protocol number */ + /* Set the protocol number */ *proto = ccp_Proto(ccp); + len = m_length(mo); + ccp->uncompout += ilen; + ccp->compout += len; log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", - *proto, m_length(mo)); + *proto, len); return mo; } @@ -163,7 +217,7 @@ MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, static void MPPEResetInput(void *v) { - log_Printf(LogCCP, "MPPE: Input channel reset\n"); + log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n"); } static struct mbuf * @@ -172,43 +226,126 @@ MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) struct mppe_state *mip = (struct mppe_state *)v; u_short prefix; char *rp; - int ilen; - - log_Printf(LogCCP, "MPPE: Input\n"); + int dictinit, flushed, ilen, len, n; ilen = m_length(mp); + dictinit = 0; + ccp->compin += ilen; log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); - log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); mp = mbuf_Read(mp, &prefix, 2); prefix = ntohs(prefix); - if ((prefix & 0xF000) != 0x9000) { - log_Printf(LogERROR, "MPPE: Input: Invalid packet\n"); + flushed = prefix & MPPE_FLUSHED; + prefix &= ~flushed; + if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) { + log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n", + (prefix & MPPE_HEADER_BITMASK) | flushed); m_freem(mp); return NULL; } - prefix &= 0xFFF; - while (prefix != mip->cohnum) { - MPPEKeyChange(mip); - mip->cohnum ++; mip->cohnum &= 0xFFF; + prefix &= ~MPPE_HEADER_BITMASK; + + if (!flushed && mip->stateless) { + log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set" + " in stateless mode\n"); + flushed = MPPE_FLUSHED; + /* Should we really continue ? */ + } + + if (mip->stateless) { + /* Change our key for each missed packet in stateless mode */ + while (prefix != mip->cohnum) { + log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); + MPPEKeyChange(mip); + /* + * mip->cohnum contains what we received last time in stateless + * mode. + */ + mip->cohnum++; + mip->cohnum &= ~MPPE_HEADER_BITMASK; + } + dictinit = 1; + } else { + if (flushed) { + /* + * We can always process a flushed packet. + * Catch up on any outstanding key changes. + */ + n = (prefix >> MPPE_HEADER_FLAGSHIFT) - + (mip->cohnum >> MPPE_HEADER_FLAGSHIFT); + while (n--) { + log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n", + prefix); + MPPEKeyChange(mip); + } + mip->flushrequired = 0; + mip->cohnum = prefix; + dictinit = 1; + } + + if (mip->flushrequired) { + /* + * Perhaps we should be lenient if + * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG + * The spec says that we shouldn't be though.... + */ + log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n"); + m_freem(mp); + return NULL; + } + + if (prefix != mip->cohnum) { + /* + * We're in stateful mode and didn't receive the expected + * packet. Send a reset request, but don't tell the CCP layer + * about it as we don't expect to receive a Reset ACK ! + * Guess what... M$ invented this ! + */ + log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n", + prefix, mip->cohnum); + fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0, + MB_CCPOUT); + mip->flushrequired = 1; + m_freem(mp); + return NULL; + } + + if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { + log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); + MPPEKeyChange(mip); + dictinit = 1; + } else if (flushed) + dictinit = 1; + + /* + * mip->cohnum contains what we expect to receive next time in stateful + * mode. + */ + mip->cohnum++; + mip->cohnum &= ~MPPE_HEADER_BITMASK; } - RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); + if (dictinit) { + log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix); + RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); + } mp = mbuf_Read(mp, proto, 2); RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); *proto = ntohs(*proto); rp = MBUF_CTOP(mp); - RC4(&mip->rc4key, m_length(mp), rp, rp); + len = m_length(mp); + RC4(&mip->rc4key, len, rp, rp); - log_Printf(LogDEBUG, "MPPE: Input: Decrypted: Proto %02x (%d bytes)\n", - *proto, m_length(mp)); + log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n", + *proto, len); + log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp); - log_DumpBp(LogDEBUG, "MPPE: Input: Decrypted: Packet:", mp); + ccp->uncompin += len; return mp; } @@ -216,14 +353,51 @@ MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) static void MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) { - log_Printf(LogCCP, "MPPE: DictSetup\n"); } static const char * MPPEDispOpts(struct lcp_opt *o) { - static char buf[32]; - sprintf(buf, "value 0x%08x", (int)ntohl(*(u_int32_t *)(o->data))); + static char buf[70]; + u_int32_t val = ntohl(*(u_int32_t *)o->data); + char ch; + int len; + + snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val); + len = strlen(buf); + if (!(val & MPPE_OPT_BITMASK)) { + snprintf(buf + len, sizeof buf - len, "(0"); + len++; + } else { + ch = '('; + if (val & MPPE_OPT_128BIT) { + snprintf(buf + len, sizeof buf - len, "%c128", ch); + len += strlen(buf + len); + ch = '/'; + } + if (val & MPPE_OPT_56BIT) { + snprintf(buf + len, sizeof buf - len, "%c56", ch); + len += strlen(buf + len); + ch = '/'; + } + if (val & MPPE_OPT_40BIT) { + snprintf(buf + len, sizeof buf - len, "%c40", ch); + len += strlen(buf + len); + ch = '/'; + } + } + + snprintf(buf + len, sizeof buf - len, " bits, state%s", + (val & MPPE_OPT_STATELESS) ? "less" : "full"); + len += strlen(buf + len); + + if (val & MPPE_OPT_COMPRESSED) { + snprintf(buf + len, sizeof buf - len, ", compressed"); + len += strlen(buf + len); + } + + snprintf(buf + len, sizeof buf - len, ")"); + return buf; } @@ -242,120 +416,213 @@ MPPEUsable(struct fsm *fp) return ok; } +static int +MPPERequired(struct fsm *fp) +{ + return fp->link->ccp.cfg.mppe.required; +} + +static u_int32_t +MPPE_ConfigVal(const struct ccp_config *cfg) +{ + u_int32_t val; + + val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0; + switch(cfg->mppe.keybits) { + case 128: + val |= MPPE_OPT_128BIT; + break; + case 56: + val |= MPPE_OPT_56BIT; + break; + case 40: + val |= MPPE_OPT_40BIT; + break; + case 0: + val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT; + break; + } + + return val; +} + +/* + * What options should we use for our first configure request + */ static void MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { - u_long val; + u_int32_t *p = (u_int32_t *)o->data; o->len = 6; - log_Printf(LogCCP, "MPPE: InitOptsOutput\n"); - if (!MPPE_MasterKeyValid) { log_Printf(LogCCP, "MPPE: MasterKey is invalid," " MPPE is available only with CHAP81 authentication\n"); - *(u_int32_t *)o->data = htonl(0x0); + *p = htonl(0x0); return; } - val = 0x1000000; - switch(cfg->mppe.keybits) { - case 128: - val |= 0x40; break; - case 56: - val |= 0x80; break; - case 40: - val |= 0x20; break; - } - *(u_int32_t *)o->data = htonl(val); + *p = htonl(MPPE_ConfigVal(cfg)); } +/* + * Our CCP request was NAK'd with the given options + */ static int -MPPESetOptsOutput(struct lcp_opt *o) +MPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { - u_long *p = (u_long *)(o->data); - u_long val = ntohl(*p); - - log_Printf(LogCCP, "MPPE: SetOptsOutput\n"); + u_int32_t *p = (u_int32_t *)o->data; + u_int32_t peer = ntohl(*p); + u_int32_t mval; + + if (!MPPE_MasterKeyValid) + /* Treat their NAK as a REJ */ + return MODE_NAK; + + mval = MPPE_ConfigVal(cfg); + + /* + * If we haven't been configured with a specific number of keybits, allow + * whatever the peer asks for. + */ + if (!cfg->mppe.keybits) { + mval &= ~MPPE_OPT_BITMASK; + mval |= (peer & MPPE_OPT_BITMASK); + if (!(mval & MPPE_OPT_BITMASK)) + mval |= MPPE_OPT_128BIT; + } - if (!MPPE_MasterKeyValid) { - if (*p != 0x0) { - *p = 0x0; - return MODE_NAK; - } else { - return MODE_ACK; - } + /* Adjust our statelessness */ + if (cfg->mppe.state == MPPE_ANYSTATE) { + mval &= ~MPPE_OPT_STATELESS; + mval |= (peer & MPPE_OPT_STATELESS); } - if (val == 0x01000020 || - val == 0x01000040 || - val == 0x01000080) - return MODE_ACK; + *p = htonl(mval); - return MODE_NAK; + return MODE_ACK; } +/* + * The peer has requested the given options + */ static int MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) { - u_long *p = (u_long *)(o->data); - u_long val = ntohl(*p); - u_long mval; - - log_Printf(LogCCP, "MPPE: SetOptsInput\n"); + u_int32_t *p = (u_int32_t *)(o->data); + u_int32_t peer = ntohl(*p); + u_int32_t mval; + int res = MODE_ACK; if (!MPPE_MasterKeyValid) { if (*p != 0x0) { *p = 0x0; return MODE_NAK; - } else { + } else return MODE_ACK; - } } - mval = 0x01000000; - switch(cfg->mppe.keybits) { - case 128: - mval |= 0x40; break; - case 56: - mval |= 0x80; break; - case 40: - mval |= 0x20; break; + mval = MPPE_ConfigVal(cfg); + + if (peer & ~MPPE_OPT_MASK) + /* He's asking for bits we don't know about */ + res = MODE_NAK; + + if (peer & MPPE_OPT_STATELESS) { + if (cfg->mppe.state == MPPE_STATEFUL) + /* Peer can't have stateless */ + res = MODE_NAK; + else + /* Peer wants stateless, that's ok */ + mval |= MPPE_OPT_STATELESS; + } else { + if (cfg->mppe.state == MPPE_STATELESS) + /* Peer must have stateless */ + res = MODE_NAK; + else + /* Peer doesn't want stateless, that's ok */ + mval &= ~MPPE_OPT_STATELESS; } - if (val == mval) - return MODE_ACK; + /* If we've got a configured number of keybits - the peer must use that */ + if (cfg->mppe.keybits) { + *p = htonl(mval); + return peer == mval ? res : MODE_NAK; + } + /* If a specific number of bits hasn't been requested, we'll need to NAK */ + switch (peer & MPPE_OPT_BITMASK) { + case MPPE_OPT_128BIT: + case MPPE_OPT_56BIT: + case MPPE_OPT_40BIT: + break; + default: + res = MODE_NAK; + } + + /* Suggest the best number of bits */ + mval &= ~MPPE_OPT_BITMASK; + if (peer & MPPE_OPT_128BIT) + mval |= MPPE_OPT_128BIT; + else if (peer & MPPE_OPT_56BIT) + mval |= MPPE_OPT_56BIT; + else if (peer & MPPE_OPT_40BIT) + mval |= MPPE_OPT_40BIT; + else + mval |= MPPE_OPT_128BIT; *p = htonl(mval); - return MODE_NAK; + return res; +} + +static struct mppe_state * +MPPE_InitState(struct lcp_opt *o) +{ + struct mppe_state *mp; + u_int32_t val; + + if ((mp = calloc(1, sizeof *mp)) != NULL) { + val = ntohl(*(u_int32_t *)o->data); + + switch (val & MPPE_OPT_BITMASK) { + case MPPE_OPT_128BIT: + mp->keylen = 16; + mp->keybits = 128; + break; + case MPPE_OPT_56BIT: + mp->keylen = 8; + mp->keybits = 56; + break; + case MPPE_OPT_40BIT: + mp->keylen = 8; + mp->keybits = 40; + break; + default: + log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val); + free(mp); + return NULL; + } + + mp->stateless = !!(val & MPPE_OPT_STATELESS); + } + + return mp; } static void * MPPEInitInput(struct lcp_opt *o) { struct mppe_state *mip; - u_int32_t val = ntohl(*(unsigned long *)o->data); - - log_Printf(LogCCP, "MPPE: InitInput\n"); if (!MPPE_MasterKeyValid) { log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); return NULL; } - mip = malloc(sizeof(*mip)); - memset(mip, 0, sizeof(*mip)); - - if (val & 0x20) { /* 40-bits */ - mip->keylen = 8; - mip->keybits = 40; - } else if (val & 0x80) { /* 56-bits */ - mip->keylen = 8; - mip->keybits = 56; - } else { /* 128-bits */ - mip->keylen = 16; - mip->keybits = 128; + if ((mip = MPPE_InitState(o)) == NULL) { + log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n"); + return NULL; } log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); @@ -366,9 +633,25 @@ MPPEInitInput(struct lcp_opt *o) MPPEReduceSessionKey(mip); - MPPEKeyChange(mip); - - mip->cohnum = 0; + log_Printf(LogCCP, "MPPE: Input channel initiated\n"); + + if (!mip->stateless) { + /* + * We need to initialise our dictionary here as the first packet we + * receive is unlikely to have the FLUSHED bit set. + */ + log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n", + mip->cohnum); + RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); + } else { + /* + * We do the first key change here as the first packet is expected + * to have a sequence number of 0 and we'll therefore not expect + * to have to change the key at that point. + */ + log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum); + MPPEKeyChange(mip); + } return mip; } @@ -377,27 +660,15 @@ static void * MPPEInitOutput(struct lcp_opt *o) { struct mppe_state *mop; - u_int32_t val = ntohl(*(unsigned long *)o->data); - - log_Printf(LogCCP, "MPPE: InitOutput\n"); if (!MPPE_MasterKeyValid) { log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); return NULL; } - mop = malloc(sizeof(*mop)); - memset(mop, 0, sizeof(*mop)); - - if (val & 0x20) { /* 40-bits */ - mop->keylen = 8; - mop->keybits = 40; - } else if (val & 0x80) { /* 56-bits */ - mop->keylen = 8; - mop->keybits = 56; - } else { /* 128-bits */ - mop->keylen = 16; - mop->keybits = 128; + if ((mop = MPPE_InitState(o)) == NULL) { + log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n"); + return NULL; } log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); @@ -408,9 +679,17 @@ MPPEInitOutput(struct lcp_opt *o) MPPEReduceSessionKey(mop); - MPPEKeyChange(mop); + log_Printf(LogCCP, "MPPE: Output channel initiated\n"); - mop->cohnum = 0; + if (!mop->stateless) { + /* + * We need to initialise our dictionary now as the first packet we + * send won't have the FLUSHED bit set. + */ + log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n", + mop->cohnum); + RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); + } return mop; } @@ -418,14 +697,12 @@ MPPEInitOutput(struct lcp_opt *o) static void MPPETermInput(void *v) { - log_Printf(LogCCP, "MPPE: TermInput\n"); free(v); } static void MPPETermOutput(void *v) { - log_Printf(LogCCP, "MPPE: TermOutput\n"); free(v); } @@ -434,6 +711,7 @@ const struct ccp_algorithm MPPEAlgorithm = { CCP_NEG_MPPE, MPPEDispOpts, MPPEUsable, + MPPERequired, { MPPESetOptsInput, MPPEInitInput, diff --git a/usr.sbin/ppp/ppp/physical.c b/usr.sbin/ppp/ppp/physical.c index 89332e6421d..2d13943e7aa 100644 --- a/usr.sbin/ppp/ppp/physical.c +++ b/usr.sbin/ppp/ppp/physical.c @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $OpenBSD: physical.c,v 1.29 2001/03/24 01:06:03 brian Exp $ + * $OpenBSD: physical.c,v 1.30 2001/06/19 10:24:56 brian Exp $ * */ @@ -758,6 +758,12 @@ physical_IsSync(struct physical *p) return p->cfg.speed == 0; } +u_short +physical_DeviceMTU(struct physical *p) +{ + return p->handler ? p->handler->mtu : 0; +} + const char *physical_GetDevice(struct physical *p) { return p->name.full; diff --git a/usr.sbin/ppp/ppp/physical.h b/usr.sbin/ppp/ppp/physical.h index 4816093b5a4..34025a577b2 100644 --- a/usr.sbin/ppp/ppp/physical.h +++ b/usr.sbin/ppp/ppp/physical.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $OpenBSD: physical.h,v 1.17 2000/09/14 22:02:50 brian Exp $ + * $OpenBSD: physical.h,v 1.18 2001/06/19 10:24:56 brian Exp $ * */ @@ -56,6 +56,7 @@ struct cd { struct device { int type; const char *name; + u_short mtu; struct cd cd; int (*awaitcarrier)(struct physical *); @@ -143,6 +144,7 @@ extern const char *physical_LockedDevice(struct physical *); extern void physical_ChangedPid(struct physical *, pid_t); extern int physical_IsSync(struct physical *); +extern u_short physical_DeviceMTU(struct physical *); extern const char *physical_GetDevice(struct physical *); extern void physical_SetDeviceList(struct physical *, int, const char *const *); extern void physical_SetDevice(struct physical *, const char *); diff --git a/usr.sbin/ppp/ppp/ppp.8 b/usr.sbin/ppp/ppp/ppp.8 index 131a966df5c..ded98a9554c 100644 --- a/usr.sbin/ppp/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp/ppp.8 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: ppp.8,v 1.111 2001/06/07 09:32:55 brian Exp $ +.\" $OpenBSD: ppp.8,v 1.112 2001/06/19 10:24:57 brian Exp $ .\" .Dd September 20, 1995 .Dt PPP 8 @@ -4910,39 +4910,93 @@ This will allow to do the necessary address translations to enable the process that triggers the connection to connect once the link is up despite the peer assigning us a new (dynamic) IP address. -.It set mppe {40|56|128} -This option selects particular key length. Default is 128. +.It set mppe Op 40|56|128|* Op stateless|statefull|* +This option selects the encryption parameters used when negotiation +MPPE. MPPE can be disabled entirely with the +.Dq disable mppe +command. +If no arguments are given, +.Nm +will attempt to negotiate a statefull link with a 128 bit key, but +will agree to whatever the peer requests (including no encryption +at all). +.Pp +If any arguments are given, +.Nm +will +.Em insist +on using MPPE and will close the link if it's rejected by the peer. +.Pp +The first argument specifies the number of bits that +.Nm +should insist on during negotiations and the second specifies whether +.Nm +should insist on statefull or stateless mode. In stateless mode, the +encryption dictionary is re-initialised with every packet according to +an encryption key that is changed with every packet. In statefull mode, +the encryption dictionary is re-initialised every 256 packets or after +the loss of any data and the key is changed every 256 packets. +Stateless mode is less efficient but is better for unreliable transport +layers. .It set mrru Op Ar value Setting this option enables Multi-link PPP negotiations, also known as Multi-link Protocol or MP. There is no default MRRU (Maximum Reconstructed Receive Unit) value. If no argument is given, multi-link mode is disabled. -.It set mru Op Ar value +.It set mru Oo max Ns Oo imum Oc Oc Op Ar value The default MRU (Maximum Receive Unit) is 1500. If it is increased, the other side *may* increase its MTU. -There is no point in decreasing the MRU to below the default as the +In theory there is no point in decreasing the MRU to below the default as the .Em PPP -protocol *must* be able to accept packets of at least 1500 octets. +protocol says implementations *must* be able to accept packets of at +least 1500 octets. +.Pp +If the +.Dq maximum +keyword is used, +.Nm +will refuse to negotiate a higher value. +The maximum MRU can be set to 2048 at most. +Setting a maximum of less than 1500 violates the +.Em PPP +rfc, but may sometimes be necessary. +For example, +.Em PPPoE +imposes a maximum of 1492 due to hardware limitations. +.Pp If no argument is given, 1500 is assumed. -.It set mtu Op Ar value +A value must be given when +.Dq maximum +is specified. +.It set mtu Oo max Ns Oo imum Oc Oc Op Ar value The default MTU is 1500. At negotiation time, .Nm -will accept whatever MRU or MRRU that the peer wants (assuming it's -not less than 296 bytes). +will accept whatever MRU the peer requests (assuming it's +not less than 296 bytes or greater than the assigned maximum). If the MTU is set, .Nm -will not accept MRU/MRRU values less than +will not accept MRU values less than .Ar value . -When negotiations are complete, the MTU is assigned to the interface, even -if the peer requested a higher value MRU/MRRU. +When negotiations are complete, the MTU is used when writing to the +interface, even if the peer requested a higher value MRU. This can be useful for limiting your packet size (giving better bandwidth sharing at the expense of more header data). .Pp +If the +.Dq maximum +keyword is used, +.Nm +will refuse to negotiate a higher value. +The maximum MTU can be set to 2048 at most. +.Pp If no .Ar value is given, 1500, or whatever the peer asks for is used. +A value must be given when +.Dq maximum +is specified. .It set nbns Op Ar x.x.x.x Op Ar y.y.y.y This option allows the setting of the Microsoft NetBIOS name server values to be returned at the peers request. diff --git a/usr.sbin/ppp/ppp/pred.c b/usr.sbin/ppp/ppp/pred.c index 5645b53cba9..c6b6150ce8f 100644 --- a/usr.sbin/ppp/ppp/pred.c +++ b/usr.sbin/ppp/ppp/pred.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: pred.c,v 1.10 2001/02/04 22:53:13 brian Exp $ + * $OpenBSD: pred.c,v 1.11 2001/06/19 10:24:57 brian Exp $ */ #include <sys/types.h> @@ -139,13 +139,15 @@ Pred1ResetInput(void *v) log_Printf(LogCCP, "Predictor1: Input channel reset\n"); } -static void +static int Pred1ResetOutput(void *v) { struct pred1_state *state = (struct pred1_state *)v; state->hash = 0; memset(state->dict, '\0', sizeof state->dict); log_Printf(LogCCP, "Predictor1: Output channel reset\n"); + + return 1; /* Ask FSM to ACK */ } static void * @@ -304,7 +306,7 @@ Pred1InitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) } static int -Pred1SetOptsOutput(struct lcp_opt *o) +Pred1SetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { if (o->len != 2) { o->len = 2; @@ -316,14 +318,19 @@ Pred1SetOptsOutput(struct lcp_opt *o) static int Pred1SetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) { - return Pred1SetOptsOutput(o); + if (o->len != 2) { + o->len = 2; + return MODE_NAK; + } + return MODE_ACK; } const struct ccp_algorithm Pred1Algorithm = { TY_PRED1, CCP_NEG_PRED1, Pred1DispOpts, - ccp_IsUsable, + ccp_DefaultUsable, + ccp_DefaultRequired, { Pred1SetOptsInput, Pred1InitInput, diff --git a/usr.sbin/ppp/ppp/route.c b/usr.sbin/ppp/ppp/route.c index 3334a985080..515c5dfcb5f 100644 --- a/usr.sbin/ppp/ppp/route.c +++ b/usr.sbin/ppp/ppp/route.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: route.c,v 1.12 2001/06/13 21:33:42 brian Exp $ + * $OpenBSD: route.c,v 1.13 2001/06/19 10:24:58 brian Exp $ */ #include <sys/param.h> @@ -577,9 +577,8 @@ route_UpdateMTU(struct bundle *bundle) log_Printf(LogTCPIP, "route_UpdateMTU: Netif: %d (%s), dst %s, mtu %d\n", rtm->rtm_index, Index2Nam(rtm->rtm_index), inet_ntoa(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr), - bundle->mtu); - rt_Update(bundle, in[RTAX_DST]->sin_addr, - in[RTAX_GATEWAY]->sin_addr); + bundle->iface->mtu); + rt_Update(bundle, in[RTAX_DST]->sin_addr, in[RTAX_GATEWAY]->sin_addr); } } @@ -890,7 +889,7 @@ rt_Update(struct bundle *bundle, struct in_addr dst, struct in_addr gw) rtmes.m_rtm.rtm_inits |= RTV_RPIPE; } - rtmes.m_rtm.rtm_rmx.rmx_mtu = bundle->mtu; + rtmes.m_rtm.rtm_rmx.rmx_mtu = bundle->iface->mtu; rtmes.m_rtm.rtm_inits |= RTV_MTU; memset(&rtdata, '\0', sizeof rtdata); diff --git a/usr.sbin/ppp/ppp/tcp.c b/usr.sbin/ppp/ppp/tcp.c index ca231142a66..1eafedac274 100644 --- a/usr.sbin/ppp/ppp/tcp.c +++ b/usr.sbin/ppp/ppp/tcp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: tcp.c,v 1.10 2001/03/24 01:06:08 brian Exp $ + * $OpenBSD: tcp.c,v 1.11 2001/06/19 10:24:59 brian Exp $ */ #include <sys/types.h> @@ -100,6 +100,7 @@ tcp_OpenConnection(const char *name, char *host, char *port) static struct device tcpdevice = { TCP_DEVICE, "tcp", + 0, { CD_NOTREQUIRED, 0 }, NULL, NULL, diff --git a/usr.sbin/ppp/ppp/tcpmss.c b/usr.sbin/ppp/ppp/tcpmss.c index ed7ef46b0a1..f8debc8805e 100644 --- a/usr.sbin/ppp/ppp/tcpmss.c +++ b/usr.sbin/ppp/ppp/tcpmss.c @@ -28,6 +28,8 @@ #include <sys/param.h> +#include <sys/socket.h> +#include <net/route.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -54,6 +56,7 @@ #include "filter.h" #include "descriptor.h" #include "mp.h" +#include "iface.h" #ifndef NORADIUS #include "radius.h" #endif @@ -93,7 +96,7 @@ tcpmss_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp, ntohs(pip->ip_len) == plen && hlen <= plen && plen - hlen >= sizeof(struct tcphdr)) MSSFixup((struct tcphdr *)(MBUF_CTOP(bp) + hlen), plen - hlen, - MAXMSS(bundle->mtu)); + MAXMSS(bundle->iface->mtu)); return bp; } diff --git a/usr.sbin/ppp/ppp/tty.c b/usr.sbin/ppp/ppp/tty.c index f843a5c5fee..951a1a6248c 100644 --- a/usr.sbin/ppp/ppp/tty.c +++ b/usr.sbin/ppp/ppp/tty.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: tty.c,v 1.15 2000/11/02 00:54:35 brian Exp $ + * $OpenBSD: tty.c,v 1.16 2001/06/19 10:25:00 brian Exp $ */ #include <sys/param.h> @@ -333,6 +333,7 @@ tty_device2iov(struct device *d, struct iovec *iov, int *niov, static struct device basettydevice = { TTY_DEVICE, "tty", + 0, { CD_VARIABLE, DEF_TTYCDDELAY }, tty_AwaitCarrier, NULL, diff --git a/usr.sbin/ppp/ppp/tun.c b/usr.sbin/ppp/ppp/tun.c index 896428eaf32..ee4ef0bfb05 100644 --- a/usr.sbin/ppp/ppp/tun.c +++ b/usr.sbin/ppp/ppp/tun.c @@ -23,14 +23,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: tun.c,v 1.11 2001/03/24 01:06:08 brian Exp $ + * $OpenBSD: tun.c,v 1.12 2001/06/19 10:25:01 brian Exp $ */ #include <sys/param.h> -#ifndef __FreeBSD__ + #include <sys/socket.h> /* For IFF_ defines */ +#ifndef __FreeBSD__ #include <net/if.h> /* For IFF_ defines */ #endif +#include <net/route.h> #include <netinet/in.h> #include <net/if_types.h> #include <net/if_tun.h> @@ -68,6 +70,7 @@ #include "ccp.h" #include "link.h" #include "mp.h" +#include "iface.h" #ifndef NORADIUS #include "radius.h" #endif @@ -89,7 +92,7 @@ tun_configure(struct bundle *bundle) } sprintf(ifr.ifr_name, "tun%d", bundle->unit); - ifr.ifr_mtu = bundle->mtu; + ifr.ifr_mtu = bundle->iface->mtu; if (ioctl(s, SIOCSIFMTU, &ifr) < 0) log_Printf(LogERROR, "tun_configure: ioctl(SIOCSIFMTU): %s\n", strerror(errno)); @@ -100,7 +103,7 @@ tun_configure(struct bundle *bundle) memset(&info, '\0', sizeof info); info.type = IFT_PPP; - info.mtu = bundle->mtu; + info.mtu = bundle->iface->mtu; info.baudrate = bundle->bandwidth; #ifdef __OpenBSD__ diff --git a/usr.sbin/ppp/ppp/udp.c b/usr.sbin/ppp/ppp/udp.c index 9d5ce6a5914..cf5a9feb850 100644 --- a/usr.sbin/ppp/ppp/udp.c +++ b/usr.sbin/ppp/ppp/udp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: udp.c,v 1.9 2001/03/24 01:06:09 brian Exp $ + * $OpenBSD: udp.c,v 1.10 2001/06/19 10:25:01 brian Exp $ */ #include <sys/types.h> @@ -154,6 +154,7 @@ udp_device2iov(struct device *d, struct iovec *iov, int *niov, static const struct device baseudpdevice = { UDP_DEVICE, "udp", + 0, { CD_NOTREQUIRED, 0 }, NULL, NULL, |