mirror of
https://github.com/paulusmack/ppp.git
synced 2024-11-27 05:23:38 +08:00
changes to linux interface for new kernel driver,
plus the start of multilink support
This commit is contained in:
parent
a95c8a6bd2
commit
2c872bc67b
@ -1,6 +1,6 @@
|
||||
#
|
||||
# pppd makefile for Linux
|
||||
# $Id: Makefile.linux,v 1.35 1999/12/23 01:23:07 paulus Exp $
|
||||
# $Id: Makefile.linux,v 1.36 2000/03/27 06:02:59 paulus Exp $
|
||||
#
|
||||
|
||||
# Default installation locations
|
||||
@ -50,7 +50,7 @@ PLUGIN=y
|
||||
|
||||
INCLUDE_DIRS= -I../include
|
||||
|
||||
COMPILE_FLAGS= -D_linux_=1 -DHAVE_PATHS_H -DIPX_CHANGE
|
||||
COMPILE_FLAGS= -D_linux_=1 -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MULTILINK
|
||||
|
||||
CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS)
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define RCSID "$Id: auth.c,v 1.61 2000/03/13 23:25:46 paulus Exp $"
|
||||
#define RCSID "$Id: auth.c,v 1.62 2000/03/27 06:02:59 paulus Exp $"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
@ -509,6 +509,7 @@ start_networks()
|
||||
struct protent *protp;
|
||||
|
||||
new_phase(PHASE_NETWORK);
|
||||
|
||||
#if 0
|
||||
if (!demand)
|
||||
set_filters(&pass_filter, &active_filter);
|
||||
|
221
pppd/lcp.c
221
pppd/lcp.c
@ -17,7 +17,7 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define RCSID "$Id: lcp.c,v 1.47 1999/12/23 01:27:28 paulus Exp $";
|
||||
#define RCSID "$Id: lcp.c,v 1.48 2000/03/27 06:02:59 paulus Exp $";
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
@ -107,6 +107,14 @@ static option_t lcp_option_list[] = {
|
||||
"Set limit on number of LCP configure-naks" },
|
||||
{ "receive-all", o_bool, &lax_recv,
|
||||
"Accept all received control characters", 1 },
|
||||
#ifdef HAVE_MULTILINK
|
||||
{ "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
|
||||
"Use short sequence numbers in multilink headers",
|
||||
OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf },
|
||||
{ "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
|
||||
"Don't use short sequence numbers in multilink headers",
|
||||
OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf },
|
||||
#endif /* HAVE_MULTILINK */
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@ -530,9 +538,13 @@ static void
|
||||
lcp_resetci(f)
|
||||
fsm *f;
|
||||
{
|
||||
lcp_wantoptions[f->unit].magicnumber = magic();
|
||||
lcp_wantoptions[f->unit].numloops = 0;
|
||||
lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
|
||||
lcp_options *wo = &lcp_wantoptions[f->unit];
|
||||
|
||||
wo->magicnumber = magic();
|
||||
wo->numloops = 0;
|
||||
if (!wo->neg_multilink)
|
||||
wo->neg_ssnhf = 0;
|
||||
lcp_gotoptions[f->unit] = *wo;
|
||||
peer_mru[f->unit] = PPP_MRU;
|
||||
auth_reset(f->unit);
|
||||
}
|
||||
@ -565,7 +577,10 @@ lcp_cilen(f)
|
||||
LENCICBCP(go->neg_cbcp) +
|
||||
LENCILONG(go->neg_magicnumber) +
|
||||
LENCIVOID(go->neg_pcompression) +
|
||||
LENCIVOID(go->neg_accompression));
|
||||
LENCIVOID(go->neg_accompression) +
|
||||
LENCISHORT(go->neg_multilink) +
|
||||
LENCIVOID(go->neg_ssnhf) +
|
||||
(go->neg_endpoint? CILEN_CHAR + go->endp_len: 0));
|
||||
}
|
||||
|
||||
|
||||
@ -618,6 +633,15 @@ lcp_addci(f, ucp, lenp)
|
||||
PUTCHAR(CILEN_CHAR, ucp); \
|
||||
PUTCHAR(val, ucp); \
|
||||
}
|
||||
#define ADDCIENDP(opt, neg, class, val, len) \
|
||||
if (neg) { \
|
||||
int i; \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_CHAR + len, ucp); \
|
||||
PUTCHAR(class, ucp); \
|
||||
for (i = 0; i < len; ++i) \
|
||||
PUTCHAR(val[i], ucp); \
|
||||
}
|
||||
|
||||
ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
|
||||
ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
|
||||
@ -629,6 +653,10 @@ lcp_addci(f, ucp, lenp)
|
||||
ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
|
||||
ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
|
||||
ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
|
||||
ADDCISHORT(CI_MRRU, go->neg_multilink, go->mrru);
|
||||
ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
|
||||
ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endp_class, go->endpoint,
|
||||
go->endp_len);
|
||||
|
||||
if (ucp - start_ucp != *lenp) {
|
||||
/* this should never happen, because peer_mtu should be 1500 */
|
||||
@ -742,6 +770,25 @@ lcp_ackci(f, p, len)
|
||||
if (cilong != val) \
|
||||
goto bad; \
|
||||
}
|
||||
#define ACKCIENDP(opt, neg, class, val, vlen) \
|
||||
if (neg) { \
|
||||
int i; \
|
||||
if ((len -= CILEN_CHAR + vlen) < 0) \
|
||||
goto bad; \
|
||||
GETCHAR(citype, p); \
|
||||
GETCHAR(cilen, p); \
|
||||
if (cilen != CILEN_CHAR + vlen || \
|
||||
citype != opt) \
|
||||
goto bad; \
|
||||
GETCHAR(cichar, p); \
|
||||
if (cichar != class) \
|
||||
goto bad; \
|
||||
for (i = 0; i < vlen; ++i) { \
|
||||
GETCHAR(cichar, p); \
|
||||
if (cichar != val[i]) \
|
||||
goto bad; \
|
||||
} \
|
||||
}
|
||||
|
||||
ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
|
||||
ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
|
||||
@ -753,6 +800,10 @@ lcp_ackci(f, p, len)
|
||||
ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
|
||||
ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
|
||||
ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
|
||||
ACKCISHORT(CI_MRRU, go->neg_multilink, go->mrru);
|
||||
ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
|
||||
ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endp_class, go->endpoint,
|
||||
go->endp_len);
|
||||
|
||||
/*
|
||||
* If there are any remaining CIs, then this packet is bad.
|
||||
@ -799,7 +850,7 @@ lcp_nakci(f, p, len)
|
||||
* Check packet length and CI length at each step.
|
||||
* If we find any deviations, then this packet is bad.
|
||||
*/
|
||||
#define NAKCIVOID(opt, neg, code) \
|
||||
#define NAKCIVOID(opt, neg) \
|
||||
if (go->neg && \
|
||||
len >= CILEN_VOID && \
|
||||
p[1] == CILEN_VOID && \
|
||||
@ -807,7 +858,7 @@ lcp_nakci(f, p, len)
|
||||
len -= CILEN_VOID; \
|
||||
INCPTR(CILEN_VOID, p); \
|
||||
no.neg = 1; \
|
||||
code \
|
||||
try.neg = 0; \
|
||||
}
|
||||
#define NAKCICHAP(opt, neg, code) \
|
||||
if (go->neg && \
|
||||
@ -866,6 +917,17 @@ lcp_nakci(f, p, len)
|
||||
no.neg = 1; \
|
||||
code \
|
||||
}
|
||||
#define NAKCIENDP(opt, neg) \
|
||||
if (go->neg && \
|
||||
len >= CILEN_CHAR && \
|
||||
p[0] == opt && \
|
||||
p[1] >= CILEN_CHAR && \
|
||||
p[1] <= len) { \
|
||||
len -= p[1]; \
|
||||
INCPTR(p[1], p); \
|
||||
no.neg = 1; \
|
||||
try.neg = 0; \
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't care if they want to send us smaller packets than
|
||||
@ -983,12 +1045,31 @@ lcp_nakci(f, p, len)
|
||||
* address/control compression requests; they should send
|
||||
* a Reject instead. If they send a Nak, treat it as a Reject.
|
||||
*/
|
||||
NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
|
||||
try.neg_pcompression = 0;
|
||||
);
|
||||
NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
|
||||
try.neg_accompression = 0;
|
||||
);
|
||||
NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
|
||||
NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
|
||||
|
||||
/*
|
||||
* Nak for MRRU option - accept their value if it is smaller
|
||||
* than the one we want.
|
||||
*/
|
||||
if (go->neg_multilink) {
|
||||
NAKCISHORT(CI_MRRU, neg_multilink,
|
||||
if (cishort <= wo->mrru)
|
||||
try.mrru = cishort;
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nak for short sequence numbers shouldn't be sent, treat it
|
||||
* like a reject.
|
||||
*/
|
||||
NAKCIVOID(CI_SSNHF, neg_ssnhf);
|
||||
|
||||
/*
|
||||
* Nak of the endpoint discriminator option is not permitted,
|
||||
* treat it like a reject.
|
||||
*/
|
||||
NAKCIENDP(CI_EPDISC, neg_endpoint);
|
||||
|
||||
/*
|
||||
* There may be remaining CIs, if the peer is requesting negotiation
|
||||
@ -1019,8 +1100,10 @@ lcp_nakci(f, p, len)
|
||||
|| no.neg_mru || cilen != CILEN_SHORT)
|
||||
goto bad;
|
||||
GETSHORT(cishort, p);
|
||||
if (cishort < DEFMRU)
|
||||
if (cishort < DEFMRU) {
|
||||
try.neg_mru = 1;
|
||||
try.mru = cishort;
|
||||
}
|
||||
break;
|
||||
case CI_ASYNCMAP:
|
||||
if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
|
||||
@ -1050,6 +1133,19 @@ lcp_nakci(f, p, len)
|
||||
if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
|
||||
goto bad;
|
||||
break;
|
||||
case CI_MRRU:
|
||||
if (go->neg_multilink || no.neg_multilink || cilen != CILEN_SHORT)
|
||||
goto bad;
|
||||
break;
|
||||
case CI_SSNHF:
|
||||
if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
|
||||
goto bad;
|
||||
try.neg_ssnhf = 1;
|
||||
break;
|
||||
case CI_EPDISC:
|
||||
if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
|
||||
goto bad;
|
||||
break;
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
@ -1183,6 +1279,24 @@ lcp_rejci(f, p, len)
|
||||
goto bad; \
|
||||
try.neg = 0; \
|
||||
}
|
||||
#define REJCIENDP(opt, neg, class, val, vlen) \
|
||||
if (go->neg && \
|
||||
len >= CILEN_CHAR + vlen && \
|
||||
p[0] == opt && \
|
||||
p[1] == CILEN_CHAR + vlen) { \
|
||||
int i; \
|
||||
len -= CILEN_CHAR + vlen; \
|
||||
INCPTR(p[1], p); \
|
||||
GETCHAR(cichar, p); \
|
||||
if (cichar != class) \
|
||||
goto bad; \
|
||||
for (i = 0; i < vlen; ++i) { \
|
||||
GETCHAR(cichar, p); \
|
||||
if (cichar != val[i]) \
|
||||
goto bad; \
|
||||
} \
|
||||
try.neg = 0; \
|
||||
}
|
||||
|
||||
REJCISHORT(CI_MRU, neg_mru, go->mru);
|
||||
REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
|
||||
@ -1195,6 +1309,10 @@ lcp_rejci(f, p, len)
|
||||
REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
|
||||
REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
|
||||
REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
|
||||
REJCISHORT(CI_MRRU, neg_multilink, go->mrru);
|
||||
REJCIVOID(CI_SSNHF, neg_ssnhf);
|
||||
REJCIENDP(CI_EPDISC, neg_endpoint, go->endp_class, go->endpoint,
|
||||
go->endp_len);
|
||||
|
||||
/*
|
||||
* If there are any remaining CIs, then this packet is bad.
|
||||
@ -1477,6 +1595,44 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
|
||||
ho->neg_accompression = 1;
|
||||
break;
|
||||
|
||||
case CI_MRRU:
|
||||
if (!ao->neg_multilink ||
|
||||
cilen != CILEN_SHORT) {
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
|
||||
GETSHORT(cishort, p);
|
||||
/* possibly should insist on a minimum/maximum MRRU here */
|
||||
ho->neg_multilink = 1;
|
||||
ho->mrru = cishort;
|
||||
break;
|
||||
|
||||
case CI_SSNHF:
|
||||
if (!ao->neg_ssnhf ||
|
||||
cilen != CILEN_VOID) {
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
ho->neg_ssnhf = 1;
|
||||
break;
|
||||
|
||||
case CI_EPDISC:
|
||||
if (!ao->neg_endpoint ||
|
||||
cilen < CILEN_CHAR ||
|
||||
cilen > CILEN_CHAR + MAX_ENDP_LEN) {
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
GETCHAR(cichar, p);
|
||||
cilen -= CILEN_CHAR;
|
||||
ho->neg_endpoint = 1;
|
||||
ho->endp_class = cichar;
|
||||
ho->endp_len = cilen;
|
||||
BCOPY(p, ho->endpoint, cilen);
|
||||
INCPTR(cilen, p);
|
||||
break;
|
||||
|
||||
default:
|
||||
LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
|
||||
orc = CONFREJ;
|
||||
@ -1627,6 +1783,10 @@ static char *lcp_codenames[] = {
|
||||
"EchoReq", "EchoRep", "DiscReq"
|
||||
};
|
||||
|
||||
static char *endp_class_names[] = {
|
||||
"null", "local", "IP", "MAC", "magic", "phone"
|
||||
};
|
||||
|
||||
static int
|
||||
lcp_printpkt(p, plen, printer, arg)
|
||||
u_char *p;
|
||||
@ -1634,8 +1794,9 @@ lcp_printpkt(p, plen, printer, arg)
|
||||
void (*printer) __P((void *, char *, ...));
|
||||
void *arg;
|
||||
{
|
||||
int code, id, len, olen;
|
||||
int code, id, len, olen, i;
|
||||
u_char *pstart, *optend;
|
||||
u_char cichar;
|
||||
u_short cishort;
|
||||
u_int32_t cilong;
|
||||
|
||||
@ -1763,6 +1924,30 @@ lcp_printpkt(p, plen, printer, arg)
|
||||
printer(arg, "accomp");
|
||||
}
|
||||
break;
|
||||
case CI_MRRU:
|
||||
if (olen == CILEN_SHORT) {
|
||||
p += 2;
|
||||
GETSHORT(cishort, p);
|
||||
printer(arg, "mrru %d", cishort);
|
||||
}
|
||||
break;
|
||||
case CI_SSNHF:
|
||||
if (olen == CILEN_VOID) {
|
||||
p += 2;
|
||||
printer(arg, "ssnhf");
|
||||
}
|
||||
break;
|
||||
case CI_EPDISC:
|
||||
if (olen >= CILEN_CHAR) {
|
||||
p += 2;
|
||||
GETCHAR(cichar, p);
|
||||
if (cichar <= 5)
|
||||
printer(arg, "endpoint [%s]:",
|
||||
endp_class_names[cichar]);
|
||||
else
|
||||
printer(arg, "endpoint [%d]:");
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (p < optend) {
|
||||
GETCHAR(code, p);
|
||||
@ -1795,10 +1980,14 @@ lcp_printpkt(p, plen, printer, arg)
|
||||
}
|
||||
|
||||
/* print the rest of the bytes in the packet */
|
||||
for (; len > 0; --len) {
|
||||
for (i = 0; i < len && i < 32; ++i) {
|
||||
GETCHAR(code, p);
|
||||
printer(arg, " %.2x", code);
|
||||
}
|
||||
if (i < len) {
|
||||
printer(arg, " ...");
|
||||
p += len - i;
|
||||
}
|
||||
|
||||
return p - pstart;
|
||||
}
|
||||
|
17
pppd/lcp.h
17
pppd/lcp.h
@ -16,7 +16,7 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: lcp.h,v 1.13 1998/11/07 06:59:27 paulus Exp $
|
||||
* $Id: lcp.h,v 1.14 2000/03/27 06:03:00 paulus Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -30,6 +30,9 @@
|
||||
#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
|
||||
#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
|
||||
#define CI_CALLBACK 13 /* callback */
|
||||
#define CI_MRRU 17 /* max reconstructed receive unit; multilink */
|
||||
#define CI_SSNHF 18 /* short sequence numbers for multilink */
|
||||
#define CI_EPDISC 19 /* endpoint discriminator */
|
||||
|
||||
/*
|
||||
* LCP-specific packet types.
|
||||
@ -40,6 +43,9 @@
|
||||
#define DISCREQ 11 /* Discard Request */
|
||||
#define CBCP_OPT 6 /* Use callback control protocol */
|
||||
|
||||
/* maximum length of endpoint discriminator value */
|
||||
#define MAX_ENDP_LEN 20
|
||||
|
||||
/*
|
||||
* The state of options is described by an lcp_options structure.
|
||||
*/
|
||||
@ -56,12 +62,19 @@ typedef struct lcp_options {
|
||||
bool neg_accompression; /* HDLC Address/Control Field Compression? */
|
||||
bool neg_lqr; /* Negotiate use of Link Quality Reports */
|
||||
bool neg_cbcp; /* Negotiate use of CBCP */
|
||||
bool neg_multilink; /* negotiate multilink (MRRU) */
|
||||
bool neg_ssnhf; /* negotiate short sequence numbers */
|
||||
bool neg_endpoint; /* negotiate endpoint discriminator */
|
||||
int mru; /* Value of MRU */
|
||||
int mrru; /* Value of MRRU, and multilink enable */
|
||||
u_char chap_mdtype; /* which MD type (hashing algorithm) */
|
||||
u_int32_t asyncmap; /* Value of async map */
|
||||
u_int32_t magicnumber;
|
||||
int numloops; /* Number of loops during magic number neg. */
|
||||
int numloops; /* Number of loops during magic number neg. */
|
||||
u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
|
||||
int endp_class; /* endpoint discriminator class */
|
||||
int endp_len; /* endpoint discriminator length */
|
||||
u_char endpoint[MAX_ENDP_LEN]; /* endpoint discriminator value */
|
||||
} lcp_options;
|
||||
|
||||
extern fsm lcp_fsm[];
|
||||
|
@ -17,7 +17,7 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define RCSID "$Id: main.c,v 1.90 2000/03/13 23:39:58 paulus Exp $"
|
||||
#define RCSID "$Id: main.c,v 1.91 2000/03/27 06:03:01 paulus Exp $"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
@ -781,7 +781,7 @@ main(argc, argv)
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
if (!demand) {
|
||||
if (!demand && ifunit >= 0) {
|
||||
|
||||
info("Using interface ppp%d", ifunit);
|
||||
slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);
|
||||
|
@ -17,7 +17,7 @@
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define RCSID "$Id: options.c,v 1.70 2000/03/13 23:39:58 paulus Exp $"
|
||||
#define RCSID "$Id: options.c,v 1.71 2000/03/27 06:03:03 paulus Exp $"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
@ -103,6 +103,8 @@ char linkname[MAXPATHLEN]; /* logical name for link */
|
||||
bool tune_kernel; /* may alter kernel settings */
|
||||
int connect_delay = 1000; /* wait this many ms after connect script */
|
||||
int max_data_rate; /* max bytes/sec through charshunt */
|
||||
int req_unit = -1; /* requested interface unit */
|
||||
bool multilink = 0; /* Enable multilink operation */
|
||||
|
||||
extern option_t auth_options[];
|
||||
extern struct stat devstat;
|
||||
@ -276,6 +278,18 @@ option_t general_options[] = {
|
||||
"Maximum time (in ms) to wait after connect script finishes" },
|
||||
{ "datarate", o_int, &max_data_rate,
|
||||
"Maximum data rate in bytes/sec (with pty, notty or record option)" },
|
||||
{ "unit", o_int, &req_unit,
|
||||
"PPP interface unit number to use if possible", OPT_LLIMIT, 0, 0 },
|
||||
#ifdef HAVE_MULTILINK
|
||||
{ "multilink", o_bool, &multilink,
|
||||
"Enable multilink operation", 1 },
|
||||
{ "nomultilink", o_bool, &multilink,
|
||||
"Disable multilink operation", 0 },
|
||||
{ "mp", o_bool, &multilink,
|
||||
"Enable multilink operation", 1 },
|
||||
{ "nomp", o_bool, &multilink,
|
||||
"Disable multilink operation", 0 },
|
||||
#endif /* HAVE_MULTILINK */
|
||||
#ifdef PLUGIN
|
||||
{ "plugin", o_special, loadplugin,
|
||||
"Load a plug-in module into pppd", OPT_PRIV },
|
||||
|
@ -16,7 +16,7 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: pppd.h,v 1.50 2000/03/13 23:39:58 paulus Exp $
|
||||
* $Id: pppd.h,v 1.51 2000/03/27 06:03:06 paulus Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -217,6 +217,8 @@ extern char linkname[MAXPATHLEN]; /* logical name for link */
|
||||
extern bool tune_kernel; /* May alter kernel settings as necessary */
|
||||
extern int connect_delay; /* Time to delay after connect script */
|
||||
extern int max_data_rate; /* max bytes/sec through charshunt */
|
||||
extern int req_unit; /* interface unit number to use */
|
||||
extern bool multilink; /* enable multilink operation */
|
||||
|
||||
#ifdef PPP_FILTER
|
||||
extern struct bpf_program pass_filter; /* Filter for pkts to pass */
|
||||
|
240
pppd/sys-linux.c
240
pppd/sys-linux.c
@ -124,6 +124,7 @@ static int master_fd = -1;
|
||||
static int sock6_fd = -1;
|
||||
#endif /* INET6 */
|
||||
static int ppp_dev_fd = -1; /* fd for /dev/ppp (new style driver) */
|
||||
static int chindex; /* channel index (new style driver) */
|
||||
|
||||
static fd_set in_fds; /* set of fds that wait_input waits for */
|
||||
static int max_in_fd; /* highest fd set in in_fds */
|
||||
@ -337,6 +338,8 @@ sys_close(void)
|
||||
|
||||
static int set_kdebugflag (int requested_level)
|
||||
{
|
||||
if (new_style_driver && ifunit < 0)
|
||||
return 1;
|
||||
if (ioctl(ppp_dev_fd, PPPIOCSDEBUG, &requested_level) < 0) {
|
||||
if ( ! ok_error (errno) )
|
||||
error("ioctl(PPPIOCSDEBUG): %m");
|
||||
@ -355,26 +358,23 @@ static int set_kdebugflag (int requested_level)
|
||||
int establish_ppp (int tty_fd)
|
||||
{
|
||||
int x;
|
||||
int fd = -1;
|
||||
|
||||
/*
|
||||
* The current PPP device will be the tty file.
|
||||
*/
|
||||
set_ppp_fd (tty_fd);
|
||||
if (new_style_driver)
|
||||
add_fd(tty_fd);
|
||||
/*
|
||||
* Ensure that the tty device is in exclusive mode.
|
||||
*/
|
||||
if (ioctl(tty_fd, TIOCEXCL, 0) < 0) {
|
||||
if ( ! ok_error ( errno ))
|
||||
warn("ioctl(TIOCEXCL): %m");
|
||||
warn("Couldn't make tty exclusive: %m");
|
||||
}
|
||||
/*
|
||||
* Demand mode - prime the old ppp device to relinquish the unit.
|
||||
*/
|
||||
if (!new_style_driver && looped
|
||||
&& ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0)
|
||||
fatal("ioctl(transfer ppp unit): %m(%d)", errno);
|
||||
&& ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0) {
|
||||
error("ioctl(transfer ppp unit): %m");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Set the current tty to the PPP discpline
|
||||
*/
|
||||
@ -382,32 +382,71 @@ int establish_ppp (int tty_fd)
|
||||
#ifndef N_SYNC_PPP
|
||||
#define N_SYNC_PPP 14
|
||||
#endif
|
||||
if (new_style_driver)
|
||||
ppp_disc = sync_serial ? N_SYNC_PPP:N_PPP;
|
||||
|
||||
ppp_disc = (new_style_driver && sync_serial)? N_SYNC_PPP: N_PPP;
|
||||
if (ioctl(tty_fd, TIOCSETD, &ppp_disc) < 0) {
|
||||
if ( ! ok_error (errno) )
|
||||
fatal("ioctl(TIOCSETD): %m(%d)", errno);
|
||||
if ( ! ok_error (errno) ) {
|
||||
error("Couldn't set tty to PPP discipline: %m");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Find out which interface we were given.
|
||||
*/
|
||||
|
||||
if (new_style_driver) {
|
||||
if (!looped) {
|
||||
/* allocate ourselves a ppp unit */
|
||||
ifunit = -1;
|
||||
if (ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit) < 0)
|
||||
fatal("Couldn't create new ppp unit: %m");
|
||||
set_kdebugflag(kdebugflag);
|
||||
} else {
|
||||
/* Open another instance of /dev/ppp and connect the channel to it */
|
||||
int flags;
|
||||
|
||||
if (ioctl(tty_fd, PPPIOCGCHAN, &chindex) == -1) {
|
||||
error("Couldn't get channel number: %m");
|
||||
goto err;
|
||||
}
|
||||
dbglog("using channel %d", chindex);
|
||||
fd = open("/dev/ppp", O_RDWR);
|
||||
if (fd < 0) {
|
||||
error("Couldn't reopen /dev/ppp: %m");
|
||||
goto err;
|
||||
}
|
||||
if (ioctl(fd, PPPIOCATTCHAN, &chindex) < 0) {
|
||||
error("Couldn't attach to channel %d: %m", chindex);
|
||||
goto err_close;
|
||||
}
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
warn("Couldn't set /dev/ppp (channel) to nonblock: %m");
|
||||
set_ppp_fd(fd);
|
||||
|
||||
ifunit = -1;
|
||||
if (!looped && !multilink) {
|
||||
/*
|
||||
* Create a new PPP unit.
|
||||
*/
|
||||
ifunit = req_unit;
|
||||
x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
|
||||
if (x < 0 && req_unit >= 0 && errno == EEXIST) {
|
||||
warn("Couldn't allocate PPP unit %d as it is already in use");
|
||||
ifunit = -1;
|
||||
x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
|
||||
}
|
||||
if (x < 0) {
|
||||
error("Couldn't create new ppp unit: %m");
|
||||
goto err_close;
|
||||
}
|
||||
}
|
||||
|
||||
if (looped)
|
||||
set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC);
|
||||
|
||||
if (!multilink) {
|
||||
add_fd(ppp_dev_fd);
|
||||
if (ioctl(fd, PPPIOCCONNECT, &ifunit) < 0) {
|
||||
error("Couldn't attach to PPP unit %d: %m", ifunit);
|
||||
goto err_close;
|
||||
}
|
||||
}
|
||||
if (ioctl(tty_fd, PPPIOCATTACH, &ifunit) < 0) {
|
||||
if (errno == EIO)
|
||||
return -1;
|
||||
fatal("Couldn't attach tty to PPP unit %d: %m", ifunit);
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Old-style driver: find out which interface we were given.
|
||||
*/
|
||||
set_ppp_fd (tty_fd);
|
||||
if (ioctl(tty_fd, PPPIOCGUNIT, &x) < 0) {
|
||||
if ( ! ok_error (errno))
|
||||
fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
|
||||
@ -416,32 +455,40 @@ int establish_ppp (int tty_fd)
|
||||
if (looped && x != ifunit)
|
||||
fatal("transfer_ppp failed: wanted unit %d, got %d", ifunit, x);
|
||||
ifunit = x;
|
||||
|
||||
/*
|
||||
* Fetch the initial file flags and reset blocking mode on the file.
|
||||
*/
|
||||
initfdflags = fcntl(tty_fd, F_GETFL);
|
||||
if (initfdflags == -1 ||
|
||||
fcntl(tty_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
|
||||
if ( ! ok_error (errno))
|
||||
warn("Couldn't set device to non-blocking mode: %m");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable debug in the driver if requested.
|
||||
*/
|
||||
if (!looped)
|
||||
set_kdebugflag (kdebugflag);
|
||||
looped = 0;
|
||||
|
||||
set_flags(tty_fd, get_flags(tty_fd) & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
|
||||
/*
|
||||
* Enable debug in the driver if requested.
|
||||
*/
|
||||
if (!looped)
|
||||
set_kdebugflag (kdebugflag);
|
||||
|
||||
set_flags(ppp_fd, get_flags(ppp_fd) & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
|
||||
SC_RCV_EVNP | SC_RCV_ODDP));
|
||||
|
||||
SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
|
||||
driver_version, driver_modification, driver_patch));
|
||||
|
||||
/*
|
||||
* Fetch the initial file flags and reset blocking mode on the file.
|
||||
*/
|
||||
initfdflags = fcntl(tty_fd, F_GETFL);
|
||||
if (initfdflags == -1 ||
|
||||
fcntl(tty_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
|
||||
if ( ! ok_error (errno))
|
||||
warn("Couldn't set device to non-blocking mode: %m");
|
||||
}
|
||||
return ppp_fd;
|
||||
|
||||
return ppp_dev_fd;
|
||||
err_close:
|
||||
close(fd);
|
||||
err:
|
||||
if (ioctl(tty_fd, TIOCSETD, &tty_disc) < 0 && !ok_error(errno))
|
||||
warn("Couldn't reset tty to normal line discipline: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
@ -452,8 +499,6 @@ int establish_ppp (int tty_fd)
|
||||
|
||||
void disestablish_ppp(int tty_fd)
|
||||
{
|
||||
if (new_style_driver)
|
||||
remove_fd(tty_fd);
|
||||
if (!hungup) {
|
||||
/*
|
||||
* Flush the tty output buffer so that the TIOCSETD doesn't hang.
|
||||
@ -480,27 +525,44 @@ void disestablish_ppp(int tty_fd)
|
||||
}
|
||||
}
|
||||
initfdflags = -1;
|
||||
if (new_style_driver && !looped) {
|
||||
if (ioctl(ppp_dev_fd, PPPIOCDETACH) < 0) {
|
||||
if (errno == ENOTTY) {
|
||||
/* first version of new driver didn't have PPPIOCDETACH */
|
||||
int flags;
|
||||
|
||||
close(ppp_dev_fd);
|
||||
ppp_dev_fd = open("/dev/ppp", O_RDWR);
|
||||
if (ppp_dev_fd < 0)
|
||||
fatal("Couldn't reopen /dev/ppp: %m");
|
||||
flags = fcntl(ppp_dev_fd, F_GETFL);
|
||||
if (flags == -1
|
||||
|| fcntl(ppp_dev_fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
warn("Couldn't set /dev/ppp to nonblock: %m");
|
||||
} else
|
||||
error("Couldn't release PPP unit: %m");
|
||||
}
|
||||
set_ppp_fd(-1);
|
||||
if (new_style_driver) {
|
||||
close(ppp_fd);
|
||||
ppp_fd = -1;
|
||||
if (!looped && ioctl(ppp_dev_fd, PPPIOCDETACH) < 0)
|
||||
error("Couldn't release PPP unit: %m");
|
||||
if (!multilink)
|
||||
remove_fd(ppp_dev_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* bundle_attach - attach our link to a given PPP unit.
|
||||
*/
|
||||
int bundle_attach(int ifnum)
|
||||
{
|
||||
int mrru = 1500;
|
||||
|
||||
if (!new_style_driver)
|
||||
return -1;
|
||||
|
||||
if (ioctl(ppp_dev_fd, PPPIOCATTACH, &ifnum) < 0) {
|
||||
error("Couldn't attach to interface unit %d: %m\n", ifnum);
|
||||
return -1;
|
||||
}
|
||||
set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_MULTILINK);
|
||||
if (ioctl(ppp_dev_fd, PPPIOCSMRRU, &mrru) < 0)
|
||||
error("Couldn't set interface MRRU: %m");
|
||||
|
||||
if (ioctl(ppp_fd, PPPIOCCONNECT, &ifnum) < 0) {
|
||||
error("Couldn't connect to interface unit %d: %m", ifnum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbglog("bundle_attach succeeded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* clean_check - Fetch the flags for the device and generate
|
||||
@ -781,6 +843,9 @@ void restore_tty (int tty_fd)
|
||||
|
||||
void output (int unit, unsigned char *p, int len)
|
||||
{
|
||||
int fd = ppp_fd;
|
||||
int proto;
|
||||
|
||||
if (debug)
|
||||
dbglog("sent %P", p, len);
|
||||
|
||||
@ -789,8 +854,11 @@ void output (int unit, unsigned char *p, int len)
|
||||
if (new_style_driver) {
|
||||
p += 2;
|
||||
len -= 2;
|
||||
proto = (p[0] << 8) + p[1];
|
||||
if (!multilink && proto != PPP_LCP)
|
||||
fd = ppp_dev_fd;
|
||||
}
|
||||
if (write(ppp_dev_fd, p, len) < 0) {
|
||||
if (write(fd, p, len) < 0) {
|
||||
if (errno == EWOULDBLOCK || errno == ENOBUFS
|
||||
|| errno == ENXIO || errno == EIO || errno == EINTR)
|
||||
warn("write: warning: %m (%d)", errno);
|
||||
@ -808,11 +876,12 @@ void output (int unit, unsigned char *p, int len)
|
||||
|
||||
void wait_input(struct timeval *timo)
|
||||
{
|
||||
fd_set ready;
|
||||
fd_set ready, exc;
|
||||
int n;
|
||||
|
||||
ready = in_fds;
|
||||
n = select(max_in_fd + 1, &ready, NULL, &ready, timo);
|
||||
exc = in_fds;
|
||||
n = select(max_in_fd + 1, &ready, NULL, &exc, timo);
|
||||
if (n < 0 && errno != EINTR)
|
||||
fatal("select: %m(%d)", errno);
|
||||
}
|
||||
@ -852,16 +921,17 @@ int read_packet (unsigned char *buf)
|
||||
len -= 2;
|
||||
}
|
||||
nr = -1;
|
||||
if (new_style_driver) {
|
||||
nr = read(ppp_dev_fd, buf, len);
|
||||
if (nr < 0 && errno != EWOULDBLOCK && errno != EIO)
|
||||
error("read /dev/ppp: %m");
|
||||
}
|
||||
if (nr < 0 && ppp_fd >= 0) {
|
||||
if (ppp_fd >= 0) {
|
||||
nr = read(ppp_fd, buf, len);
|
||||
if (nr < 0 && errno != EWOULDBLOCK && errno != EIO)
|
||||
error("read: %m");
|
||||
}
|
||||
if (nr < 0 && new_style_driver && !multilink) {
|
||||
/* N.B. we read ppp_fd first since LCP packets come in there. */
|
||||
nr = read(ppp_dev_fd, buf, len);
|
||||
if (nr < 0 && errno != EWOULDBLOCK && errno != EIO)
|
||||
error("read /dev/ppp: %m");
|
||||
}
|
||||
return (new_style_driver && nr > 0)? nr+2: nr;
|
||||
}
|
||||
|
||||
@ -916,7 +986,7 @@ void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
|
||||
ifr.ifr_mtu = mtu;
|
||||
|
||||
if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
|
||||
if (ifunit >= 0 && ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
|
||||
fatal("ioctl(SIOCSIFMTU): %m(%d)", errno);
|
||||
|
||||
if (!still_ppp())
|
||||
@ -975,7 +1045,8 @@ void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
|
||||
if ( ! ok_error (errno))
|
||||
error("ioctl(PPPIOCSMRU): %m(%d)", errno);
|
||||
}
|
||||
if (new_style_driver && ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
|
||||
if (new_style_driver && ifunit >= 0
|
||||
&& ioctl(ppp_dev_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
|
||||
error("Couldn't set MRU in generic PPP layer: %m");
|
||||
|
||||
SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
|
||||
@ -1694,6 +1765,7 @@ int ppp_available(void)
|
||||
|
||||
if (kernel_version >= KVERSION(2,3,13)) {
|
||||
fd = open("/dev/ppp", O_RDWR);
|
||||
#if 0
|
||||
if (fd < 0 && errno == ENOENT) {
|
||||
/* try making it and see if that helps. */
|
||||
if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
|
||||
@ -1707,6 +1779,7 @@ int ppp_available(void)
|
||||
fd = open("/dev/ppp", O_RDWR);
|
||||
}
|
||||
}
|
||||
#endif /* 0 */
|
||||
if (fd >= 0) {
|
||||
new_style_driver = 1;
|
||||
|
||||
@ -1717,6 +1790,7 @@ int ppp_available(void)
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2281,13 +2355,19 @@ get_pty(master_fdp, slave_fdp, slave_name, uid)
|
||||
int
|
||||
open_ppp_loopback(void)
|
||||
{
|
||||
int flags;
|
||||
int flags, x;
|
||||
|
||||
looped = 1;
|
||||
if (new_style_driver) {
|
||||
/* allocate ourselves a ppp unit */
|
||||
ifunit = -1;
|
||||
if (ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit) < 0)
|
||||
ifunit = req_unit;
|
||||
x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
|
||||
if (x < 0 && req_unit >= 0 && errno == EEXIST) {
|
||||
warn("Couldn't allocate PPP unit %d as it is already in use");
|
||||
ifunit = -1;
|
||||
x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
|
||||
}
|
||||
if (x < 0)
|
||||
fatal("Couldn't create PPP unit: %m");
|
||||
set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC);
|
||||
set_kdebugflag(kdebugflag);
|
||||
@ -2514,5 +2594,9 @@ sys_check_options(void)
|
||||
driver_patch);
|
||||
return 0;
|
||||
}
|
||||
if (multilink && !new_style_driver) {
|
||||
option_error("multilink is not supported by the kernel driver");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user