diff options
author | brian <brian@FreeBSD.org> | 1998-08-07 18:42:51 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1998-08-07 18:42:51 +0000 |
commit | f9ee8808e7fd6798eb442188b9b4b8e23c461f07 (patch) | |
tree | 4a1f01689ab26830c419f0100830cd94b3e03a62 /usr.sbin/ppp/lcp.c | |
parent | da1fbd5e2562a9182735d47266f718c37ce51225 (diff) | |
download | FreeBSD-src-f9ee8808e7fd6798eb442188b9b4b8e23c461f07.zip FreeBSD-src-f9ee8808e7fd6798eb442188b9b4b8e23c461f07.tar.gz |
o Support callback types NONE, E.164, AUTH and CBCP.
(see the new ``set callback'' and ``set cbcp'' commands)
o Add a ``cbcp'' log level and mbuf type.
o Don't dump core when \T is given in ``set login'' or
``set hangup''.
o Allow ``*'' and blanks as placeholders in ppp.secret and
allow a fifth field for specifying auth/cbcp dialback
parameters.
o Remove a few extraneous #includes
o Define the default number of REQs (restart counter) in defs.h
rather than hardcoding ``5'' all over the place.
o Fix a few man page inconsistencies.
Diffstat (limited to 'usr.sbin/ppp/lcp.c')
-rw-r--r-- | usr.sbin/ppp/lcp.c | 187 |
1 files changed, 179 insertions, 8 deletions
diff --git a/usr.sbin/ppp/lcp.c b/usr.sbin/ppp/lcp.c index 897eb23..47d2074 100644 --- a/usr.sbin/ppp/lcp.c +++ b/usr.sbin/ppp/lcp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lcp.c,v 1.60 1998/06/25 22:33:28 brian Exp $ + * $Id: lcp.c,v 1.61 1998/06/27 23:48:47 brian Exp $ * * TODO: * o Limit data field length by MRU @@ -61,6 +61,7 @@ #include "chat.h" #include "auth.h" #include "chap.h" +#include "cbcp.h" #include "datalink.h" #include "bundle.h" @@ -237,6 +238,7 @@ lcp_Setup(struct lcp *lcp, int openmode) lcp->his_lqrperiod = 0; lcp->his_acfcomp = 0; lcp->his_auth = 0; + lcp->his_callback.opmask = 0; lcp->his_shortseq = 0; lcp->want_mru = lcp->cfg.mru; @@ -245,6 +247,8 @@ lcp_Setup(struct lcp *lcp, int openmode) 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; @@ -252,6 +256,10 @@ lcp_Setup(struct lcp *lcp, int openmode) lcp->want_magic = GenerateMagic(); lcp->want_auth = IsEnabled(lcp->cfg.chap) ? PROTO_CHAP : IsEnabled(lcp->cfg.pap) ? PROTO_PAP : 0; + if (p->type != PHYS_DIRECT) + memcpy(&lcp->want_callback, &p->dl->cfg.callback, sizeof(struct callback)); + else + lcp->want_callback.opmask = 0; lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ? lcp->cfg.lqrperiod * 100 : 0; } else { @@ -259,6 +267,7 @@ lcp_Setup(struct lcp *lcp, int openmode) lcp->his_protocomp = lcp->want_protocomp = 1; lcp->want_magic = 0; lcp->want_auth = 0; + lcp->want_callback.opmask = 0; lcp->want_lqrperiod = 0; } @@ -274,7 +283,7 @@ LcpInitRestartCounter(struct fsm * fp) struct lcp *lcp = fsm2lcp(fp); fp->FsmTimer.load = lcp->cfg.fsmretry * SECTICKS; - fp->restart = 5; + fp->restart = DEF_REQs; } static void @@ -336,6 +345,26 @@ LcpSendConfigReq(struct fsm *fp) break; } + if (!REJECTED(lcp, TY_CALLBACK)) { + if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) { + *o->data = CALLBACK_AUTH; + INC_LCP_OPT(TY_CALLBACK, 3, o); + } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) { + *o->data = CALLBACK_CBCP; + INC_LCP_OPT(TY_CALLBACK, 3, o); + } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) { + int sz = strlen(lcp->want_callback.msg); + + if (sz > sizeof o->data - 1) { + sz = sizeof o->data - 1; + log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz); + } + *o->data = CALLBACK_E164; + memcpy(o->data + 1, lcp->want_callback.msg, sz); + INC_LCP_OPT(TY_CALLBACK, sz + 3, o); + } + } + if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) { *(u_int16_t *)o->data = htons(lcp->want_mrru); INC_LCP_OPT(TY_MRRU, 4, o); @@ -371,6 +400,11 @@ static void LcpSendTerminateAck(struct fsm *fp, u_char id) { /* Send Term ACK please */ + struct physical *p = link2physical(fp->link); + + if (p && p->dl->state == DATALINK_CBCP) + cbcp_ReceiveTerminateReq(p); + fsm_Output(fp, CODE_TERMACK, id, NULL, 0); } @@ -417,13 +451,32 @@ LcpLayerDown(struct fsm *fp) lcp_Setup(fsm2lcp(fp), 0); } +static int +E164ok(struct callback *cb, char *req, int sz) +{ + char list[sizeof cb->msg], *next; + int len; + + if (!strcmp(cb->msg, "*")) + return 1; + + strncpy(list, cb->msg, sizeof list - 1); + list[sizeof list - 1] = '\0'; + for (next = strtok(list, ","); next; next = strtok(NULL, ",")) { + len = strlen(next); + if (sz == len && !memcmp(list, req, sz)) + return 1; + } + return 0; +} + static void LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, struct fsm_decode *dec) { /* Deal with incoming PROTO_LCP */ struct lcp *lcp = fsm2lcp(fp); - int type, length, sz, pos; + int type, length, sz, pos, op, callback_req; u_int32_t magic, accmap; u_short mtu, mru, proto; u_int16_t *sp; @@ -432,20 +485,22 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, struct mp *mp; struct physical *p = link2physical(fp->link); + callback_req = 0; + while (plen >= sizeof(struct fsmconfig)) { type = *cp; length = cp[1]; - if (length == 0) { - log_Printf(LogLCP, "%s: LCP size zero\n", fp->link->name); - break; - } - if (type < 0 || type >= NCFTYPES) snprintf(request, sizeof request, " <%d>[%d]", type, length); else snprintf(request, sizeof request, " %s[%d]", cftypes[type], length); + if (length < 2) { + log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request); + break; + } + switch (type) { case TY_MRRU: mp = &lcp->fsm.bundle->ncp.mp; @@ -782,6 +837,103 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, } break; + case TY_CALLBACK: + if (length == 2) + op = CALLBACK_NONE; + else + op = (int)cp[2]; + sz = length - 3; + switch (op) { + case CALLBACK_AUTH: + log_Printf(LogLCP, "%s Auth\n", request); + break; + case CALLBACK_DIALSTRING: + log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3); + break; + case CALLBACK_LOCATION: + log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3); + break; + case CALLBACK_E164: + log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3); + break; + case CALLBACK_NAME: + log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3); + break; + case CALLBACK_CBCP: + log_Printf(LogLCP, "%s CBCP\n", request); + break; + default: + log_Printf(LogLCP, "%s ???\n", request); + break; + } + + switch (mode_type) { + case MODE_REQ: + callback_req = 1; + if (p->type != PHYS_DIRECT) + goto reqreject; + if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) && + (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) && + (op != CALLBACK_E164 || + E164ok(&p->dl->cfg.callback, cp + 3, sz))) { + lcp->his_callback.opmask = CALLBACK_BIT(op); + if (sz > sizeof lcp->his_callback.msg - 1) { + sz = sizeof lcp->his_callback.msg - 1; + log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz); + } + memcpy(lcp->his_callback.msg, cp + 3, sz); + lcp->his_callback.msg[sz] = '\0'; + memcpy(dec->ackend, cp, sz + 3); + dec->ackend += sz + 3; + } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) && + p->link.lcp.auth_ineed) { + *dec->nakend++ = *cp; + *dec->nakend++ = 3; + *dec->nakend++ = CALLBACK_AUTH; + } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) { + *dec->nakend++ = *cp; + *dec->nakend++ = 3; + *dec->nakend++ = CALLBACK_CBCP; + } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) { + *dec->nakend++ = *cp; + *dec->nakend++ = 3; + *dec->nakend++ = CALLBACK_E164; + } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) { + log_Printf(LogWARN, "Cannot insist on auth callback without" + " PAP or CHAP enabled !\n"); + *dec->nakend++ = *cp; + *dec->nakend++ = 2; + } else + goto reqreject; + break; + case MODE_NAK: + /* We don't do what he NAKs want, we do things in our preferred order */ + if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) + lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH); + else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) + lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP); + else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) + lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164); + if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) { + log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n"); + lcp->want_callback.opmask = 0; + } else if (!lcp->want_callback.opmask) { + log_Printf(LogPHASE, "Peer NAKd last configured callback\n"); + fsm_Close(&lcp->fsm); + } + break; + case MODE_REJ: + if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) { + lcp->his_reject |= (1 << type); + lcp->want_callback.opmask = 0; + } else { + log_Printf(LogPHASE, "Peer rejected *required* callback\n"); + fsm_Close(&lcp->fsm); + } + break; + } + break; + case TY_SHORTSEQ: mp = &lcp->fsm.bundle->ncp.mp; log_Printf(LogLCP, "%s\n", request); @@ -874,6 +1026,25 @@ reqreject: } if (mode_type != MODE_NOP) { + if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT && + p->dl->cfg.callback.opmask && !callback_req && + !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) { + /* We *REQUIRE* that the peer requests callback */ + *dec->nakend++ = TY_CALLBACK; + *dec->nakend++ = 3; + if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) && + p->link.lcp.auth_ineed) + *dec->nakend++ = CALLBACK_AUTH; + else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) + *dec->nakend++ = CALLBACK_CBCP; + else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) + *dec->nakend++ = CALLBACK_E164; + else { + log_Printf(LogWARN, "Cannot insist on auth callback without" + " PAP or CHAP enabled !\n"); + dec->nakend[-1] = 2; /* XXX: Silly ! */ + } + } if (dec->rejend != dec->rej) { /* rejects are preferred */ dec->ackend = dec->ack; |