diff --git a/usr.sbin/ppp/auth.c b/usr.sbin/ppp/auth.c index 1aa6a6ef70b..aeda3072a10 100644 --- a/usr.sbin/ppp/auth.c +++ b/usr.sbin/ppp/auth.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: auth.c,v 1.27.2.22 1998/04/19 15:24:34 brian Exp $ + * $Id: auth.c,v 1.27.2.23 1998/04/23 03:22:43 brian Exp $ * * TODO: * o Implement check against with registered IP addresses. @@ -86,17 +86,19 @@ auth_CheckPasswd(const char *name, const char *data, const char *key) } int -AuthValidate(struct bundle *bundle, const char *fname, const char *system, - const char *key, struct physical *physical) +AuthSelect(struct bundle *bundle, const char *name, struct physical *physical) { - /* Used by PAP routines */ - FILE *fp; int n; char *vector[5]; char buff[LINE_LEN]; - fp = OpenSecret(fname); + if (*name == '\0') { + ipcp_Setup(&bundle->ncp.ipcp); + return 1; + } + + fp = OpenSecret(SECRETFILE); if (fp != NULL) { while (fgets(buff, sizeof buff, fp)) { if (buff[0] == '#') @@ -106,20 +108,57 @@ AuthValidate(struct bundle *bundle, const char *fname, const char *system, n = MakeArgs(buff, vector, VECSIZE(vector)); if (n < 2) continue; - if (strcmp(vector[0], system) == 0) - if (auth_CheckPasswd(vector[0], vector[1], key)) { - CloseSecret(fp); - if (n > 2 && !UseHisaddr(bundle, vector[2], 1)) - return (0); - /* XXX This should be deferred - we may join an existing bundle ! */ - ipcp_Setup(&bundle->ncp.ipcp); - if (n > 3) - bundle_SetLabel(bundle, vector[3]); - return 1; /* Valid */ - } else { - CloseSecret(fp); - return 0; /* Invalid */ - } + if (strcmp(vector[0], name) == 0) + CloseSecret(fp); +/* + memset(&bundle->ncp.ipcp.cfg.peer_range, '\0', + sizeof bundle->ncp.ipcp.cfg.peer_range); +*/ + if (n > 2 && !UseHisaddr(bundle, vector[2], 1)) + return 0; + ipcp_Setup(&bundle->ncp.ipcp); + if (n > 3) + bundle_SetLabel(bundle, vector[3]); + return 1; /* Valid */ + } + CloseSecret(fp); + } + +#ifndef NOPASSWDAUTH + /* Let 'em in anyway - they must have been in the passwd file */ + ipcp_Setup(&bundle->ncp.ipcp); + return 1; +#else + /* Disappeared from ppp.secret ? */ + return 0; +#endif +} + +int +AuthValidate(struct bundle *bundle, const char *system, + const char *key, struct physical *physical) +{ + /* Used by PAP routines */ + + FILE *fp; + int n; + char *vector[5]; + char buff[LINE_LEN]; + + fp = OpenSecret(SECRETFILE); + if (fp != NULL) { + while (fgets(buff, sizeof buff, fp)) { + if (buff[0] == '#') + continue; + buff[strlen(buff) - 1] = 0; + memset(vector, '\0', sizeof vector); + n = MakeArgs(buff, vector, VECSIZE(vector)); + if (n < 2) + continue; + if (strcmp(vector[0], system) == 0) { + CloseSecret(fp); + return auth_CheckPasswd(vector[0], vector[1], key); + } } CloseSecret(fp); } @@ -133,8 +172,8 @@ AuthValidate(struct bundle *bundle, const char *fname, const char *system, } char * -AuthGetSecret(struct bundle *bundle, const char *fname, const char *system, - int len, int setaddr, struct physical *physical) +AuthGetSecret(struct bundle *bundle, const char *system, int len, + struct physical *physical) { /* Used by CHAP routines */ @@ -143,7 +182,7 @@ AuthGetSecret(struct bundle *bundle, const char *fname, const char *system, char *vector[5]; static char buff[LINE_LEN]; - fp = OpenSecret(fname); + fp = OpenSecret(SECRETFILE); if (fp == NULL) return (NULL); @@ -156,17 +195,7 @@ AuthGetSecret(struct bundle *bundle, const char *fname, const char *system, if (n < 2) continue; if (strlen(vector[0]) == len && strncmp(vector[0], system, len) == 0) { - if (setaddr) - memset(&bundle->ncp.ipcp.cfg.peer_range, '\0', - sizeof bundle->ncp.ipcp.cfg.peer_range); - if (n > 2 && setaddr) - if (UseHisaddr(bundle, vector[2], 1)) - /* XXX This should be deferred - we may join an existing bundle ! */ - ipcp_Setup(&bundle->ncp.ipcp); - else - return NULL; - if (n > 3) - bundle_SetLabel(bundle, vector[3]); + CloseSecret(fp); return vector[1]; } } diff --git a/usr.sbin/ppp/auth.h b/usr.sbin/ppp/auth.h index 39b50ee2368..4a86166cf09 100644 --- a/usr.sbin/ppp/auth.h +++ b/usr.sbin/ppp/auth.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: auth.h,v 1.10.2.6 1998/04/03 19:25:21 brian Exp $ + * $Id: auth.h,v 1.10.2.7 1998/04/07 00:53:20 brian Exp $ * * TODO: */ @@ -41,6 +41,7 @@ extern void StopAuthTimer(struct authinfo *); extern void StartAuthChallenge(struct authinfo *, struct physical *, void (*fn)(struct authinfo *, int, struct physical *)); extern int AuthValidate(struct bundle *, const char *, const char *, - const char *, struct physical *); -extern char *AuthGetSecret(struct bundle *, const char *, const char *, int, - int, struct physical *); + struct physical *); +extern char *AuthGetSecret(struct bundle *, const char *, int, + struct physical *); +extern int AuthSelect(struct bundle *, const char *, struct physical *); diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 0ce39be4a3a..074b53f147c 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.c,v 1.1.2.59 1998/04/23 21:50:00 brian Exp $ + * $Id: bundle.c,v 1.1.2.60 1998/04/24 19:15:34 brian Exp $ */ #include @@ -836,14 +836,10 @@ bundle_FillQueues(struct bundle *bundle) int bundle_ShowLinks(struct cmdargs const *arg) { - if (arg->cx) - datalink_Show(arg->cx, arg->prompt); - else { - struct datalink *dl; + struct datalink *dl; - for (dl = arg->bundle->links; dl; dl = dl->next) - datalink_Show(dl, arg->prompt); - } + for (dl = arg->bundle->links; dl; dl = dl->next) + prompt_Printf(arg->prompt, "Name: %s [%s]\n", dl->name, datalink_State(dl)); return 0; } @@ -860,9 +856,10 @@ bundle_ShowStatus(struct cmdargs const *arg) int remaining; prompt_Printf(arg->prompt, "Phase %s\n", bundle_PhaseName(arg->bundle)); - prompt_Printf(arg->prompt, " Interface: %s\n", arg->bundle->dev); + prompt_Printf(arg->prompt, " Interface: %s\n", arg->bundle->dev); prompt_Printf(arg->prompt, "\nDefaults:\n"); + prompt_Printf(arg->prompt, " Label: %s\n", arg->bundle->cfg.label); prompt_Printf(arg->prompt, " Auth name: %s\n", arg->bundle->cfg.auth.name); prompt_Printf(arg->prompt, " Idle Timer: "); if (arg->bundle->cfg.idle_timeout) { diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c index 957065a5d78..d906b06b0df 100644 --- a/usr.sbin/ppp/chap.c +++ b/usr.sbin/ppp/chap.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.c,v 1.28.2.23 1998/04/07 00:53:25 brian Exp $ + * $Id: chap.c,v 1.28.2.24 1998/04/16 00:25:52 brian Exp $ * * TODO: */ @@ -203,9 +203,7 @@ RecvChapTalk(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp, /* * Get a secret key corresponds to the peer */ - keyp = AuthGetSecret(bundle, SECRETFILE, name, namelen, - chp->code == CHAP_RESPONSE, - physical); + keyp = AuthGetSecret(bundle, name, namelen, physical); if (keyp) { /* * Compute correct digest value @@ -227,6 +225,7 @@ RecvChapTalk(struct bundle *bundle, struct fsmheader *chp, struct mbuf *bp, * Compare with the response */ if (memcmp(cp, cdigest, 16) == 0) { + datalink_GotAuthname(physical->dl, name, namelen); ChapOutput(physical, CHAP_SUCCESS, chp->id, "Welcome!!", 10); if (Enabled(bundle, OPT_UTMP)) Physical_Login(physical, name); diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 7f9595a4ad7..dc841908a8d 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.131.2.69 1998/04/23 21:50:05 brian Exp $ + * $Id: command.c,v 1.131.2.70 1998/04/24 19:15:37 brian Exp $ * */ #include @@ -194,7 +194,7 @@ CloneCommand(struct cmdargs const *arg) if (arg->argc == arg->argn) return -1; - if (!arg->bundle->ncp.mp.active) { + if (!arg->bundle->ncp.mp.cfg.mrru) { LogPrintf(LogWARN, "clone: Only available in multilink mode\n"); return 1; } @@ -210,11 +210,6 @@ RemoveCommand(struct cmdargs const *arg) if (arg->argc != arg->argn) return -1; - if (!arg->bundle->ncp.mp.active) { - LogPrintf(LogWARN, "remove: Only available in multilink mode\n"); - return 1; - } - if (arg->cx->state != DATALINK_CLOSED) { LogPrintf(LogWARN, "remove: Cannot delete links that aren't closed\n"); return 2; @@ -513,7 +508,7 @@ static int ShowVersion(struct cmdargs const *arg) { static char VarVersion[] = "PPP Version 2.0-beta"; - static char VarLocalVersion[] = "$Date: 1998/04/23 21:50:05 $"; + static char VarLocalVersion[] = "$Date: 1998/04/24 19:15:37 $"; prompt_Printf(arg->prompt, "%s - %s \n", VarVersion, VarLocalVersion); return 0; @@ -544,16 +539,18 @@ static struct cmdtab const ShowCommands[] = { "Show HDLC errors", "show hdlc"}, {"ipcp", NULL, ReportIpcpStatus, LOCAL_AUTH, "Show IPCP status", "show ipcp"}, - {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX_OPT, + {"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX, "Show LCP status", "show lcp"}, - {"links", "link", bundle_ShowLinks, LOCAL_AUTH, + {"link", "datalink", datalink_Show, LOCAL_AUTH | LOCAL_CX, + "Show (high-level) link info", "show link"}, + {"links", NULL, bundle_ShowLinks, LOCAL_AUTH, "Show available link names", "show links"}, {"log", NULL, log_ShowLevel, LOCAL_AUTH, "Show log levels", "show log"}, {"mem", NULL, ShowMemMap, LOCAL_AUTH, "Show memory map", "show mem"}, {"modem", NULL, modem_ShowStatus, LOCAL_AUTH | LOCAL_CX, - "Show modem setups", "show modem"}, + "Show (low-level) link info", "show modem"}, {"mp", "multilink", mp_ShowStatus, LOCAL_AUTH, "Show multilink setup", "show mp"}, {"proto", NULL, ShowProtocolStats, LOCAL_AUTH | LOCAL_CX_OPT, @@ -1352,7 +1349,7 @@ static struct cmdtab const SetCommands[] = { "Set login script", "set login chat-script", (const void *) VAR_LOGIN}, {"lqrperiod", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, "Set LQR period", "set lqrperiod value", (const void *)VAR_LQRPERIOD}, - {"mrru", NULL, SetVariable, LOCAL_AUTH, "Set MRRU value (enable multilink)", + {"mrru", NULL, SetVariable, LOCAL_AUTH, "Set MRRU value", "set mrru value", (const void *)VAR_MRRU}, {"mru", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, "Set MRU value", "set mru value", (const void *)VAR_MRU}, diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c index 9c67ab7806c..d4b20754123 100644 --- a/usr.sbin/ppp/datalink.c +++ b/usr.sbin/ppp/datalink.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.c,v 1.1.2.44 1998/04/23 18:55:48 brian Exp $ + * $Id: datalink.c,v 1.1.2.45 1998/04/23 18:56:09 brian Exp $ */ #include @@ -66,7 +66,6 @@ #include "command.h" #include "datalink.h" -static const char *datalink_State(struct datalink *); static void datalink_LoginDone(struct datalink *); static void @@ -183,7 +182,7 @@ datalink_LoginDone(struct datalink *dl) } else { dl->dial_tries = -1; - hdlc_Init(&dl->physical->hdlc); + hdlc_Init(&dl->physical->hdlc, &dl->physical->link.lcp); async_Init(&dl->physical->async); lcp_Setup(&dl->physical->link.lcp, dl->state == DATALINK_READY ? @@ -422,6 +421,7 @@ datalink_LayerUp(void *v, struct fsm *fp) struct datalink *dl = (struct datalink *)v; if (fp->proto == PROTO_LCP) { + datalink_GotAuthname(dl, "", 0); dl->physical->link.lcp.auth_ineed = dl->physical->link.lcp.want_auth; dl->physical->link.lcp.auth_iwait = dl->physical->link.lcp.his_auth; if (dl->physical->link.lcp.his_auth || dl->physical->link.lcp.want_auth) { @@ -439,13 +439,22 @@ datalink_LayerUp(void *v, struct fsm *fp) } } +void +datalink_GotAuthname(struct datalink *dl, const char *name, int len) +{ + if (len >= sizeof dl->peer.authname) + len = sizeof dl->peer.authname - 1; + strncpy(dl->peer.authname, name, len); + dl->peer.authname[len] = '\0'; +} + void datalink_AuthOk(struct datalink *dl) { /* XXX: Connect to another ppp instance HERE */ if (dl->physical->link.lcp.want_mrru && dl->physical->link.lcp.his_mrru) { - if (!mp_Up(&dl->bundle->ncp.mp, + if (!mp_Up(&dl->bundle->ncp.mp, &dl->peer, dl->physical->link.lcp.want_mrru, dl->physical->link.lcp.his_mrru, dl->physical->link.lcp.want_shortseq, @@ -460,6 +469,7 @@ datalink_AuthOk(struct datalink *dl) } else ipcp_SetLink(&dl->bundle->ncp.ipcp, &dl->physical->link); + AuthSelect(dl->bundle, dl->peer.authname, dl->physical); FsmUp(&dl->physical->link.ccp.fsm); FsmOpen(&dl->physical->link.ccp.fsm); dl->state = DATALINK_OPEN; @@ -483,6 +493,7 @@ datalink_LayerDown(void *v, struct fsm *fp) if (fp->proto == PROTO_LCP) { switch (dl->state) { case DATALINK_OPEN: + peerid_Init(&dl->peer); FsmDown(&dl->physical->link.ccp.fsm); FsmClose(&dl->physical->link.ccp.fsm); (*dl->parent->LayerDown)(dl->parent->object, fp); @@ -555,6 +566,7 @@ datalink_Create(const char *name, struct bundle *bundle, dl->cfg.reconnect.timeout = RECONNECT_TIMEOUT; dl->name = strdup(name); + peerid_Init(&dl->peer); dl->parent = parent; dl->fsmp.LayerStart = datalink_LayerStart; dl->fsmp.LayerUp = datalink_LayerUp; @@ -598,14 +610,19 @@ datalink_Clone(struct datalink *odl, const char *name) memcpy(&dl->cfg, &odl->cfg, sizeof dl->cfg); mp_linkInit(&dl->mp); *dl->phone.list = '\0'; + dl->phone.next = NULL; + dl->phone.alt = NULL; + dl->phone.chosen = "N/A"; dl->bundle = odl->bundle; dl->next = NULL; memset(&dl->dial_timer, '\0', sizeof dl->dial_timer); dl->dial_tries = 0; dl->reconnect_tries = 0; dl->name = strdup(name); + peerid_Init(&dl->peer); dl->parent = odl->parent; memcpy(&dl->fsmp, &odl->fsmp, sizeof dl->fsmp); + dl->fsmp.object = dl; authinfo_Init(&dl->pap); dl->pap.cfg.fsmretry = odl->pap.cfg.fsmretry; @@ -701,6 +718,7 @@ datalink_Close(struct datalink *dl, int stay) /* Please close */ switch (dl->state) { case DATALINK_OPEN: + peerid_Init(&dl->peer); FsmDown(&dl->physical->link.ccp.fsm); FsmClose(&dl->physical->link.ccp.fsm); /* fall through */ @@ -725,6 +743,7 @@ datalink_Down(struct datalink *dl, int stay) /* Carrier is lost */ switch (dl->state) { case DATALINK_OPEN: + peerid_Init(&dl->peer); FsmDown(&dl->physical->link.ccp.fsm); FsmClose(&dl->physical->link.ccp.fsm); /* fall through */ @@ -749,35 +768,55 @@ datalink_StayDown(struct datalink *dl) dl->reconnect_tries = 0; } -void -datalink_Show(struct datalink *dl, struct prompt *prompt) +int +datalink_Show(struct cmdargs const *arg) { - prompt_Printf(prompt, "Name: %s\n", dl->name); - prompt_Printf(prompt, " State: %s\n", datalink_State(dl)); - prompt_Printf(prompt, " CHAP Encryption: %s\n", - dl->chap.using_MSChap ? "MSChap" : "MD5" ); - prompt_Printf(prompt, "\nDefaults:\n"); - prompt_Printf(prompt, " Phone List: %s\n", dl->cfg.phone.list); - if (dl->cfg.dial.max) - prompt_Printf(prompt, " Dial tries: %d, delay ", dl->cfg.dial.max); + prompt_Printf(arg->prompt, "Name: %s\n", arg->cx->name); + prompt_Printf(arg->prompt, " State: %s\n", + datalink_State(arg->cx)); + prompt_Printf(arg->prompt, " CHAP Encryption: %s\n", + arg->cx->chap.using_MSChap ? "MSChap" : "MD5" ); + prompt_Printf(arg->prompt, " Peer name: "); + if (*arg->cx->peer.authname) + prompt_Printf(arg->prompt, "%s\n", arg->cx->peer.authname); + else if (arg->cx->state == DATALINK_OPEN) + prompt_Printf(arg->prompt, "None requested\n"); else - prompt_Printf(prompt, " Dial tries: infinite, delay "); - if (dl->cfg.dial.next_timeout > 0) - prompt_Printf(prompt, "%ds/", dl->cfg.dial.next_timeout); + prompt_Printf(arg->prompt, "N/A\n"); + prompt_Printf(arg->prompt, " Discriminator: %s\n", + mp_Enddisc(arg->cx->peer.enddisc.class, + arg->cx->peer.enddisc.address, + arg->cx->peer.enddisc.len)); + + prompt_Printf(arg->prompt, "\nDefaults:\n"); + prompt_Printf(arg->prompt, " Phone List: %s\n", + arg->cx->cfg.phone.list); + if (arg->cx->cfg.dial.max) + prompt_Printf(arg->prompt, " Dial tries: %d, delay ", + arg->cx->cfg.dial.max); else - prompt_Printf(prompt, "random/"); - if (dl->cfg.dial.timeout > 0) - prompt_Printf(prompt, "%ds\n", dl->cfg.dial.timeout); + prompt_Printf(arg->prompt, " Dial tries: infinite, delay "); + if (arg->cx->cfg.dial.next_timeout > 0) + prompt_Printf(arg->prompt, "%ds/", arg->cx->cfg.dial.next_timeout); else - prompt_Printf(prompt, "random\n"); - prompt_Printf(prompt, " Reconnect tries: %d, delay ", dl->cfg.reconnect.max); - if (dl->cfg.reconnect.timeout > 0) - prompt_Printf(prompt, "%ds\n", dl->cfg.reconnect.timeout); + prompt_Printf(arg->prompt, "random/"); + if (arg->cx->cfg.dial.timeout > 0) + prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.dial.timeout); else - prompt_Printf(prompt, "random\n"); - prompt_Printf(prompt, " Dial Script: %s\n", dl->cfg.script.dial); - prompt_Printf(prompt, " Login Script: %s\n", dl->cfg.script.login); - prompt_Printf(prompt, " Hangup Script: %s\n", dl->cfg.script.hangup); + prompt_Printf(arg->prompt, "random\n"); + prompt_Printf(arg->prompt, " Reconnect tries: %d, delay ", + arg->cx->cfg.reconnect.max); + if (arg->cx->cfg.reconnect.timeout > 0) + prompt_Printf(arg->prompt, "%ds\n", arg->cx->cfg.reconnect.timeout); + else + prompt_Printf(arg->prompt, "random\n"); + prompt_Printf(arg->prompt, " Dial Script: %s\n", + arg->cx->cfg.script.dial); + prompt_Printf(arg->prompt, " Login Script: %s\n", + arg->cx->cfg.script.login); + prompt_Printf(arg->prompt, " Hangup Script: %s\n", + arg->cx->cfg.script.hangup); + return 0; } int @@ -859,7 +898,7 @@ static const char *states[] = { "open" }; -static const char * +const char * datalink_State(struct datalink *dl) { if (dl->state < 0 || dl->state >= sizeof states / sizeof states[0]) diff --git a/usr.sbin/ppp/datalink.h b/usr.sbin/ppp/datalink.h index c4ddcc7cc93..4600a1720ec 100644 --- a/usr.sbin/ppp/datalink.h +++ b/usr.sbin/ppp/datalink.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.h,v 1.1.2.17 1998/04/10 13:19:06 brian Exp $ + * $Id: datalink.h,v 1.1.2.18 1998/04/18 01:01:20 brian Exp $ */ #define DATALINK_CLOSED (0) @@ -86,6 +86,8 @@ struct datalink { char *name; /* Our name */ + struct peerid peer; /* Peer identification */ + struct fsm_parent fsmp; /* Our callback functions */ const struct fsm_parent *parent; /* Our parent */ @@ -106,12 +108,14 @@ extern struct datalink *datalink_Create(const char *name, struct bundle *, const struct fsm_parent *, int); extern struct datalink *datalink_Clone(struct datalink *, const char *); extern struct datalink *datalink_Destroy(struct datalink *); +extern void datalink_GotAuthname(struct datalink *, const char *, int); extern void datalink_Up(struct datalink *, int, int); extern void datalink_Close(struct datalink *, int); extern void datalink_Down(struct datalink *, int); extern void datalink_StayDown(struct datalink *); -extern void datalink_Show(struct datalink *, struct prompt *); extern void datalink_AuthOk(struct datalink *); extern void datalink_AuthNotOk(struct datalink *); +extern int datalink_Show(struct cmdargs const *); extern int datalink_SetRedial(struct cmdargs const *); extern int datalink_SetReconnect(struct cmdargs const *); +extern const char *datalink_State(struct datalink *); diff --git a/usr.sbin/ppp/hdlc.c b/usr.sbin/ppp/hdlc.c index 9a528563991..663e13586f7 100644 --- a/usr.sbin/ppp/hdlc.c +++ b/usr.sbin/ppp/hdlc.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: hdlc.c,v 1.28.2.27 1998/04/19 15:24:42 brian Exp $ + * $Id: hdlc.c,v 1.28.2.28 1998/04/23 21:50:09 brian Exp $ * * TODO: */ @@ -97,9 +97,10 @@ static u_short const fcstab[256] = { }; void -hdlc_Init(struct hdlc *hdlc) +hdlc_Init(struct hdlc *hdlc, struct lcp *lcp) { memset(hdlc, '\0', sizeof(struct hdlc)); + hdlc->lqm.owner = lcp; } /* @@ -212,10 +213,10 @@ HdlcOutput(struct link *l, int pri, u_short proto, struct mbuf *bp) * from the last one */ lqr.PeerOutLQRs = ++p->hdlc.lqm.lqr.OutLQRs; - LqrDump("LqrOutput", &lqr); + LqrDump(l->name, "Output", &lqr); } else { lqr.PeerOutLQRs = p->hdlc.lqm.lqr.OutLQRs; - LqrDump("LqrOutput (again)", &lqr); + LqrDump(l->name, "Output (again)", &lqr); } LqrChangeOrder(&lqr, (struct lqrdata *)MBUF_CTOP(bp)); } diff --git a/usr.sbin/ppp/hdlc.h b/usr.sbin/ppp/hdlc.h index 1895966197b..436459d1189 100644 --- a/usr.sbin/ppp/hdlc.h +++ b/usr.sbin/ppp/hdlc.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: hdlc.h,v 1.14.2.9 1998/04/05 22:48:19 brian Exp $ + * $Id: hdlc.h,v 1.14.2.10 1998/04/07 00:53:44 brian Exp $ * * TODO: */ @@ -101,7 +101,7 @@ struct hdlc { }; -extern void hdlc_Init(struct hdlc *); +extern void hdlc_Init(struct hdlc *, struct lcp *); extern void hdlc_StartTimer(struct hdlc *); extern void hdlc_StopTimer(struct hdlc *); extern int hdlc_ReportStatus(struct cmdargs const *); diff --git a/usr.sbin/ppp/lcp.c b/usr.sbin/ppp/lcp.c index 9b376dc8b33..703fe1c3f96 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.55.2.45 1998/04/23 18:55:50 brian Exp $ + * $Id: lcp.c,v 1.55.2.46 1998/04/24 19:15:42 brian Exp $ * * TODO: * o Limit data field length by MRU @@ -56,6 +56,11 @@ #include "ipcp.h" #include "filter.h" #include "mp.h" +#include "chat.h" +#include "auth.h" +#include "pap.h" +#include "chap.h" +#include "datalink.h" #include "bundle.h" /* for received LQRs */ @@ -408,6 +413,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, struct lqrreq *req; char request[20], desc[22]; struct mp *mp; + struct physical *p = link2physical(fp->link); while (plen >= sizeof(struct fsmconfig)) { type = *cp; @@ -789,12 +795,16 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, mp_Enddisc(cp[2], cp + 3, length - 3)); switch (mode_type) { case MODE_REQ: - if (length-3 < sizeof lcp->fsm.bundle->ncp.mp.peer_enddisc.address && - cp[2] <= MAX_ENDDISC_CLASS) { - lcp->fsm.bundle->ncp.mp.peer_enddisc.class = cp[2]; - lcp->fsm.bundle->ncp.mp.peer_enddisc.len = length-3; - memcpy(lcp->fsm.bundle->ncp.mp.peer_enddisc.address, cp+3, length-3); - lcp->fsm.bundle->ncp.mp.peer_enddisc.address[length-3] = '\0'; + if (!p) { + LogPrintf(LogLCP, " ENDDISC rejected - not a physical link\n"); + goto reqreject; + } else if (length-3 < sizeof p->dl->peer.enddisc.address && + cp[2] <= MAX_ENDDISC_CLASS) { + p->dl->peer.enddisc.class = cp[2]; + p->dl->peer.enddisc.len = length-3; + memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3); + p->dl->peer.enddisc.address[length - 3] = '\0'; + /* XXX: If mp->active, compare and NAK with mp->peer ? */ memcpy(dec->ackend, cp, length); dec->ackend += length; } else { @@ -803,7 +813,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, cp[2]); else LogPrintf(LogLCP, " ENDDISC rejected - local max length is %d\n", - sizeof lcp->fsm.bundle->ncp.mp.peer_enddisc.address - 1); + sizeof p->dl->peer.enddisc.address - 1); goto reqreject; } break; diff --git a/usr.sbin/ppp/log.c b/usr.sbin/ppp/log.c index ff1e9e3fc04..5de125fc4bf 100644 --- a/usr.sbin/ppp/log.c +++ b/usr.sbin/ppp/log.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: log.c,v 1.25.2.8 1998/04/14 23:17:08 brian Exp $ + * $Id: log.c,v 1.25.2.9 1998/04/24 19:15:43 brian Exp $ */ #include @@ -42,7 +42,6 @@ static const char *LogNames[] = { "Async", - "Carrier", "CCP", "Chat", "Command", @@ -52,7 +51,6 @@ static const char *LogNames[] = { "ID0", "IPCP", "LCP", - "Link", "LQM", "Phase", "TCP/IP", diff --git a/usr.sbin/ppp/lqr.c b/usr.sbin/ppp/lqr.c index 1461e6961ab..299b10d79d6 100644 --- a/usr.sbin/ppp/lqr.c +++ b/usr.sbin/ppp/lqr.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lqr.c,v 1.22.2.25 1998/04/19 15:24:44 brian Exp $ + * $Id: lqr.c,v 1.22.2.26 1998/04/19 23:08:40 brian Exp $ * * o LQR based on RFC1333 * @@ -130,8 +130,10 @@ SendLqrReport(void *v) if (p->hdlc.lqm.method & LQM_LQR) { if (p->hdlc.lqm.lqr.resent > 5) { /* XXX: Should implement LQM strategy */ - LogPrintf(LogPHASE, "** Too many LQR packets lost **\n"); - LogPrintf(LogLQM, "LqrOutput: Too many LQR packets lost\n"); + LogPrintf(LogPHASE, "%s: ** Too many LQR packets lost **\n", + lcp->fsm.link->name); + LogPrintf(LogLQM, "%s: Too many LQR packets lost\n", + lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, 0); } else { @@ -143,8 +145,10 @@ SendLqrReport(void *v) p->hdlc.lqm.echo.seq_sent - 5 > p->hdlc.lqm.echo.seq_recv) || (p->hdlc.lqm.echo.seq_sent <= 5 && p->hdlc.lqm.echo.seq_sent > p->hdlc.lqm.echo.seq_recv + 5)) { - LogPrintf(LogPHASE, "** Too many ECHO LQR packets lost **\n"); - LogPrintf(LogLQM, "LqrOutput: Too many ECHO LQR packets lost\n"); + LogPrintf(LogPHASE, "%s: ** Too many ECHO LQR packets lost **\n", + lcp->fsm.link->name); + LogPrintf(LogLQM, "%s: Too many ECHO LQR packets lost\n", + lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, 0); } else @@ -186,7 +190,7 @@ LqrInput(struct physical *physical, struct mbuf *bp) lastLQR = physical->hdlc.lqm.lqr.peer.PeerInLQRs; LqrChangeOrder(lqr, &physical->hdlc.lqm.lqr.peer); - LqrDump("Input", &physical->hdlc.lqm.lqr.peer); + LqrDump(physical->link.name, "Input", &physical->hdlc.lqm.lqr.peer); /* we have received an LQR from peer */ physical->hdlc.lqm.lqr.resent = 0; @@ -227,7 +231,6 @@ StartLqm(struct lcp *lcp) StopTimer(&physical->hdlc.lqm.timer); physical->hdlc.lqm.lqr.peer_timeout = lcp->his_lqrperiod; - physical->hdlc.lqm.owner = lcp; if (lcp->his_lqrperiod) LogPrintf(LogLQM, "Expecting LQR every %d.%02d secs\n", lcp->his_lqrperiod / 100, lcp->his_lqrperiod % 100); @@ -271,10 +274,10 @@ StopLqr(struct physical *physical, int method) } void -LqrDump(const char *message, const struct lqrdata * lqr) +LqrDump(const char *link, const char *message, const struct lqrdata * lqr) { if (LogIsKept(LogLQM)) { - LogPrintf(LogLQM, "%s:\n", message); + LogPrintf(LogLQM, "%s: %s:\n", link, message); LogPrintf(LogLQM, " Magic: %08x LastOutLQRs: %08x\n", lqr->MagicNumber, lqr->LastOutLQRs); LogPrintf(LogLQM, " LastOutPackets: %08x LastOutOctets: %08x\n", diff --git a/usr.sbin/ppp/lqr.h b/usr.sbin/ppp/lqr.h index 144d2ac2148..72e9a10af24 100644 --- a/usr.sbin/ppp/lqr.h +++ b/usr.sbin/ppp/lqr.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lqr.h,v 1.12.2.2 1998/03/13 00:44:12 brian Exp $ + * $Id: lqr.h,v 1.12.2.3 1998/04/07 00:54:02 brian Exp $ * * TODO: */ @@ -49,7 +49,7 @@ struct physical; struct lcp; struct fsm; -extern void LqrDump(const char *, const struct lqrdata *); +extern void LqrDump(const char *, const char *, const struct lqrdata *); extern void LqrChangeOrder(struct lqrdata *, struct lqrdata *); extern void StartLqm(struct lcp *); extern void StopLqr(struct physical *, int); diff --git a/usr.sbin/ppp/modem.c b/usr.sbin/ppp/modem.c index 36a74140932..eac66bf1059 100644 --- a/usr.sbin/ppp/modem.c +++ b/usr.sbin/ppp/modem.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: modem.c,v 1.77.2.54 1998/04/20 00:20:37 brian Exp $ + * $Id: modem.c,v 1.77.2.55 1998/04/21 01:02:24 brian Exp $ * * TODO: */ @@ -111,7 +111,7 @@ modem_Create(struct datalink *dl, int type) p->desc.Write = modem_DescriptorWrite; p->type = type; - hdlc_Init(&p->hdlc); + hdlc_Init(&p->hdlc, &p->link.lcp); async_Init(&p->async); p->fd = -1; diff --git a/usr.sbin/ppp/mp.c b/usr.sbin/ppp/mp.c index 8b4909a7262..e344f15b038 100644 --- a/usr.sbin/ppp/mp.c +++ b/usr.sbin/ppp/mp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp.c,v 1.1.2.11 1998/04/23 23:50:39 brian Exp $ + * $Id: mp.c,v 1.1.2.12 1998/04/24 19:15:45 brian Exp $ */ #include @@ -72,6 +72,24 @@ #include "id.h" #include "arp.h" +void +peerid_Init(struct peerid *peer) +{ + peer->enddisc.class = 0; + *peer->enddisc.address = '\0'; + peer->enddisc.len = 0; + *peer->authname = '\0'; +} + +int +peerid_Equal(const struct peerid *p1, const struct peerid *p2) +{ + return !strcmp(p1->authname, p2->authname) && + p1->enddisc.class == p2->enddisc.class && + p1->enddisc.len == p2->enddisc.len && + !memcmp(p1->enddisc.address, p2->enddisc.address, p1->enddisc.len); +} + static u_int32_t inc_seq(struct mp *mp, u_int32_t seq) { @@ -139,9 +157,9 @@ mp_Init(struct mp *mp, struct bundle *bundle) { mp->peer_is12bit = mp->local_is12bit = 0; mp->peer_mrru = mp->local_mrru = 0; - mp->peer_enddisc.class = 0; - *mp->peer_enddisc.address = '\0'; - mp->peer_enddisc.len = 0; + + peerid_Init(&mp->peer); + mp->seq.out = 0; mp->seq.min_in = 0; mp->seq.next_in = 0; @@ -151,6 +169,7 @@ mp_Init(struct mp *mp, struct bundle *bundle) mp->link.type = MP_LINK; mp->link.name = "mp"; mp->link.len = sizeof *mp; + throughput_init(&mp->link.throughput); memset(mp->link.Queue, '\0', sizeof mp->link.Queue); memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in); @@ -173,11 +192,15 @@ mp_Init(struct mp *mp, struct bundle *bundle) } int -mp_Up(struct mp *mp, u_short local_mrru, u_short peer_mrru, - int local_shortseq, int peer_shortseq) +mp_Up(struct mp *mp, const struct peerid *peer, u_short local_mrru, + u_short peer_mrru, int local_shortseq, int peer_shortseq) { if (mp->active) { /* We're adding a link - do a last validation on our parameters */ + if (!peerid_Equal(peer, &mp->peer)) { + LogPrintf(LogPHASE, "Inappropriate peer !\n"); + return 0; + } if (mp->local_mrru != local_mrru || mp->peer_mrru != peer_mrru || mp->local_is12bit != local_shortseq || @@ -192,6 +215,7 @@ mp_Up(struct mp *mp, u_short local_mrru, u_short peer_mrru, mp->peer_mrru = peer_mrru; mp->local_is12bit = local_shortseq; mp->peer_is12bit = peer_shortseq; + mp->peer = *peer; throughput_init(&mp->link.throughput); memset(mp->link.Queue, '\0', sizeof mp->link.Queue); @@ -232,6 +256,7 @@ mp_Down(struct mp *mp) mp->inbufs = next; } + peerid_Init(&mp->peer); mp->active = 0; } } @@ -547,33 +572,34 @@ mp_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, "\nMy Side:\n"); if (mp->active) { - prompt_Printf(arg->prompt, " MRRU: %u\n", mp->local_mrru); - prompt_Printf(arg->prompt, " Short Seq: %s\n", + prompt_Printf(arg->prompt, " MRRU: %u\n", mp->local_mrru); + prompt_Printf(arg->prompt, " Short Seq: %s\n", mp->local_is12bit ? "on" : "off"); } - prompt_Printf(arg->prompt, " End Disc: %s\n", + prompt_Printf(arg->prompt, " Discriminator: %s\n", mp_Enddisc(mp->cfg.enddisc.class, mp->cfg.enddisc.address, mp->cfg.enddisc.len)); prompt_Printf(arg->prompt, "\nHis Side:\n"); if (mp->active) { - prompt_Printf(arg->prompt, " Next SEQ: %u\n", mp->seq.out); - prompt_Printf(arg->prompt, " MRRU: %u\n", mp->peer_mrru); - prompt_Printf(arg->prompt, " Short Seq: %s\n", + prompt_Printf(arg->prompt, " Auth Name: %s\n", mp->peer.authname); + prompt_Printf(arg->prompt, " Next SEQ: %u\n", mp->seq.out); + prompt_Printf(arg->prompt, " MRRU: %u\n", mp->peer_mrru); + prompt_Printf(arg->prompt, " Short Seq: %s\n", mp->peer_is12bit ? "on" : "off"); } - prompt_Printf(arg->prompt, " End Disc: %s\n", - mp_Enddisc(mp->peer_enddisc.class, mp->peer_enddisc.address, - mp->peer_enddisc.len)); + prompt_Printf(arg->prompt, " Discriminator: %s\n", + mp_Enddisc(mp->peer.enddisc.class, mp->peer.enddisc.address, + mp->peer.enddisc.len)); prompt_Printf(arg->prompt, "\nDefaults:\n"); - prompt_Printf(arg->prompt, " MRRU: "); + prompt_Printf(arg->prompt, " MRRU: "); if (mp->cfg.mrru) prompt_Printf(arg->prompt, "%d (multilink enabled)\n", mp->cfg.mrru); else prompt_Printf(arg->prompt, "disabled\n"); - prompt_Printf(arg->prompt, " Short Seq: %s\n", + prompt_Printf(arg->prompt, " Short Seq: %s\n", command_ShowNegval(mp->cfg.shortseq)); return 0; diff --git a/usr.sbin/ppp/mp.h b/usr.sbin/ppp/mp.h index 0d4e4445726..27f2dda09e2 100644 --- a/usr.sbin/ppp/mp.h +++ b/usr.sbin/ppp/mp.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp.h,v 1.1.2.4 1998/04/23 21:50:13 brian Exp $ + * $Id: mp.h,v 1.1.2.5 1998/04/23 23:50:39 brian Exp $ */ struct mbuf; @@ -38,45 +38,51 @@ struct cmdargs; #define ENDDISC_MAGIC 4 #define ENDDISC_PSN 5 +struct enddisc { + u_char class; + char address[50]; + int len; +}; + +struct peerid { + struct enddisc enddisc; /* Peers endpoint discriminator */ + char authname[50]; /* Peers name (authenticated) */ +}; + +extern void peerid_Init(struct peerid *); +extern int peerid_Equal(const struct peerid *, const struct peerid *); + struct mp { struct link link; unsigned active : 1; - unsigned peer_is12bit : 1; /* 12 / 24bit seq nos */ + unsigned peer_is12bit : 1; /* 12/24bit seq nos */ unsigned local_is12bit : 1; u_short peer_mrru; u_short local_mrru; - struct { - u_char class; - char address[50]; - int len; - } peer_enddisc; /* peers endpoint discriminator */ + struct peerid peer; /* Who are we talking to */ struct { - u_int32_t out; /* next outgoing seq */ - u_int32_t min_in; /* minimum received incoming seq */ - u_int32_t next_in; /* next incoming seq to process */ + u_int32_t out; /* next outgoing seq */ + u_int32_t min_in; /* minimum received incoming seq */ + u_int32_t next_in; /* next incoming seq to process */ } seq; struct { - u_short mrru; /* Max Reconstructed Receive Unit */ - unsigned shortseq : 2; /* I want short Sequence Numbers */ - struct { - u_char class; - char address[50]; - int len; - } enddisc; /* endpoint discriminator */ + u_short mrru; /* Max Reconstructed Receive Unit */ + unsigned shortseq : 2; /* I want short Sequence Numbers */ + struct enddisc enddisc; /* endpoint discriminator */ } cfg; - struct mbuf *inbufs; /* Received fragments */ - struct fsm_parent fsmp; /* Our callback functions */ - struct bundle *bundle; /* Parent */ + struct mbuf *inbufs; /* Received fragments */ + struct fsm_parent fsmp; /* Our callback functions */ + struct bundle *bundle; /* Parent */ }; struct mp_link { - u_int32_t seq; /* 12 or 24 bit incoming seq */ - int weight; /* bytes to send with each write */ + u_int32_t seq; /* 12 or 24 bit incoming seq */ + int weight; /* bytes to send with each write */ }; struct mp_header { @@ -87,7 +93,8 @@ struct mp_header { extern void mp_Init(struct mp *, struct bundle *); extern void mp_linkInit(struct mp_link *); -extern int mp_Up(struct mp *, u_short, u_short, int, int); +extern int mp_Up(struct mp *, const struct peerid *, u_short, u_short, + int, int); extern void mp_Down(struct mp *); extern void mp_Input(struct mp *, struct mbuf *, struct physical *); extern int mp_FillQueues(struct bundle *); diff --git a/usr.sbin/ppp/pap.c b/usr.sbin/ppp/pap.c index 8596a20da56..b14671d24fb 100644 --- a/usr.sbin/ppp/pap.c +++ b/usr.sbin/ppp/pap.c @@ -18,7 +18,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pap.c,v 1.20.2.24 1998/04/07 00:54:12 brian Exp $ + * $Id: pap.c,v 1.20.2.25 1998/04/16 00:26:12 brian Exp $ * * TODO: */ @@ -129,7 +129,7 @@ PapValidate(struct bundle *bundle, u_char *name, u_char *key, LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n", name, nlen, key, klen); - return AuthValidate(bundle, SECRETFILE, name, key, physical); + return AuthValidate(bundle, name, key, physical); } void @@ -150,6 +150,7 @@ PapInput(struct bundle *bundle, struct mbuf *bp, struct physical *physical) case PAP_REQUEST: cp = (u_char *) (php + 1); if (PapValidate(bundle, cp, cp + *cp + 1, physical)) { + datalink_GotAuthname(physical->dl, cp+1, *cp); SendPapCode(php->id, PAP_ACK, "Greetings!!", physical); physical->link.lcp.auth_ineed = 0; if (Enabled(bundle, OPT_UTMP)) diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index ef625f2e835..801aab51415 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.97.2.22 1998/04/23 23:50:40 brian Exp $ +.\" $Id: ppp.8,v 1.97.2.23 1998/04/24 19:15:48 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 @@ -2154,7 +2154,7 @@ unavailable. It's not considered polite to use this command. Show a list of available commands. If .Ar command is specified, show the usage string for that command. -.It link Ar name command Op Ar args +.It [data]link Ar name command Op Ar args This command may prefix any other command if the user wishes to specify which link the command should affect. This is only applicable after multiple links have been created in Multilink @@ -2861,14 +2861,16 @@ Give a summary of available show commands. Show the current IPCP statistics. .It show lcp Show the current LCP statistics. -.It show [data]link Op Ar name -Show link information. +.It show [data]link +Show high level link information. +.It show links +Show a list of available logical links. .It show log Show the current log values. .It show mem Show current memory statistics. .It show modem -Show current modem statistics. +Show low level link information. .It show proto Show current protocol totals. .It show route