*/
#ifndef lint
-static char rcsid[] = "$Id: lcp.c,v 1.32 1998/05/13 05:49:19 paulus Exp $";
+static char rcsid[] = "$Id: lcp.c,v 1.35 1999/03/16 02:47:00 paulus Exp $";
#endif
/*
#include <stdio.h>
#include <string.h>
-#include <syslog.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
+#include <stdlib.h>
#include "pppd.h"
#include "fsm.h"
#include "chap.h"
#include "magic.h"
+/*
+ * LCP-related command-line options.
+ */
+int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
+int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
+
+static int setescape __P((char **));
+
+static option_t lcp_option_list[] = {
+ /* LCP options */
+ { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
+ "Disable address/control compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+ { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
+ "Disable address/control compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+ { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+ "Disable asyncmap negotiation",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+ { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+ "Disable asyncmap negotiation",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+ { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
+ "Set asyncmap (for received packets)",
+ OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+ { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
+ "Set asyncmap (for received packets)",
+ OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+ { "nomagicnumber", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+ "Disable magic number negotiation (looped-back line detection)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+ { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+ "Disable magic number negotiation (looped-back line detection)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+ { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+ "Disable MRU negotiation (use default 1500)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+ { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+ "Disable MRU negotiation (use default 1500)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+ { "mru", o_int, &lcp_wantoptions[0].mru,
+ "Set MRU (maximum received packet size) for negotiation",
+ 0, &lcp_wantoptions[0].neg_mru },
+ { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
+ "Disable protocol field compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+ { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
+ "Disable protocol field compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+ { "-p", o_bool, &lcp_wantoptions[0].passive,
+ "Set passive mode", 1 },
+ { "passive", o_bool, &lcp_wantoptions[0].passive,
+ "Set passive mode", 1 },
+ { "silent", o_bool, &lcp_wantoptions[0].silent,
+ "Set silent mode", 1 },
+ { "escape", o_special, setescape,
+ "List of character codes to escape on transmission" },
+ { "lcp-echo-failure", o_int, &lcp_echo_fails,
+ "Set number of consecutive echo failures to indicate link failure" },
+ { "lcp-echo-interval", o_int, &lcp_echo_interval,
+ "Set time in seconds between LCP echo requests" },
+ { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
+ "Set time in seconds between LCP retransmissions" },
+ { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
+ "Set maximum number of LCP terminate-request transmissions" },
+ { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
+ "Set maximum number of LCP configure-request transmissions" },
+ { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
+ "Set limit on number of LCP configure-naks" },
+ {NULL}
+};
+
/* global vars */
fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
NULL,
1,
"LCP",
+ lcp_option_list,
NULL,
NULL,
NULL
(x) == CONFNAK ? "NAK" : "REJ")
+/*
+ * setescape - add chars to the set we escape on transmission.
+ */
+static int
+setescape(argv)
+ char **argv;
+{
+ int n, ret;
+ char *p, *endp;
+
+ p = *argv;
+ ret = 1;
+ while (*p) {
+ n = strtol(p, &endp, 16);
+ if (p == endp) {
+ option_error("escape parameter contains invalid hex number '%s'",
+ p);
+ return 0;
+ }
+ p = endp;
+ if (n < 0 || n == 0x5E || n > 0xFF) {
+ option_error("can't escape character 0x%x", n);
+ ret = 0;
+ } else
+ xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
+ while (*p == ',' || *p == ' ')
+ ++p;
+ }
+ return ret;
+}
+
/*
* lcp_init - Initialize LCP.
*/
implementations */
wo->neg_mru = 1;
wo->mru = DEFMRU;
- wo->neg_asyncmap = 0;
+ wo->neg_asyncmap = 1;
wo->asyncmap = 0;
wo->neg_chap = 0; /* Set to 1 on server */
wo->neg_upap = 0; /* Set to 1 on server */
case ECHOREQ:
if (f->state != OPENED)
break;
- LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
magp = inp;
PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
fsm_sdata(f, ECHOREP, id, inp, len);
struct protent *protp;
u_short prot;
- LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
-
if (len < sizeof (u_short)) {
- LCPDEBUG((LOG_INFO,
- "lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
+ LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
return;
}
GETSHORT(prot, inp);
- LCPDEBUG((LOG_INFO,
- "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!",
- prot));
-
/*
* Protocol-Reject packets received in any state other than the LCP
* OPENED state SHOULD be silently discarded.
*/
if( f->state != OPENED ){
- LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d",
- f->state));
+ LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
return;
}
return;
}
- syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x",
- prot);
+ warn("Protocol-Reject for unsupported protocol 0x%x", prot);
}
/*
* Can't reject LCP!
*/
- LCPDEBUG((LOG_WARNING,
- "lcp_protrej: Received Protocol-Reject for LCP!"));
+ error("Received Protocol-Reject for LCP!");
fsm_protreject(&lcp_fsm[unit]);
}
if (ucp - start_ucp != *lenp) {
/* this should never happen, because peer_mtu should be 1500 */
- syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
+ error("Bug in lcp_addci: wrong length");
}
}
goto bad;
return (1);
bad:
- LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!"));
+ LCPDEBUG(("lcp_acki: received bad Ack!"));
return (0);
}
if (f->state != OPENED) {
if (looped_back) {
if (++try.numloops >= lcp_loopbackfail) {
- syslog(LOG_NOTICE, "Serial line is looped back.");
+ notice("Serial line is looped back.");
lcp_close(f->unit, "Loopback detected");
}
} else
return 1;
bad:
- LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!"));
+ LCPDEBUG(("lcp_nakci: received bad Nak!"));
return 0;
}
len -= CILEN_VOID; \
INCPTR(CILEN_VOID, p); \
try.neg = 0; \
- LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \
}
#define REJCISHORT(opt, neg, val) \
if (go->neg && \
if (cishort != val) \
goto bad; \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \
}
#define REJCICHAP(opt, neg, val, digest) \
if (go->neg && \
goto bad; \
try.neg = 0; \
try.neg_upap = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
}
#define REJCILONG(opt, neg, val) \
if (go->neg && \
if (cilong != val) \
goto bad; \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \
}
#define REJCILQR(opt, neg, val) \
if (go->neg && \
if (cishort != PPP_LQR || cilong != val) \
goto bad; \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
}
#define REJCICBCP(opt, neg, val) \
if (go->neg && \
if (cichar != val) \
goto bad; \
try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \
}
REJCISHORT(CI_MRU, neg_mru, go->mru);
return 1;
bad:
- LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
+ LCPDEBUG(("lcp_rejci: received bad Reject!"));
return 0;
}
if (l < 2 || /* Not enough data for CI header or */
p[1] < 2 || /* CI length too small or */
p[1] > l) { /* CI length too big? */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!"));
+ LCPDEBUG(("lcp_reqci: bad CI length!"));
orc = CONFREJ; /* Reject bad CI */
cilen = l; /* Reject till end of packet */
l = 0; /* Don't loop again */
switch (citype) { /* Check CI type */
case CI_MRU:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU"));
if (!ao->neg_mru || /* Allow option? */
cilen != CILEN_SHORT) { /* Check CI length */
orc = CONFREJ; /* Reject CI */
break;
}
GETSHORT(cishort, p); /* Parse MRU */
- LCPDEBUG((LOG_INFO, "(%d)", cishort));
/*
* He must be able to receive at least our minimum.
break;
case CI_ASYNCMAP:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP"));
if (!ao->neg_asyncmap ||
cilen != CILEN_LONG) {
orc = CONFREJ;
break;
}
GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
/*
* Asyncmap must have set at least the bits
break;
case CI_AUTHTYPE:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
if (cilen < CILEN_SHORT ||
!(ao->neg_upap || ao->neg_chap)) {
/*
break;
}
GETSHORT(cishort, p);
- LCPDEBUG((LOG_INFO, "(%x)", cishort));
/*
* Authtype must be UPAP or CHAP.
if (cishort == PPP_PAP) {
if (ho->neg_chap || /* we've already accepted CHAP */
cilen != CILEN_SHORT) {
- LCPDEBUG((LOG_WARNING,
- "lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
+ LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
orc = CONFREJ;
break;
}
if (cishort == PPP_CHAP) {
if (ho->neg_upap || /* we've already accepted PAP */
cilen != CILEN_CHAP) {
- LCPDEBUG((LOG_INFO,
- "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
+ LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
orc = CONFREJ;
break;
}
break;
case CI_QUALITY:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY"));
if (!ao->neg_lqr ||
cilen != CILEN_LQR) {
orc = CONFREJ;
GETSHORT(cishort, p);
GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong));
/*
* Check the protocol and the reporting period.
break;
case CI_MAGICNUMBER:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER"));
if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
cilen != CILEN_LONG) {
orc = CONFREJ;
break;
}
GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
/*
* He must have a different magic number.
case CI_PCOMPRESSION:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION"));
if (!ao->neg_pcompression ||
cilen != CILEN_VOID) {
orc = CONFREJ;
break;
case CI_ACCOMPRESSION:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION"));
if (!ao->neg_accompression ||
cilen != CILEN_VOID) {
orc = CONFREJ;
break;
default:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
- citype));
+ LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
orc = CONFREJ;
break;
}
endswitch:
- LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc)));
if (orc == CONFACK && /* Good CI */
rc != CONFACK) /* but prior CI wasnt? */
continue; /* Don't send this one */
break;
}
- LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
+ LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
return (rc); /* Return final code */
}
fsm *f;
{
if (f->state == OPENED) {
- syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending);
- syslog(LOG_NOTICE, "Serial link appears to be disconnected.");
+ info("No response to %d echo-requests", lcp_echos_pending);
+ notice("Serial link appears to be disconnected.");
lcp_close(f->unit, "Peer not responding");
}
}
/*
* Start the timer for the next interval.
*/
- assert (lcp_echo_timer_running==0);
+ if (lcp_echo_timer_running)
+ warn("assertion lcp_echo_timer_running==0 failed");
TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
lcp_echo_timer_running = 1;
}
/* Check the magic number - don't count replies from ourselves. */
if (len < 4) {
- syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len);
+ dbglog("lcp: received short Echo-Reply, length %d", len);
return;
}
GETLONG(magic, inp);
if (lcp_gotoptions[f->unit].neg_magicnumber
&& magic == lcp_gotoptions[f->unit].magicnumber) {
- syslog(LOG_WARNING, "appear to have received our own echo-reply!");
+ warn("appear to have received our own echo-reply!");
return;
}