Added PPPoE support and various PPP improvements.

This commit is contained in:
marcbou 2007-08-16 18:12:20 +00:00
parent a6ca9aa306
commit 931fcfd0f5
14 changed files with 1805 additions and 75 deletions

View File

@ -328,6 +328,14 @@ tcpip_thread(void *arg)
msg->msg.cb.f(msg->msg.cb.ctx);
memp_free(MEMP_TCPIP_MSG, msg);
break;
case TCPIP_MSG_TIMEOUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
if(msg->msg.tmo.msecs != 0xffffffff)
sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
else
sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg);
break;
default:
break;
}
@ -420,6 +428,27 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
return ERR_VAL;
}
err_t
tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
if (mbox != SYS_MBOX_NULL) {
msg = memp_malloc(MEMP_TCPIP_MSG);
if (msg == NULL) {
return ERR_MEM;
}
msg->type = TCPIP_MSG_TIMEOUT;
msg->msg.tmo.msecs = msecs;
msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
return ERR_VAL;
}
/**
* Call the lower part of a netconn_* function
* This function is then running in the thread context

View File

@ -643,9 +643,19 @@
#define PPP_SUPPORT 0 /* Set for PPP */
#endif
#ifndef PPPOE_SUPPORT
#define PPPOE_SUPPORT 0 /* Set for PPP Over Ethernet */
#endif
#ifndef PPPOS_SUPPORT
#define PPPOS_SUPPORT PPP_SUPPORT /* Set for PPP Over Serial */
#endif
#if PPP_SUPPORT
#ifndef NUM_PPP
#define NUM_PPP 1 /* Max PPP sessions. */
#endif
@ -657,9 +667,15 @@
#define CHAP_SUPPORT 0 /* Set for CHAP. */
#endif
#ifndef MSCHAP_SUPPORT
#define MSCHAP_SUPPORT 0 /* Set for MSCHAP (NOT FUNCTIONAL!) */
#endif
#ifndef CBCP_SUPPORT
#define CBCP_SUPPORT 0 /* Set for CBCP (NOT FUNCTIONAL!) */
#endif
#ifndef CCP_SUPPORT
#define CCP_SUPPORT 0 /* Set for CCP (NOT FUNCTIONAL!) */
#endif
#ifndef VJ_SUPPORT
#define VJ_SUPPORT 0 /* Set for VJ header compression. */
@ -673,30 +689,48 @@
/*
* Timeouts.
*/
#ifndef FSM_DEFTIMEOUT
#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */
#endif
#ifndef FSM_DEFMAXTERMREQS
#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
#endif
#ifndef FSM_DEFMAXCONFREQS
#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
#endif
#ifndef FSM_DEFMAXNAKLOOPS
#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
#endif
#ifndef UPAP_DEFTIMEOUT
#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */
#endif
#ifndef UPAP_DEFREQTIME
#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
#endif
#ifndef CHAP_DEFTIMEOUT
#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */
#endif
#ifndef CHAP_DEFTRANSMITS
#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
#endif
/* Interval in seconds between keepalive echo requests, 0 to disable. */
#if 1
#ifndef LCP_ECHOINTERVAL
#define LCP_ECHOINTERVAL 0
#else
#define LCP_ECHOINTERVAL 10
#endif
/* Number of unanswered echo requests before failure. */
#ifndef LCP_MAXECHOFAILS
#define LCP_MAXECHOFAILS 3
#endif
/* Max Xmit idle time (in jiffies) before resend flag char. */
#ifndef PPP_MAXIDLEFLAG
#define PPP_MAXIDLEFLAG 100
#endif
/*
* Packet sizes
@ -707,6 +741,8 @@
* of living in lcp.h)
*/
#define PPP_MTU 1500 /* Default MTU (size of Info field) */
#endif
#ifndef PPP_MAXMTU
#if 0
#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
#else
@ -715,7 +751,9 @@
#define PPP_MINMTU 64
#define PPP_MRU 1500 /* default MRU = max length of info field */
#define PPP_MAXMRU 1500 /* Largest MRU we allow */
#ifndef PPP_DEFMRU
#define PPP_DEFMRU 296 /* Try for this */
#endif
#define PPP_MINMRU 128 /* No MRUs below this */

View File

@ -80,6 +80,8 @@ err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg);
#endif /* LWIP_NETIF_API */
err_t tcpip_callback(void (*f)(void *ctx), void *ctx);
err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
#define tcpip_untimeout(h, arg) tcpip_timeout(0xffffffff, h, arg)
enum tcpip_msg_type {
TCPIP_MSG_API,
@ -92,7 +94,8 @@ enum tcpip_msg_type {
#if LWIP_NETIF_API
TCPIP_MSG_NETIFAPI,
#endif /* LWIP_NETIF_API */
TCPIP_MSG_CALLBACK
TCPIP_MSG_CALLBACK,
TCPIP_MSG_TIMEOUT
};
struct tcpip_msg {
@ -106,11 +109,17 @@ struct tcpip_msg {
struct {
struct pbuf *p;
struct netif *netif;
err_t (*f)(struct pbuf *, struct netif *);
} inp;
struct {
void (*f)(void *ctx);
void *ctx;
} cb;
struct {
u32_t msecs;
sys_timeout_handler h;
void *arg;
} tmo;
} msg;
};

View File

@ -121,6 +121,8 @@ PACK_STRUCT_END
#define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP 0x0800
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
/** ARP message types (opcodes) */
#define ARP_REQUEST 1
@ -162,6 +164,8 @@ err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
#error ARP_TABLE_SIZE must fit in an s8_t
#endif
extern const struct eth_addr ethbroadcast, ethzero;
#ifdef __cplusplus
}
#endif

View File

@ -102,8 +102,8 @@ struct etharp_entry {
struct netif *netif;
};
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
static const struct eth_addr ethzero = {{0,0,0,0,0,0}};
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
const struct eth_addr ethzero = {{0,0,0,0,0,0}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
#if !LWIP_NETIF_HWADDRHINT
static u8_t etharp_cached_entry = 0;

View File

@ -51,6 +51,7 @@
#include <lwip/stats.h>
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
@ -289,6 +290,15 @@ ethernetif_input(struct netif *netif)
#endif /* ETHARP_TCPIP_INPUT */
#endif /* ETHARP_TCPIP_ETHINPUT */
#if PPPOE_SUPPORT > 0
case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */
pppoe_disc_input(netif, p);
break;
case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */
pppoe_data_input(netif, p);
break;
#endif
default:
pbuf_free(p);
p = NULL;

View File

@ -195,7 +195,7 @@ void link_terminated(int unit)
logout();
lcp_phase[unit] = PHASE_DEAD;
AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
pppMainWakeup(unit);
pppLinkTerminated(unit);
}
/*
@ -223,7 +223,7 @@ void link_down(int unit)
num_np_up = 0;
if (lcp_phase[unit] != PHASE_DEAD)
lcp_phase[unit] = PHASE_TERMINATE;
pppMainWakeup(unit);
pppLinkDown(unit);
}
/*

View File

@ -101,8 +101,10 @@ static void ChapLowerUp (int);
static void ChapLowerDown (int);
static void ChapInput (int, u_char *, int);
static void ChapProtocolReject (int);
#if 0
static int ChapPrintPkt (u_char *, int,
void (*) (void *, char *, ...), void *);
#endif
static void ChapChallengeTimeout (void *);
static void ChapResponseTimeout (void *);
@ -146,15 +148,6 @@ struct protent chap_protent = {
/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
static char *ChapCodenames[] = {
"Challenge", "Response", "Success", "Failure"
};
/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
@ -808,6 +801,10 @@ static void ChapSendResponse(chap_state *cstate)
++cstate->resp_transmits;
}
#if 0
static char *ChapCodenames[] = {
"Challenge", "Response", "Success", "Failure"
};
/*
* ChapPrintPkt - print the contents of a CHAP packet.
*/
@ -866,7 +863,8 @@ static int ChapPrintPkt(
return len + CHAP_HEADERLEN;
}
#endif
#endif /* CHAP_SUPPORT > 0 */
#endif /* PPP_SUPPORT */

View File

@ -655,7 +655,7 @@ static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
if (!proc || !(ret = proc(f, inp, len))) {
if (!proc || !((ret = proc(f, inp, len)))) {
/* Nak/reject is bad - ignore it */
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));

View File

@ -61,6 +61,12 @@
#include "lcp.h"
#include "pppdebug.h"
#if PPPOE_SUPPORT
#include "ppp_oe.h"
#else
#define PPPOE_MAXMTU PPP_MAXMRU
#endif
/*************************/
/*** LOCAL DEFINITIONS ***/

View File

@ -98,6 +98,9 @@
#if VJ_SUPPORT > 0
#include "vj.h"
#endif
#if PPPOE_SUPPORT > 0
#include "ppp_oe.h"
#endif
#include "pppdebug.h"
@ -134,24 +137,29 @@ typedef enum {
*/
typedef struct PPPControl_s {
char openFlag; /* True when in use. */
char oldFrame; /* Old framing character for fd. */
#if PPPOE_SUPPORT
struct netif *ethif;
struct pppoe_softc *pppoe_sc;
#endif
int if_up; /* True when the interface is up. */
int errCode; /* Code indicating why interface is down. */
#if PPPOS_SUPPORT
sio_fd_t fd; /* File device ID of port. */
int kill_link; /* Shut the link down. */
int sig_hup; /* Carrier lost. */
int if_up; /* True when the interface is up. */
int errCode; /* Code indicating why interface is down. */
struct pbuf *inHead, *inTail; /* The input packet. */
PPPDevStates inState; /* The input process state. */
char inEscaped; /* Escape next character. */
u16_t inProtocol; /* The input protocol code. */
u16_t inFCS; /* Input Frame Check Sequence value. */
#endif
int mtu; /* Peer's mru */
int pcomp; /* Does peer accept protocol compression? */
int accomp; /* Does peer accept addr/ctl compression? */
u_long lastXMit; /* Time of last transmission. */
ext_accm inACCM; /* Async-Ctl-Char-Map for input. */
ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
#if VJ_SUPPORT > 0
#if PPPOS_SUPPORT && VJ_SUPPORT > 0
int vjEnabled; /* Flag indicating VJ compression enabled. */
struct vjcompress vjComp; /* Van Jabobsen compression header. */
#endif
@ -180,9 +188,11 @@ struct npioctl {
/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
#if PPPOS_SUPPORT
static void pppMain(void *pd);
static void pppDrop(PPPControl *pc);
static void pppInProc(int pd, u_char *s, int l);
#endif
/******************************/
@ -220,13 +230,14 @@ struct protent *ppp_protocols[] = {
* Buffers for outgoing packets. This must be accessed only from the appropriate
* PPP task so that it doesn't need to be protected to avoid collisions.
*/
u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
u_char *outpacket_buf[NUM_PPP];
/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
#if PPPOS_SUPPORT
/*
* FCS lookup table as calculated by genfcstab.
*/
@ -279,6 +290,86 @@ static u_char pppACCMMask[] = {
};
void
pppMainWakeup(int pd)
{
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
sio_read_abort(pppControl[pd].fd);
}
#endif /* PPPOS_SUPPORT */
void
pppLinkTerminated(int pd)
{
PPPControl *pc = &pppControl[pd];
PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
#if PPPOE_SUPPORT
if(pc->ethif) {
pppoe_disconnect(pc->pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
}
void
pppLinkDown(int pd)
{
PPPControl *pc = &pppControl[pd];
PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
#if PPPOE_SUPPORT
if(pc->ethif) {
pppoe_disconnect(pc->pppoe_sc);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
}
/* these callbacks are necessary because lcp_* functions
must be called in the same context as pppInput(),
namely the tcpip_thread(), essentially because
they manipulate timeouts which are thread-private
*/
static void
pppStartCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
lcp_lowerup(pd);
lcp_open(pd); /* Start protocol */
}
static void
pppStopCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
lcp_close(pd, "User request");
}
static void
pppHupCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
lcp_lowerdown(pd);
link_terminated(pd);
}
/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
@ -286,7 +377,8 @@ static u_char pppACCMMask[] = {
struct ppp_settings ppp_settings;
void pppInit(void)
err_t
pppInit(void)
{
struct protent *protp;
int i, j;
@ -302,6 +394,10 @@ void pppInit(void)
subnetMask = htonl(0xffffff00);
outpacket_buf[i] = mem_malloc(PPP_MRU+PPP_HDRLEN);
if(!outpacket_buf[i])
return ERR_MEM;
/*
* Initialize to the standard option set.
*/
@ -313,6 +409,12 @@ void pppInit(void)
/* Clear the statistics. */
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
#endif
#if PPPOE_SUPPORT > 0
pppoe_init();
#endif
return ERR_OK;
}
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
@ -374,6 +476,7 @@ void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
ppp_settings.passwd[0] = '\0';
}
#if PPPOS_SUPPORT
/* Open a new PPP connection using the given I/O device.
* This initializes the PPP control block but does not
* attempt to negotiate the LCP session. If this port
@ -381,7 +484,7 @@ void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
* established before calling this.
* Return a new PPP connection descriptor on success or
* an error code (negative) on failure. */
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
int pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
PPPControl *pc;
int pd;
@ -401,6 +504,7 @@ int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg)
lcp_init(pd);
pc = &pppControl[pd];
pc->fd = fd;
pc->ethif= NULL;
pc->kill_link = 0;
pc->sig_hup = 0;
pc->if_up = 0;
@ -444,6 +548,99 @@ int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg)
}
return pd;
}
#endif /* PPPOS_SUPPORT */
#if PPPOE_SUPPORT
static void pppOverEthernetLinkStatusCB(int pd, int up);
void pppOverEthernetClose(int pd)
{
PPPControl* pc = &pppControl[pd];
// *TJL* There's no lcp_deinit
lcp_close(pd, NULL);
pppoe_destroy(&pc->netif);
}
int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
PPPControl *pc;
int pd;
/* Find a free PPP session descriptor. Critical region? */
for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
if (pd >= NUM_PPP)
pd = PPPERR_OPEN;
else
pppControl[pd].openFlag = !0;
/* Launch a deamon thread. */
if (pd >= 0) {
pppControl[pd].openFlag = 1;
lcp_init(pd);
lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
lcp_wantoptions[pd].neg_asyncmap = 0;
lcp_wantoptions[pd].neg_pcompression = 0;
lcp_wantoptions[pd].neg_accompression = 0;
lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
lcp_allowoptions[pd].neg_asyncmap = 0;
lcp_allowoptions[pd].neg_pcompression = 0;
lcp_allowoptions[pd].neg_accompression = 0;
pc = &pppControl[pd];
pc->if_up = 0;
pc->errCode = 0;
pc->lastXMit = 0;
#if PPPOS_SUPPORT
pc->kill_link = 0;
pc->sig_hup = 0;
pc->inState = PDIDLE;
pc->inHead = NULL;
pc->inTail = NULL;
pc->inEscaped = 0;
#if VJ_SUPPORT > 0
pc->vjEnabled = 0;
#endif
#endif /* PPPOS_SUPPORT */
pc->ethif= ethif;
memset(pc->inACCM, 0, sizeof(ext_accm));
memset(pc->outACCM, 0, sizeof(ext_accm));
pc->linkStatusCB = linkStatusCB;
pc->linkStatusCtx = linkStatusCtx;
if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
pc->openFlag = 0;
return PPPERR_OPEN;
}
pppoe_connect(pc->pppoe_sc);
if(!linkStatusCB) {
while(pd >= 0 && !pc->if_up) {
sys_msleep(500);
if (lcp_phase[pd] == PHASE_DEAD) {
pppClose(pd);
if (pc->errCode)
pd = pc->errCode;
else
pd = PPPERR_CONNECT;
}
}
}
}
return pd;
}
#endif /* PPPOE_SUPPORT */
/* Close a PPP connection and release the descriptor.
* Any outstanding packets in the queues are dropped.
@ -454,8 +651,20 @@ int pppClose(int pd)
int st = 0;
/* Disconnect */
#if PPPOE_SUPPORT
if(pc->ethif) {
PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd));
pc->errCode = PPPERR_USER;
/* This will leave us at PHASE_DEAD. */
tcpip_callback(pppStopCB, (void*)pd);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
pc->kill_link = !0;
pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
if(!pc->linkStatusCB) {
while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
@ -471,10 +680,21 @@ void pppSigHUP(int pd)
{
PPPControl *pc = &pppControl[pd];
#if PPPOE_SUPPORT
if(pc->ethif) {
PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
tcpip_callback(pppHupCB, (void*)pd);
} else
#endif /* PPPOE_SUPPORT */
{
#if PPPOS_SUPPORT
pc->sig_hup = 1;
pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
}
}
#if PPPOS_SUPPORT
static void nPut(PPPControl *pc, struct pbuf *nb)
{
struct pbuf *b;
@ -535,6 +755,50 @@ static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
return tb;
}
#endif /* PPPOS_SUPPORT */
#if PPPOE_SUPPORT
static err_t
pppifOutputOverEthernet(int pd, struct pbuf *p)
{
PPPControl *pc = &pppControl[pd];
struct pbuf *pb;
u_short protocol = PPP_IP;
int i=0;
pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM);
if(!pb) {
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
return ERR_MEM;
}
pbuf_header(pb, -pppoe_hdrlen);
pc->lastXMit = sys_jiffies();
if (!pc->pcomp || protocol > 0xFF) {
*((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
}
*((u_char*)pb->payload + i) = protocol & 0xFF;
pbuf_chain(pb, p);
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
#if LINK_STATS
lwip_stats.link.err++;
#endif /* LINK_STATS */
return PPPERR_DEVICE;
}
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return ERR_OK;
}
#endif /* PPPOE_SUPPORT */
/* Send a packet on the given connection. */
static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
@ -542,9 +806,11 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
int pd = (int)netif->state;
u_short protocol = PPP_IP;
PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB = NULL, *p;
u_char c;
#endif /* PPPOS_SUPPORT */
LWIP_UNUSED_ARG(ipaddr);
@ -571,6 +837,13 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
return ERR_RTE;
}
#if PPPOE_SUPPORT
if(pc->ethif) {
return pppifOutputOverEthernet(pd, pb);
}
#endif /* PPPOE_SUPPORT */
#if PPPOS_SUPPORT
/* Grab an output buffer. */
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
@ -675,6 +948,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));
nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */
return ERR_OK;
}
@ -708,12 +982,14 @@ int pppIOCtl(int pd, int cmd, void *arg)
else
st = PPPERR_PARAM;
break;
#if PPPOS_SUPPORT
case PPPCTLG_FD:
if (arg)
*(sio_fd_t *)arg = pc->fd;
else
st = PPPERR_PARAM;
break;
#endif /* PPPOS_SUPPORT */
default:
st = PPPERR_PARAM;
break;
@ -740,6 +1016,45 @@ u_int pppMTU(int pd)
return st;
}
#if PPPOE_SUPPORT
int pppWriteOverEthernet(int pd, const u_char *s, int n)
{
PPPControl *pc = &pppControl[pd];
struct pbuf *pb;
/* skip address & flags */
s += 2;
n -= 2;
pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM);
if(!pb) {
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
return PPPERR_ALLOC;
}
pbuf_header(pb, -pppoe_hdrlen);
pc->lastXMit = sys_jiffies();
SMEMCPY(pb->payload, s, n);
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
#if LINK_STATS
lwip_stats.link.err++;
#endif /* LINK_STATS */
return PPPERR_DEVICE;
}
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return PPPERR_NONE;
}
#endif /* PPPOE_SUPPORT */
/*
* Write n characters to a ppp link.
* RETURN: >= 0 Number of characters written
@ -748,9 +1063,19 @@ u_int pppMTU(int pd)
int pppWrite(int pd, const u_char *s, int n)
{
PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
u_char c;
u_int fcsOut = PPP_INITFCS;
struct pbuf *headMB = NULL, *tailMB;
u_int fcsOut;
struct pbuf *headMB, *tailMB;
#endif /* PPPOS_SUPPORT */
#if PPPOE_SUPPORT
if(pc->ethif) {
return pppWriteOverEthernet(pd, s, n);
}
#endif /* PPPOE_SUPPORT */
#if PPPOS_SUPPORT
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
#if LINK_STATS
@ -768,6 +1093,7 @@ int pppWrite(int pd, const u_char *s, int n)
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
pc->lastXMit = sys_jiffies();
fcsOut = PPP_INITFCS;
/* Load output buffer. */
while (n-- > 0) {
c = *s++;
@ -803,6 +1129,7 @@ int pppWrite(int pd, const u_char *s, int n)
PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */
return PPPERR_NONE;
}
@ -967,7 +1294,7 @@ int sifvjcomp(
int maxcid
)
{
#if VJ_SUPPORT > 0
#if PPPOS_SUPPORT > 0 && VJ_SUPPORT > 0
PPPControl *pc = &pppControl[pd];
pc->vjEnabled = vjcomp;
@ -1009,6 +1336,8 @@ int sifup(int pd)
if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
netif_set_up(&pc->netif);
/* ugly workaround for storing a reference to the ppp related info*/
pc->netif.dhcp = (struct dhcp *) &pc->addrs;
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
@ -1154,50 +1483,11 @@ int cifdefaultroute(int pd, u32_t l, u32_t g)
return st;
}
void
pppMainWakeup(int pd)
{
PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
sio_read_abort(pppControl[pd].fd);
}
/* these callbacks are necessary because lcp_* functions
must be called in the same context as pppInput(),
namely the tcpip_thread(), essentially because
they manipulate timeouts which are thread-private
*/
static void
pppStartCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
lcp_lowerup(pd);
lcp_open(pd); /* Start protocol */
}
static void
pppStopCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
lcp_close(pd, "User request");
}
static void
pppHupCB(void *arg)
{
int pd = (int)arg;
PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
lcp_lowerdown(pd);
link_terminated(pd);
}
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
#if PPPOS_SUPPORT
/* The main PPP process function. This implements the state machine according
* to section 4 of RFC 1661: The Point-To-Point Protocol. */
static void pppMain(void *arg)
@ -1243,6 +1533,7 @@ static void pppMain(void *arg)
}
}
PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
pppDrop(pc); // bug fix #17726
pbuf_free(p);
out:
@ -1252,8 +1543,44 @@ out:
pc->openFlag = 0;
}
#endif /* PPPOS_SUPPORT */
static struct pbuf *pppSingleBuf(struct pbuf *p)
#if PPPOE_SUPPORT
void pppOverEthernetInitFailed(void* arg)
{
PPPControl* pc;
int pd = (int)arg;
pppHupCB(arg);
pppStopCB(arg);
pc = &pppControl[pd];
pppoe_destroy(&pc->netif);
pc->openFlag = 0;
if(pc->linkStatusCB)
{
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
}
}
static void
pppOverEthernetLinkStatusCB(int pd, int up)
{
if(up) {
PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
tcpip_callback(pppStartCB, (void*)pd);
} else {
PPPControl* pc;
pc = &pppControl[pd];
tcpip_callback(pppOverEthernetInitFailed, (void*)pd);
}
}
#endif /* PPPOE_SUPPORT */
struct pbuf *pppSingleBuf(struct pbuf *p)
{
struct pbuf *q, *b;
u_char *pl;
@ -1412,6 +1739,7 @@ out:
}
#if PPPOS_SUPPORT
/*
* Drop the input packet.
*/
@ -1635,5 +1963,47 @@ static void pppInProc(int pd, u_char *s, int l)
}
avRandomize();
}
#endif /* PPPOS_SUPPORT */
#if PPPOE_SUPPORT
void pppInProcOverEthernet(int pd, struct pbuf *pb)
{
struct pppInputHeader *pih;
u16_t inProtocol;
if(pb->len < sizeof(inProtocol)) {
PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n"));
goto drop;
}
inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
/* make room for pppInputHeader - should not fail */
if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n"));
goto drop;
}
pih = pb->payload;
pih->unit = pd;
pih->proto = inProtocol;
/* Dispatch the packet thereby consuming it. */
if(tcpip_callback(pppInput, pb) != ERR_OK) {
PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd));
goto drop;
}
return;
drop:
#if LINK_STATS
lwip_stats.link.drop++;
#endif
pbuf_free(pb);
return;
}
#endif /* PPPOE_SUPPORT */
#endif /* PPP_SUPPORT */

View File

@ -329,7 +329,7 @@ struct ppp_addrs {
*** PUBLIC DATA STRUCTURES ***
*****************************/
/* Buffers for outgoing packets. */
extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
extern u_char *outpacket_buf[NUM_PPP];
extern struct ppp_settings ppp_settings;
@ -341,7 +341,7 @@ extern struct protent *ppp_protocols[];/* Table of pointers to supported protoco
***********************/
/* Initialize the PPP subsystem. */
void pppInit(void);
err_t pppInit(void);
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
* RFC 1994 says:
@ -372,13 +372,18 @@ enum pppAuthType {
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd);
/*
* Open a new PPP connection using the given I/O device.
* Open a new PPP connection using the given serial I/O device.
* This initializes the PPP control block but does not
* attempt to negotiate the LCP session.
* Return a new PPP connection descriptor on success or
* an error code (negative) on failure.
*/
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
int pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
/*
* Open a new PPP Over Ethernet (PPPOE) connection.
*/
int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
/*
* Close a PPP connection and release the descriptor.
@ -410,6 +415,14 @@ u_int pppMTU(int pd);
*/
int pppWrite(int pd, const u_char *s, int n);
void pppInProcOverEthernet(int pd, struct pbuf *pb);
struct pbuf *pppSingleBuf(struct pbuf *p);
void pppLinkTerminated(int pd);
void pppLinkDown(int pd);
void pppMainWakeup(int pd);
/* Configure i/f transmit parameters */

1092
src/netif/ppp/ppp_oe.c Normal file

File diff suppressed because it is too large Load Diff

161
src/netif/ppp/ppp_oe.h Normal file
View File

@ -0,0 +1,161 @@
/*****************************************************************************
* ppp_oe.h - PPP Over Ethernet implementation for lwIP.
*
* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 06-01-01 Marc Boucher <marc@mbsi.ca>
* Ported to lwIP.
*****************************************************************************/
/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Husemann <martin@NetBSD.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PPP_OE_H
#define PPP_OE_H
#include "lwip/opt.h"
#if PPPOE_SUPPORT > 0
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct pppoehdr {
PACK_STRUCT_FIELD(u8_t vertype);
PACK_STRUCT_FIELD(u8_t code);
PACK_STRUCT_FIELD(u16_t session);
PACK_STRUCT_FIELD(u16_t plen);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct pppoetag {
PACK_STRUCT_FIELD(u16_t tag);
PACK_STRUCT_FIELD(u16_t len);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
#define PPPOE_STATE_INITIAL 0
#define PPPOE_STATE_PADI_SENT 1
#define PPPOE_STATE_PADR_SENT 2
#define PPPOE_STATE_SESSION 3
#define PPPOE_STATE_CLOSING 4
/* passive */
#define PPPOE_STATE_PADO_SENT 1
#define PPPOE_HEADERLEN sizeof(struct pppoehdr)
#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */
#define PPPOE_TAG_EOL 0x0000 /* end of list */
#define PPPOE_TAG_SNAME 0x0101 /* service name */
#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */
#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */
#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */
#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */
#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */
#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */
#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */
#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */
#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */
#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */
#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */
#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */
#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */
#ifndef ETHERMTU
#define ETHERMTU 1500
#endif
/* two byte PPP protocol discriminator, then IP data */
#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2)
struct pppoe_softc;
void pppoe_init(void);
err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
err_t pppoe_destroy(struct netif *ifp);
int pppoe_connect(struct pppoe_softc *sc);
void pppoe_disconnect(struct pppoe_softc *sc);
void pppoe_disc_input(struct netif *netif, struct pbuf *p);
void pppoe_data_input(struct netif *netif, struct pbuf *p);
err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb);
extern int pppoe_hdrlen;
#endif /* PPPOE_SUPPORT */
#endif /* PPP_OE_H */