diff options
| author | Brian Somers <brian@FreeBSD.org> | 2001-07-09 01:37:18 +0000 |
|---|---|---|
| committer | Brian Somers <brian@FreeBSD.org> | 2001-07-09 01:37:18 +0000 |
| commit | 6ba3c70f82860e162a1ae0d8a1092ab80971db45 (patch) | |
| tree | f44569aac37f15b7eddf1a2b590eeb7e3f804bdc | |
| parent | baabe56244d4b11ed0e592488aebb60edfede66c (diff) | |
Notes
| -rw-r--r-- | usr.sbin/ppp/bundle.c | 45 | ||||
| -rw-r--r-- | usr.sbin/ppp/bundle.h | 2 | ||||
| -rw-r--r-- | usr.sbin/ppp/ccp.c | 168 | ||||
| -rw-r--r-- | usr.sbin/ppp/ccp.h | 21 | ||||
| -rw-r--r-- | usr.sbin/ppp/command.c | 289 | ||||
| -rw-r--r-- | usr.sbin/ppp/datalink.c | 3 | ||||
| -rw-r--r-- | usr.sbin/ppp/deflate.c | 14 | ||||
| -rw-r--r-- | usr.sbin/ppp/ether.c | 11 | ||||
| -rw-r--r-- | usr.sbin/ppp/exec.c | 1 | ||||
| -rw-r--r-- | usr.sbin/ppp/fsm.c | 20 | ||||
| -rw-r--r-- | usr.sbin/ppp/fsm.h | 4 | ||||
| -rw-r--r-- | usr.sbin/ppp/i4b.c | 1 | ||||
| -rw-r--r-- | usr.sbin/ppp/iface.c | 5 | ||||
| -rw-r--r-- | usr.sbin/ppp/iface.h | 1 | ||||
| -rw-r--r-- | usr.sbin/ppp/ip.c | 8 | ||||
| -rw-r--r-- | usr.sbin/ppp/ipcp.c | 142 | ||||
| -rw-r--r-- | usr.sbin/ppp/lcp.c | 79 | ||||
| -rw-r--r-- | usr.sbin/ppp/lcp.h | 3 | ||||
| -rw-r--r-- | usr.sbin/ppp/log.c | 6 | ||||
| -rw-r--r-- | usr.sbin/ppp/mp.c | 7 | ||||
| -rw-r--r-- | usr.sbin/ppp/mppe.c | 534 | ||||
| -rw-r--r-- | usr.sbin/ppp/physical.c | 6 | ||||
| -rw-r--r-- | usr.sbin/ppp/physical.h | 2 | ||||
| -rw-r--r-- | usr.sbin/ppp/ppp.8 | 102 | ||||
| -rw-r--r-- | usr.sbin/ppp/pred.c | 16 | ||||
| -rw-r--r-- | usr.sbin/ppp/route.c | 7 | ||||
| -rw-r--r-- | usr.sbin/ppp/tcp.c | 1 | ||||
| -rw-r--r-- | usr.sbin/ppp/tcpmss.c | 5 | ||||
| -rw-r--r-- | usr.sbin/ppp/tty.c | 1 | ||||
| -rw-r--r-- | usr.sbin/ppp/tun.c | 9 | ||||
| -rw-r--r-- | usr.sbin/ppp/udp.c | 1 |
31 files changed, 1125 insertions, 389 deletions
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index f8d8ad62fda3..ba1eca594b13 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -276,7 +276,8 @@ bundle_LayerUp(void *v, struct fsm *fp) bundle_StartIdleTimer(bundle, 0); bundle_Notify(bundle, EX_NORMAL); mp_CheckAutoloadTimer(&fp->bundle->ncp.mp); - } + } else if (fp->proto == PROTO_CCP) + bundle_CalculateBandwidth(fp->bundle); /* Against ccp_MTUOverhead */ } static void @@ -802,7 +803,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 +821,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 +1095,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) @@ -1823,11 +1817,16 @@ void bundle_CalculateBandwidth(struct bundle *bundle) { struct datalink *dl; - int sp; + int sp, overhead, maxoverhead; bundle->bandwidth = 0; - bundle->mtu = 0; - for (dl = bundle->links; dl; dl = dl->next) + bundle->iface->mtu = 0; + maxoverhead = 0; + + for (dl = bundle->links; dl; dl = dl->next) { + overhead = ccp_MTUOverhead(&dl->physical->link.ccp); + if (maxoverhead < overhead) + maxoverhead = overhead; if (dl->state == DATALINK_OPEN) { if ((sp = dl->mp.bandwidth) == 0 && (sp = physical_GetSpeed(dl->physical)) == 0) @@ -1836,28 +1835,38 @@ 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; } } + } if(bundle->bandwidth == 0) bundle->bandwidth = 115200; /* Shrug */ - if (bundle->ncp.mp.active) - bundle->mtu = bundle->ncp.mp.peer_mrru; - else if (!bundle->mtu) - bundle->mtu = 1500; + if (bundle->ncp.mp.active) { + bundle->iface->mtu = bundle->ncp.mp.peer_mrru; + overhead = ccp_MTUOverhead(&bundle->ncp.mp.link.ccp); + if (maxoverhead < overhead) + maxoverhead = overhead; + } 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 + if (maxoverhead) { + log_Printf(LogLCP, "Reducing MTU from %d to %d (CCP requirement)\n", + bundle->iface->mtu, bundle->iface->mtu - maxoverhead); + bundle->iface->mtu -= maxoverhead; + } + tun_configure(bundle); route_UpdateMTU(bundle); diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h index 29536315d34a..de8cb130f01d 100644 --- a/usr.sbin/ppp/bundle.h +++ b/usr.sbin/ppp/bundle.h @@ -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/ccp.c b/usr.sbin/ppp/ccp.c index 4e4a806e80dd..278fd506ef1e 100644 --- a/usr.sbin/ppp/ccp.c +++ b/usr.sbin/ppp/ccp.c @@ -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, "stateful"); + 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,43 @@ 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; +} + +/* + * Report whether it's possible to increase a packet's size after + * compression (and by how much). + */ +int +ccp_MTUOverhead(struct ccp *ccp) +{ + if (ccp->fsm.state == ST_OPENED && ccp->out.algorithm >= 0) + return algorithm[ccp->out.algorithm]->o.MTUOverhead; + + return 0; +} + static void CcpInitRestartCounter(struct fsm *fp, int what) { @@ -332,13 +406,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 +472,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 */ @@ -406,7 +487,24 @@ CcpLayerUp(struct fsm *fp) /* We're now up */ struct ccp *ccp = fsm2ccp(fp); struct ccp_opt **o; - int f; + int f, fail; + + for (f = fail = 0; f < NALGORITHMS; f++) + if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && + (*algorithm[f]->Required)(&ccp->fsm) && + (ccp->in.algorithm != f || ccp->out.algorithm != f)) { + /* Blow it all away - we haven't negotiated a required algorithm */ + log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", + fp->link->name, protoname(algorithm[f]->id)); + fail = 1; + } + + if (fail) { + ccp->his_proto = ccp->my_proto = -1; + fsm_Close(fp); + fsm_Close(&fp->link->lcp.fsm); + return 0; + } log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); @@ -531,17 +629,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 +727,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 +824,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/ccp.h b/usr.sbin/ppp/ccp.h index ac2ecf71bdc3..bb4f08bac588 100644 --- a/usr.sbin/ppp/ccp.h +++ b/usr.sbin/ppp/ccp.h @@ -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 *); @@ -124,11 +135,12 @@ struct ccp_algorithm { void (*DictSetup)(void *, struct ccp *, u_short, struct mbuf *); } i; struct { + int MTUOverhead; 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 +149,8 @@ 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 int ccp_MTUOverhead(struct ccp *); extern void ccp_SendResetReq(struct fsm *); extern struct mbuf *ccp_Input(struct bundle *, struct link *, struct mbuf *); @@ -144,6 +158,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/command.c b/usr.sbin/ppp/command.c index 4f205f5ddfb9..48b2c93342ef 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -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 *); @@ -1488,10 +1488,10 @@ static int SetVariable(struct cmdargs const *arg) { long long_val, param = (long)arg->cmd->args; - int mode, dummyint, f, first; + int mode, dummyint, f, first, res; + u_short *change; const char *argp; struct datalink *cx = arg->cx; /* LOCAL_CX uses this */ - const char *err = NULL; struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */ struct in_addr dummyaddr, *addr; @@ -1500,6 +1500,8 @@ SetVariable(struct cmdargs const *arg) else argp = ""; + res = 0; + if ((arg->cmd->lauth & LOCAL_CX) && !cx) { log_Printf(LogWARN, "set %s: No context (use the `link' command)\n", arg->cmd->name); @@ -1541,14 +1543,16 @@ SetVariable(struct cmdargs const *arg) if (v1 < 0 || *end) { log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", arg->argv[arg->argn]); - return 1; + res = 1; + break; } v2 = strtol(arg->argv[arg->argn + 1], &end, 0); if (v2 < 0 || *end) { log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", arg->argv[arg->argn + 1]); - return 1; + res = 1; + break; } if (v2 < v1) { v3 = v1; @@ -1560,7 +1564,8 @@ SetVariable(struct cmdargs const *arg) if (v3 <= 0 || *end) { log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", arg->argv[arg->argn + 2]); - return 1; + res = 1; + break; } arg->bundle->ncp.mp.cfg.autoload.min = v1; @@ -1568,8 +1573,8 @@ SetVariable(struct cmdargs const *arg) arg->bundle->ncp.mp.cfg.autoload.period = v3; mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); } else { - err = "Set autoload requires three arguments\n"; - log_Printf(LogWARN, err); + log_Printf(LogWARN, "Set autoload requires three arguments\n"); + res = 1; } break; @@ -1603,26 +1608,53 @@ SetVariable(struct cmdargs const *arg) } else l->ccp.cfg.deflate.in.winsize = 0; } else { - err = "No window size specified\n"; - log_Printf(LogWARN, err); + log_Printf(LogWARN, "No window size specified\n"); + res = 1; } 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) { + res = -1; + break; + } + + 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); + res = -1; + break; } - } 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], "stateful")) + l->ccp.cfg.mppe.state = MPPE_STATEFUL; + else { + log_Printf(LogWARN, "%s: Invalid state value\n", + arg->argv[arg->argn + 1]); + res = -1; + break; + } + } else + l->ccp.cfg.mppe.state = MPPE_ANYSTATE; + l->ccp.cfg.mppe.keybits = long_val; + l->ccp.cfg.mppe.required = 1; break; #endif @@ -1637,8 +1669,8 @@ SetVariable(struct cmdargs const *arg) sscanf(argp, "%lx", &ulong_val); cx->physical->link.lcp.cfg.accmap = (u_int32_t)ulong_val; } else { - err = "No accmap specified\n"; - log_Printf(LogWARN, err); + log_Printf(LogWARN, "No accmap specified\n"); + res = 1; } break; @@ -1646,7 +1678,8 @@ SetVariable(struct cmdargs const *arg) mode = Nam2mode(argp); if (mode == PHYS_NONE || mode == PHYS_ALL) { log_Printf(LogWARN, "%s: Invalid mode\n", argp); - return -1; + res = -1; + break; } bundle_SetMode(arg->bundle, cx, mode); break; @@ -1659,48 +1692,141 @@ SetVariable(struct cmdargs const *arg) /* Make sure none of our links are DATALINK_LCP or greater */ if (bundle_HighestState(arg->bundle) >= DATALINK_LCP) { log_Printf(LogWARN, "mrru: Only changable before LCP negotiations\n"); - return 1; + res = 1; + break; } break; default: log_Printf(LogWARN, "mrru: Only changable at phase DEAD/ESTABLISH\n"); - return 1; + res = 1; + break; } + if (res != 0) + break; long_val = atol(argp); if (long_val && long_val < MIN_MRU) { log_Printf(LogWARN, "MRRU %ld: too small - min %d\n", long_val, MIN_MRU); - return 1; + res = 1; + break; } else if (long_val > MAX_MRU) { log_Printf(LogWARN, "MRRU %ld: too big - max %d\n", long_val, MAX_MRU); - return 1; + res = 1; + break; } else arg->bundle->ncp.mp.cfg.mrru = long_val; break; case VAR_MRU: - long_val = atol(argp); + long_val = 0; /* silence gcc */ + change = NULL; /* silence gcc */ + switch(arg->argc - arg->argn) { + case 1: + if (argp[strspn(argp, "0123456789")] != '\0') { + res = -1; + break; + } + /*FALLTHRU*/ + 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); + res = 1; + break; + } + break; + case 2: + if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { + res = -1; + break; + } + 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); + res = 1; + break; + } + break; + default: + res = -1; + break; + } + if (res != 0) + break; + 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; + res = 1; + break; } else if (long_val > MAX_MRU) { log_Printf(LogWARN, "MRU %ld: too big - max %d\n", long_val, MAX_MRU); - return 1; + res = 1; + break; } 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); + long_val = 0; /* silence gcc */ + change = NULL; /* silence gcc */ + switch(arg->argc - arg->argn) { + case 1: + if (argp[strspn(argp, "0123456789")] != '\0') { + res = -1; + break; + } + /*FALLTHRU*/ + 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); + res = 1; + break; + } + break; + case 2: + if (strcasecmp(argp, "max") && strcasecmp(argp, "maximum")) { + res = -1; + break; + } + 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); + res = 1; + break; + } + break; + default: + res = -1; + break; + } + + if (res != 0) + break; + if (long_val && long_val < MIN_MTU) { log_Printf(LogWARN, "MTU %ld: too small - min %d\n", long_val, MIN_MTU); - return 1; + res = 1; + break; } else if (long_val > MAX_MTU) { log_Printf(LogWARN, "MTU %ld: too big - max %d\n", long_val, MAX_MTU); - return 1; + res = 1; + break; } 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: @@ -1710,8 +1836,8 @@ SetVariable(struct cmdargs const *arg) else if (strcasecmp(argp, "passive") == 0) cx->physical->link.lcp.cfg.openmode = OPEN_PASSIVE; else { - err = "%s: Invalid openmode\n"; - log_Printf(LogWARN, err, argp); + log_Printf(LogWARN, "%s: Invalid openmode\n", argp); + res = 1; } break; @@ -1737,19 +1863,19 @@ SetVariable(struct cmdargs const *arg) break; case VAR_IDLETIMEOUT: - if (arg->argc > arg->argn+2) - err = "Too many idle timeout values\n"; - else if (arg->argc == arg->argn) - err = "Too few idle timeout values\n"; - else { + if (arg->argc > arg->argn+2) { + log_Printf(LogWARN, "Too many idle timeout values\n"); + res = 1; + } else if (arg->argc == arg->argn) { + log_Printf(LogWARN, "Too few idle timeout values\n"); + res = 1; + } else { int timeout, min; timeout = atoi(argp); min = arg->argc == arg->argn + 2 ? atoi(arg->argv[arg->argn + 1]) : -1; bundle_SetIdleTimer(arg->bundle, timeout, min); } - if (err) - log_Printf(LogWARN, err); break; case VAR_LQRPERIOD: @@ -1757,41 +1883,41 @@ SetVariable(struct cmdargs const *arg) if (long_val < MIN_LQRPERIOD) { log_Printf(LogWARN, "%ld: Invalid lqr period - min %d\n", long_val, MIN_LQRPERIOD); - return 1; + res = 1; } else l->lcp.cfg.lqrperiod = long_val; break; case VAR_LCPRETRY: - return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, - &cx->physical->link.lcp.cfg.fsm.timeout, - &cx->physical->link.lcp.cfg.fsm.maxreq, - &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); + res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, + &cx->physical->link.lcp.cfg.fsm.timeout, + &cx->physical->link.lcp.cfg.fsm.maxreq, + &cx->physical->link.lcp.cfg.fsm.maxtrm, DEF_FSMTRIES); break; case VAR_CHAPRETRY: - return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, - &cx->chap.auth.cfg.fsm.timeout, - &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); + res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, + &cx->chap.auth.cfg.fsm.timeout, + &cx->chap.auth.cfg.fsm.maxreq, NULL, DEF_FSMAUTHTRIES); break; case VAR_PAPRETRY: - return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, - &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, - NULL, DEF_FSMAUTHTRIES); + res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, + &cx->pap.cfg.fsm.timeout, &cx->pap.cfg.fsm.maxreq, + NULL, DEF_FSMAUTHTRIES); break; case VAR_CCPRETRY: - return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, - &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, - &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); + res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, + &l->ccp.cfg.fsm.timeout, &l->ccp.cfg.fsm.maxreq, + &l->ccp.cfg.fsm.maxtrm, DEF_FSMTRIES); break; case VAR_IPCPRETRY: - return SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, - &arg->bundle->ncp.ipcp.cfg.fsm.timeout, - &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, - &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); + res = SetRetry(arg->argc - arg->argn, arg->argv + arg->argn, + &arg->bundle->ncp.ipcp.cfg.fsm.timeout, + &arg->bundle->ncp.ipcp.cfg.fsm.maxreq, + &arg->bundle->ncp.ipcp.cfg.fsm.maxtrm, DEF_FSMTRIES); break; case VAR_NBNS: @@ -1840,8 +1966,10 @@ SetVariable(struct cmdargs const *arg) } } else if (!strcasecmp(arg->argv[dummyint], "none")) cx->cfg.callback.opmask |= CALLBACK_BIT(CALLBACK_NONE); - else - return -1; + else { + res = -1; + break; + } } if (cx->cfg.callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) cx->cfg.callback.opmask = 0; @@ -1891,7 +2019,8 @@ SetVariable(struct cmdargs const *arg) *arg->bundle->radius.cfg.file = '\0'; else if (access(argp, R_OK)) { log_Printf(LogWARN, "%s: %s\n", argp, strerror(errno)); - return 1; + res = 1; + break; } else { strncpy(arg->bundle->radius.cfg.file, argp, sizeof arg->bundle->radius.cfg.file - 1); @@ -1920,10 +2049,10 @@ SetVariable(struct cmdargs const *arg) case VAR_PARITY: if (arg->argc == arg->argn + 1) - return physical_SetParity(arg->cx->physical, argp); + res = physical_SetParity(arg->cx->physical, argp); else { - err = "Parity value must be odd, even or none\n"; - log_Printf(LogWARN, err); + log_Printf(LogWARN, "Parity value must be odd, even or none\n"); + res = 1; } break; @@ -1933,8 +2062,8 @@ SetVariable(struct cmdargs const *arg) else if (strcasecmp(argp, "off") == 0) physical_SetRtsCts(arg->cx->physical, 0); else { - err = "RTS/CTS value must be on or off\n"; - log_Printf(LogWARN, err); + log_Printf(LogWARN, "RTS/CTS value must be on or off\n"); + res = 1; } break; @@ -1984,7 +2113,7 @@ SetVariable(struct cmdargs const *arg) break; } - return err ? 1 : 0; + return res; } static struct cmdtab const SetCommands[] = { @@ -2022,8 +2151,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|* [stateful|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 +2193,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/datalink.c b/usr.sbin/ppp/datalink.c index 5f8544f387be..71616cc1aa4b 100644 --- a/usr.sbin/ppp/datalink.c +++ b/usr.sbin/ppp/datalink.c @@ -570,7 +570,8 @@ datalink_LayerUp(void *v, struct fsm *fp) auth_StartReq(&dl->chap.auth); } else datalink_AuthOk(dl); - } + } else if (fp->proto == PROTO_CCP) + (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.ccp.fsm); } static void diff --git a/usr.sbin/ppp/deflate.c b/usr.sbin/ppp/deflate.c index 8908f127e6bd..ef04c270bcdd 100644 --- a/usr.sbin/ppp/deflate.c +++ b/usr.sbin/ppp/deflate.c @@ -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, @@ -564,6 +567,7 @@ const struct ccp_algorithm PppdDeflateAlgorithm = { DeflateDictSetup }, { + 0, DeflateInitOptsOutput, DeflateSetOptsOutput, DeflateInitOutput, @@ -577,7 +581,8 @@ const struct ccp_algorithm DeflateAlgorithm = { TY_DEFLATE, /* rfc 1979 */ CCP_NEG_DEFLATE, DeflateDispOpts, - ccp_IsUsable, + ccp_DefaultUsable, + ccp_DefaultRequired, { DeflateSetOptsInput, DeflateInitInput, @@ -587,6 +592,7 @@ const struct ccp_algorithm DeflateAlgorithm = { DeflateDictSetup }, { + 0, DeflateInitOptsOutput, DeflateSetOptsOutput, DeflateInitOutput, diff --git a/usr.sbin/ppp/ether.c b/usr.sbin/ppp/ether.c index 0af8ff54633e..1e8d53c15049 100644 --- a/usr.sbin/ppp/ether.c +++ b/usr.sbin/ppp/ether.c @@ -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/exec.c b/usr.sbin/ppp/exec.c index 1ca966500291..252265384ddd 100644 --- a/usr.sbin/ppp/exec.c +++ b/usr.sbin/ppp/exec.c @@ -68,6 +68,7 @@ static struct device execdevice = { EXEC_DEVICE, "exec", + 0, { CD_NOTREQUIRED, 0 }, NULL, NULL, diff --git a/usr.sbin/ppp/fsm.c b/usr.sbin/ppp/fsm.c index 109241060295..3c4204a21120 100644 --- a/usr.sbin/ppp/fsm.c +++ b/usr.sbin/ppp/fsm.c @@ -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/fsm.h b/usr.sbin/ppp/fsm.h index e0a69eac950d..126c9b78dd80 100644 --- a/usr.sbin/ppp/fsm.h +++ b/usr.sbin/ppp/fsm.h @@ -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/i4b.c b/usr.sbin/ppp/i4b.c index fe82faeb817b..855bfcef89a6 100644 --- a/usr.sbin/ppp/i4b.c +++ b/usr.sbin/ppp/i4b.c @@ -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/iface.c b/usr.sbin/ppp/iface.c index 5384340e8124..9676b38ec271 100644 --- a/usr.sbin/ppp/iface.c +++ b/usr.sbin/ppp/iface.c @@ -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/iface.h b/usr.sbin/ppp/iface.h index 6de1b50684b5..d520e84b0686 100644 --- a/usr.sbin/ppp/iface.h +++ b/usr.sbin/ppp/iface.h @@ -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/ip.c b/usr.sbin/ppp/ip.c index 5f666ccd507f..c33cb256bd77 100644 --- a/usr.sbin/ppp/ip.c +++ b/usr.sbin/ppp/ip.c @@ -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/ipcp.c b/usr.sbin/ppp/ipcp.c index d6585fe39586..dfec4788fbe0 100644 --- a/usr.sbin/ppp/ipcp.c +++ b/usr.sbin/ppp/ipcp.c @@ -1063,19 +1063,90 @@ AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) } static void +ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) +{ + struct bundle *bundle = ipcp->fsm.bundle; + struct iface *iface = bundle->iface; + int n; + + if (iplist_isvalid(&ipcp->cfg.peer_list)) { + if (ip.s_addr == INADDR_ANY || + iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || + ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, ip, 1)) { + log_Printf(LogIPCP, "%s: Address invalid or already in use\n", + inet_ntoa(ip)); + /* + * If we've already had a valid address configured for the peer, + * try NAKing with that so that we don't have to upset things + * too much. + */ + for (n = 0; n < iface->in_addrs; n++) + if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) >= 0) { + ipcp->peer_ip = iface->in_addr[n].brd; + break; + } + + if (n == iface->in_addrs) + /* Just pick an IP number from our list */ + ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->cfg.my_range.ipaddr); + + if (ipcp->peer_ip.s_addr == INADDR_ANY) { + *dec->rejend++ = TY_IPADDR; + *dec->rejend++ = 6; + memcpy(dec->rejend, &ip.s_addr, 4); + dec->rejend += 4; + } else { + *dec->nakend++ = TY_IPADDR; + *dec->nakend++ = 6; + memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); + dec->nakend += 4; + } + return; + } + } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ip)) { + /* + * If the destination address is not acceptable, NAK with what we + * want to use. + */ + *dec->nakend++ = TY_IPADDR; + *dec->nakend++ = 6; + for (n = 0; n < iface->in_addrs; n++) + if ((iface->in_addr[n].brd.s_addr & ipcp->cfg.peer_range.mask.s_addr) + == (ipcp->cfg.peer_range.ipaddr.s_addr & + ipcp->cfg.peer_range.mask.s_addr)) { + /* We prefer the already-configured address */ + memcpy(dec->nakend, &iface->in_addr[n].brd.s_addr, 4); + break; + } + + if (n == iface->in_addrs) + memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); + + dec->nakend += 4; + return; + } + + ipcp->peer_ip = ip; + *dec->ackend++ = TY_IPADDR; + *dec->ackend++ = 6; + memcpy(dec->ackend, &ip.s_addr, 4); + dec->ackend += 4; +} + +static void IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, struct fsm_decode *dec) { /* Deal with incoming PROTO_IPCP */ - struct iface *iface = fp->bundle->iface; struct ipcp *ipcp = fsm2ipcp(fp); - int type, length, gotdnsnak, n; + int type, length, gotdnsnak, ipaddr_req; u_int32_t compproto; struct compreq *pcomp; struct in_addr ipaddr, dstipaddr, have_ip; char tbuff[100], tbuff2[100]; gotdnsnak = 0; + ipaddr_req = 0; while (plen >= sizeof(struct fsmconfig)) { type = *cp; @@ -1095,66 +1166,8 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, switch (mode_type) { case MODE_REQ: - if (iplist_isvalid(&ipcp->cfg.peer_list)) { - if (ipaddr.s_addr == INADDR_ANY || - iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || - ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, - ipaddr, 1)) { - log_Printf(LogIPCP, "%s: Address invalid or already in use\n", - inet_ntoa(ipaddr)); - /* - * If we've already had a valid address configured for the peer, - * try NAKing with that so that we don't have to upset things - * too much. - */ - for (n = 0; n < iface->in_addrs; n++) - if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) - >=0) { - ipcp->peer_ip = iface->in_addr[n].brd; - break; - } - - if (n == iface->in_addrs) - /* Just pick an IP number from our list */ - ipcp->peer_ip = ChooseHisAddr - (fp->bundle, ipcp->cfg.my_range.ipaddr); - - if (ipcp->peer_ip.s_addr == INADDR_ANY) { - memcpy(dec->rejend, cp, length); - dec->rejend += length; - } else { - memcpy(dec->nakend, cp, 2); - memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); - dec->nakend += length; - } - break; - } - } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { - /* - * If destination address is not acceptable, NAK with what we - * want to use. - */ - memcpy(dec->nakend, cp, 2); - for (n = 0; n < iface->in_addrs; n++) - if ((iface->in_addr[n].brd.s_addr & - ipcp->cfg.peer_range.mask.s_addr) - == (ipcp->cfg.peer_range.ipaddr.s_addr & - ipcp->cfg.peer_range.mask.s_addr)) { - /* We prefer the already-configured address */ - memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, - length - 2); - break; - } - - if (n == iface->in_addrs) - memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); - - dec->nakend += length; - break; - } - ipcp->peer_ip = ipaddr; - memcpy(dec->ackend, cp, length); - dec->ackend += length; + ipaddr_req = 1; + ipcp_ValidateReq(ipcp, ipaddr, dec); break; case MODE_NAK: @@ -1401,6 +1414,11 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, } if (mode_type != MODE_NOP) { + if (mode_type == MODE_REQ && !ipaddr_req) { + /* We *REQUIRE* that the peer requests an IP address */ + ipaddr.s_addr = INADDR_ANY; + ipcp_ValidateReq(ipcp, ipaddr, dec); + } if (dec->rejend != dec->rej) { /* rejects are preferred */ dec->ackend = dec->ack; diff --git a/usr.sbin/ppp/lcp.c b/usr.sbin/ppp/lcp.c index f4bfee4be0a6..25c893bea40a 100644 --- a/usr.sbin/ppp/lcp.c +++ b/usr.sbin/ppp/lcp.c @@ -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/lcp.h b/usr.sbin/ppp/lcp.h index e86e3bea85d4..3e0e8b223d2a 100644 --- a/usr.sbin/ppp/lcp.h +++ b/usr.sbin/ppp/lcp.h @@ -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/log.c b/usr.sbin/ppp/log.c index d31d9c9bf32f..30f0b126e7c8 100644 --- a/usr.sbin/ppp/log.c +++ b/usr.sbin/ppp/log.c @@ -306,10 +306,10 @@ log_Printf(int lev, const char *fmt,...) va_list ap; struct prompt *prompt; - va_start(ap, fmt); if (log_IsKept(lev)) { char nfmt[200]; + va_start(ap, fmt); if (promptlist && (log_IsKept(lev) & LOG_KEPT_LOCAL)) { if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1) snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME, @@ -324,7 +324,9 @@ log_Printf(int lev, const char *fmt,...) if (lev > LogMAXCONF || (prompt->logmask & MSK(lev))) prompt_vPrintf(prompt, nfmt, ap); } + va_end(ap); + va_start(ap, fmt); if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) && (lev != LogWARN || !log_PromptContext)) { if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1) @@ -334,8 +336,8 @@ log_Printf(int lev, const char *fmt,...) snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt); vsyslog(syslogLevel(lev), nfmt, ap); } + va_end(ap); } - va_end(ap); } void diff --git a/usr.sbin/ppp/mp.c b/usr.sbin/ppp/mp.c index 2652d465baf5..448b9e29eeef 100644 --- a/usr.sbin/ppp/mp.c +++ b/usr.sbin/ppp/mp.c @@ -167,6 +167,8 @@ static void mp_LayerUp(void *v, struct fsm *fp) { /* The given fsm (ccp) is now up */ + + bundle_CalculateBandwidth(fp->bundle); /* Against ccp_MTUOverhead */ } static void @@ -646,6 +648,11 @@ mp_Output(struct mp *mp, struct bundle *bundle, struct link *l, mp->out.seq, m_length(m), l->name); mp->out.seq = inc_seq(mp->peer_is12bit, mp->out.seq); + if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { + log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); + return; + } + link_PushPacket(l, m, bundle, LINK_QUEUES(l) - 1, PROTO_MP); } diff --git a/usr.sbin/ppp/mppe.c b/usr.sbin/ppp/mppe.c index 617596a816bf..f079660c2fa4 100644 --- a/usr.sbin/ppp/mppe.c +++ b/usr.sbin/ppp/mppe.c @@ -30,6 +30,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <termios.h> #ifdef __FreeBSD__ #include <sha.h> @@ -61,23 +62,54 @@ * 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 +#define MPPE_HEADER_STATEFUL_KEYCHANGES 16 + 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 +144,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 +165,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 +200,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 +218,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 +227,128 @@ 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); + if (n < 0) + n += MPPE_HEADER_STATEFUL_KEYCHANGES; + 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 +356,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" : "ful"); + 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 +419,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 +636,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 +663,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 +682,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 +700,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 +714,7 @@ const struct ccp_algorithm MPPEAlgorithm = { CCP_NEG_MPPE, MPPEDispOpts, MPPEUsable, + MPPERequired, { MPPESetOptsInput, MPPEInitInput, @@ -443,6 +724,7 @@ const struct ccp_algorithm MPPEAlgorithm = { MPPEDictSetup }, { + 2, MPPEInitOptsOutput, MPPESetOptsOutput, MPPEInitOutput, diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c index 78250c3041fe..86a9a52e8f7b 100644 --- a/usr.sbin/ppp/physical.c +++ b/usr.sbin/ppp/physical.c @@ -752,6 +752,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/physical.h b/usr.sbin/ppp/physical.h index 74ce890745cd..9684fedbf764 100644 --- a/usr.sbin/ppp/physical.h +++ b/usr.sbin/ppp/physical.h @@ -55,6 +55,7 @@ struct cd { struct device { int type; const char *name; + u_short mtu; struct cd cd; int (*awaitcarrier)(struct physical *); @@ -142,6 +143,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.8 b/usr.sbin/ppp/ppp.8 index acfd8fc7aea2..7b684c89cd7b 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -382,9 +382,11 @@ It is possible to configure to open more than one physical connection to the peer, combining the bandwidth of all links for better throughput. .It Supports MPPE (draft-ietf-pppext-mppe) -MPPE is Microsoft Point to Point Encryption scheme. It is possible to configure +MPPE is Microsoft Point to Point Encryption scheme. +It is possible to configure .Nm -to participate in Microsoft's Windows VPN. For now, +to participate in Microsoft's Windows VPN. +For now, .Nm can only get encryption keys from CHAP 81 authentication. .Nm @@ -2403,7 +2405,8 @@ to exit. This signal, tells .Nm to re-open any existing server socket, dropping all existing diagnostic -connections. Sockets that couldn't previously be opened will be retried. +connections. +Sockets that couldn't previously be opened will be retried. .It USR2 This signal, tells .Nm @@ -2796,8 +2799,10 @@ values are honoured as if the peer were responsible for dropping the connection. .It mppe Default: Enabled and Accepted. -This is Microsoft Point to Point Encryption scheme. MPPE key size can be -40-, 56- and 128-bits. Refer to +This is Microsoft Point to Point Encryption scheme. +MPPE key size can be +40-, 56- and 128-bits. +Refer to .Dq set mppe command. .It MSChapV2|chap81 @@ -4910,39 +4915,102 @@ 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|stateful|* +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 stateful 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 stateful 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 stateful 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 Xo +.Op max Ns Op imum +.Op Ar value +.Xc 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 Xo +.Op max Ns Op imum +.Op Ar value +.Xc 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. @@ -5574,6 +5642,7 @@ This socket is used to pass links between different instances of .Xr syslog 3 , .Xr uucplock 3 , .Xr netgraph 4 , +.Xr ng_pppoe 4 , .Xr crontab 5 , .Xr group 5 , .Xr passwd 5 , @@ -5587,7 +5656,6 @@ This socket is used to pass links between different instances of .Xr init 8 , .Xr isdn 8 , .Xr named 8 , -.Xr ng_pppoe 4 , .Xr ping 8 , .Xr pppctl 8 , .Xr pppd 8 , diff --git a/usr.sbin/ppp/pred.c b/usr.sbin/ppp/pred.c index 6fd300c7a8c1..d1a5b53f1276 100644 --- a/usr.sbin/ppp/pred.c +++ b/usr.sbin/ppp/pred.c @@ -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, @@ -333,6 +340,7 @@ const struct ccp_algorithm Pred1Algorithm = { Pred1DictSetup }, { + 0, Pred1InitOptsOutput, Pred1SetOptsOutput, Pred1InitOutput, diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c index 2b6325352a8a..54f585ab37ec 100644 --- a/usr.sbin/ppp/route.c +++ b/usr.sbin/ppp/route.c @@ -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/tcp.c b/usr.sbin/ppp/tcp.c index b7482d1ff463..567072a665e0 100644 --- a/usr.sbin/ppp/tcp.c +++ b/usr.sbin/ppp/tcp.c @@ -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/tcpmss.c b/usr.sbin/ppp/tcpmss.c index ed7ef46b0a1f..f8debc8805ef 100644 --- a/usr.sbin/ppp/tcpmss.c +++ b/usr.sbin/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/tty.c b/usr.sbin/ppp/tty.c index 2727fecffbb0..773525ccf141 100644 --- a/usr.sbin/ppp/tty.c +++ b/usr.sbin/ppp/tty.c @@ -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/tun.c b/usr.sbin/ppp/tun.c index f61f1f2caf55..480e6c269cdb 100644 --- a/usr.sbin/ppp/tun.c +++ b/usr.sbin/ppp/tun.c @@ -27,10 +27,12 @@ */ #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/udp.c b/usr.sbin/ppp/udp.c index 6894e1ef964a..8307a4ae7104 100644 --- a/usr.sbin/ppp/udp.c +++ b/usr.sbin/ppp/udp.c @@ -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, |
