mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Add support for 802.1Q VLANs
This commit is contained in:
1 parent
1d4ef08e6a
commit
caa84f048d
9 files changed
+412
-410
No files matched your search
+57
-84
@@ -88,21 +88,15 @@ struct pppoe { // RFC-2516, "A Method for Transmitting PPP Over Ethernet
|
||||
#define MG_PPPoE_PADS 0x65
|
||||
#define MG_PPPoE_PADT 0xa7
|
||||
|
||||
<<<<<<< HEAD
|
||||
#define MG_PPPoE_ST_DISC 0 // Discovery phase, see what servers are out there
|
||||
#define MG_PPPoE_ST_REQ 1 // Chose a server, request a session and wait
|
||||
#define MG_PPPoE_ST_SESS 2 // Session established, PPP traffic is exchanged
|
||||
|
||||
#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
|
||||
|
||||
static bool s_link = false; // ************ THESE SHOULD MOVE TO A struct mg_l2data *******************************
|
||||
static bool s_link = false; // ************ THESE SHOULD MOVE TO A struct
|
||||
// mg_l2data *******************************
|
||||
static uint8_t s_state = MG_PPPoE_ST_DISC;
|
||||
=======
|
||||
#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
|
||||
|
||||
static bool s_link = false; // *******************************************
|
||||
static uint8_t s_state = 0;
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
static uint16_t s_id;
|
||||
|
||||
void mg_l2_ppp_init(struct mg_tcpip_if *ifp) {
|
||||
@@ -119,12 +113,7 @@ void mg_l2_pppoe_init(struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
|
||||
bool mg_l2_ppp_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
|
||||
<<<<<<< HEAD
|
||||
if (expired_1000ms && ifp->state == MG_TCPIP_STATE_DOWN) s_link = false;
|
||||
=======
|
||||
(void) ifp;
|
||||
(void) expired_1000ms;
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
return s_link;
|
||||
}
|
||||
|
||||
@@ -148,31 +137,36 @@ static uint8_t *l2_ppp_header(enum mg_l2proto proto, uint8_t *p) {
|
||||
return ppp_header(ppp_proto, p);
|
||||
}
|
||||
|
||||
uint8_t *mg_l2_ppp_header(enum mg_l2proto proto, struct mg_l2addr *src,
|
||||
struct mg_l2addr *dst, uint8_t *frame) {
|
||||
uint8_t *mg_l2_ppp_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
struct mg_l2addr *src, struct mg_l2addr *dst,
|
||||
uint8_t *frame) {
|
||||
(void) ifp;
|
||||
(void) src;
|
||||
(void) dst;
|
||||
return l2_ppp_header(proto, hdlc_header(frame));
|
||||
}
|
||||
|
||||
extern uint8_t *mg_l2_eth_header(enum mg_l2proto proto, struct mg_l2addr *src,
|
||||
struct mg_l2addr *dst, uint8_t *frame);
|
||||
extern uint8_t *mg_l2_eth_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
struct mg_l2addr *src, struct mg_l2addr *dst,
|
||||
uint8_t *frame);
|
||||
|
||||
static uint8_t *pppoe_header(enum mg_l2proto proto, uint8_t code, uint16_t id,
|
||||
struct mg_l2addr *src, struct mg_l2addr *dst,
|
||||
uint8_t *frame) {
|
||||
static uint8_t *pppoe_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
uint8_t code, uint16_t id, struct mg_l2addr *src,
|
||||
struct mg_l2addr *dst, uint8_t *frame) {
|
||||
struct pppoe *pppoe =
|
||||
(struct pppoe *) mg_l2_eth_header(proto, src, dst, frame);
|
||||
(struct pppoe *) mg_l2_eth_header(ifp, proto, src, dst, frame);
|
||||
pppoe->vertype = 0x11;
|
||||
pppoe->code = code;
|
||||
pppoe->id = id;
|
||||
return (uint8_t *) (pppoe + 1);
|
||||
}
|
||||
|
||||
uint8_t *mg_l2_pppoe_header(enum mg_l2proto proto, struct mg_l2addr *src,
|
||||
struct mg_l2addr *dst, uint8_t *frame) {
|
||||
return l2_ppp_header(proto, pppoe_header(MG_TCPIP_L2PROTO_PPPoE_SESS, 0, s_id,
|
||||
src, dst, frame));
|
||||
uint8_t *mg_l2_pppoe_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
struct mg_l2addr *src, struct mg_l2addr *dst,
|
||||
uint8_t *frame) {
|
||||
(void) dst;
|
||||
return l2_ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
|
||||
s_id, src, dst, frame));
|
||||
}
|
||||
|
||||
// Calculate FCS/CRC for PPP frames. Could be implemented faster using lookup
|
||||
@@ -191,7 +185,7 @@ static uint16_t fcs_do(uint8_t *frame, size_t len) {
|
||||
return (uint16_t) (fcs & 0xffff);
|
||||
}
|
||||
|
||||
size_t mg_l2_ppp_footer(size_t len, uint8_t *cur) {
|
||||
size_t mg_l2_ppp_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
|
||||
uint16_t crc;
|
||||
uint8_t *frame;
|
||||
len += sizeof(struct ppp) + sizeof(struct hdlc_);
|
||||
@@ -200,19 +194,20 @@ size_t mg_l2_ppp_footer(size_t len, uint8_t *cur) {
|
||||
*cur++ = (uint8_t) ~crc; // add CRC, note the byte order
|
||||
*cur++ = (uint8_t) (~crc >> 8);
|
||||
// there is no len field in PPP
|
||||
(void) ifp;
|
||||
return len + 2;
|
||||
}
|
||||
|
||||
extern size_t mg_l2_eth_footer(size_t len, uint8_t *cur);
|
||||
extern size_t mg_l2_eth_trailer(struct mg_tcpip_if *, size_t, uint8_t *);
|
||||
|
||||
static size_t pppoe_footer(size_t len, uint8_t *cur) {
|
||||
static size_t pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
|
||||
struct pppoe *pppoe = (struct pppoe *) (cur - len - sizeof(struct pppoe));
|
||||
pppoe->len = mg_htons((uint16_t) len);
|
||||
return mg_l2_eth_footer(PDIFF(pppoe, cur), cur);
|
||||
return mg_l2_eth_trailer(ifp, PDIFF(pppoe, cur), cur);
|
||||
}
|
||||
|
||||
size_t mg_l2_pppoe_footer(size_t len, uint8_t *cur) {
|
||||
return pppoe_footer(len + sizeof(struct ppp), cur);
|
||||
size_t mg_l2_pppoe_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
|
||||
return pppoe_trailer(ifp, len + sizeof(struct ppp), cur);
|
||||
}
|
||||
|
||||
size_t mg_l2_driver_output(struct mg_tcpip_if *ifp, size_t len);
|
||||
@@ -221,15 +216,15 @@ static uint8_t *ppp_tx_frame_header(struct mg_tcpip_if *ifp, uint16_t proto) {
|
||||
uint8_t *l2p = (uint8_t *) ifp->tx.buf;
|
||||
if (ifp->l2type == MG_TCPIP_L2_PPP)
|
||||
return ppp_header(proto, hdlc_header(l2p));
|
||||
return ppp_header(proto, pppoe_header(MG_TCPIP_L2PROTO_PPPoE_SESS, 0, s_id,
|
||||
(struct mg_l2addr *) ifp->mac,
|
||||
return ppp_header(proto, pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_SESS, 0,
|
||||
s_id, (struct mg_l2addr *) ifp->mac,
|
||||
(struct mg_l2addr *) ifp->gwmac, l2p));
|
||||
}
|
||||
static size_t ppp_tx_frame_footer(struct mg_tcpip_if *ifp, size_t len,
|
||||
uint8_t *cur) {
|
||||
static size_t ppp_tx_frame_trailer(struct mg_tcpip_if *ifp, size_t len,
|
||||
uint8_t *cur) {
|
||||
return mg_l2_driver_output(ifp, ifp->l2type == MG_TCPIP_L2_PPPoE
|
||||
? mg_l2_pppoe_footer(len, cur)
|
||||
: mg_l2_ppp_footer(len, cur));
|
||||
? mg_l2_pppoe_trailer(ifp, len, cur)
|
||||
: mg_l2_ppp_trailer(ifp, len, cur));
|
||||
}
|
||||
|
||||
// Transmit a single PPP frame for the given protocol
|
||||
@@ -237,7 +232,7 @@ static size_t ppp_tx_frame(struct mg_tcpip_if *ifp, uint16_t proto,
|
||||
uint8_t *data, size_t datasz) {
|
||||
uint8_t *pay = ppp_tx_frame_header(ifp, proto);
|
||||
memcpy(pay, data, datasz);
|
||||
return ppp_tx_frame_footer(ifp, datasz, pay + datasz);
|
||||
return ppp_tx_frame_trailer(ifp, datasz, pay + datasz);
|
||||
}
|
||||
|
||||
static void ppp_handle_lcp(struct mg_tcpip_if *ifp, uint8_t *lcpp,
|
||||
@@ -367,15 +362,18 @@ static void ppp_handle_ipv6cp(struct mg_tcpip_if *ifp, uint8_t *ipv6cpp,
|
||||
case MG_PPP_IPV6CP_CFG_REQ:
|
||||
MG_VERBOSE(("got IPV6CP config request..."));
|
||||
if (len >= 10 &&
|
||||
find_opt(MG_PPP_IPV6CP_OPT_IFCID, 10, (const uint8_t *) (ipv6cp + 1),
|
||||
len - sizeof(*ipv6cp), (uint8_t *) &((struct mg_l2addr *)(ifp->gwmac))->addr.ieee64)) {
|
||||
if (((struct mg_l2addr *)(ifp->gwmac))->addr.ieee64 != 0) {
|
||||
MG_DEBUG(("IPV6CP cfg, GW IFCID: %M", mg_print_ieee64, &((struct mg_l2addr *)(ifp->gwmac))->addr.ieee64));
|
||||
find_opt(
|
||||
MG_PPP_IPV6CP_OPT_IFCID, 10, (const uint8_t *) (ipv6cp + 1),
|
||||
len - sizeof(*ipv6cp),
|
||||
(uint8_t *) &((struct mg_l2addr *) (ifp->gwmac))->addr.ieee64)) {
|
||||
if (((struct mg_l2addr *) (ifp->gwmac))->addr.ieee64 != 0) {
|
||||
MG_DEBUG(("IPV6CP cfg, GW IFCID: %M", mg_print_ieee64,
|
||||
&((struct mg_l2addr *) (ifp->gwmac))->addr.ieee64));
|
||||
ipv6cp->code = MG_PPP_IPV6CP_CFG_ACK;
|
||||
ppp_tx_frame(ifp, MG_PPP_PROTO_IPV6CP, ipv6cpp, len);
|
||||
req[1] = id;
|
||||
ifp->ip6ll[0] = 0, ifp->ip6ll[1] = 0; // clear any former ll address
|
||||
memset(req + 6, 0, 8); // Inform ifc id 0
|
||||
ifp->ip6ll[0] = 0, ifp->ip6ll[1] = 0; // clear any former ll address
|
||||
memset(req + 6, 0, 8); // Inform ifc id 0
|
||||
ppp_tx_frame(ifp, MG_PPP_PROTO_IPV6CP, req, sizeof(req));
|
||||
} else {
|
||||
MG_ERROR(("Peer is not able to provide its interface id"));
|
||||
@@ -398,9 +396,12 @@ static void ppp_handle_ipv6cp(struct mg_tcpip_if *ifp, uint8_t *ipv6cpp,
|
||||
MG_VERBOSE(("got IPV6CP config nack"));
|
||||
// NACK contains our "suggested" IFC id, use it
|
||||
if (len >= 10 &&
|
||||
find_opt(MG_PPP_IPV6CP_OPT_IFCID, 10, (const uint8_t *) (ipv6cp + 1),
|
||||
len - sizeof(*ipv6cp), (uint8_t *) &((struct mg_l2addr *)(ifp->mac))->addr.ieee64)) {
|
||||
MG_DEBUG(("IPV6CP cfg, IFCID: %M", mg_print_ieee64, &((struct mg_l2addr *)(ifp->mac))->addr.ieee64));
|
||||
find_opt(
|
||||
MG_PPP_IPV6CP_OPT_IFCID, 10, (const uint8_t *) (ipv6cp + 1),
|
||||
len - sizeof(*ipv6cp),
|
||||
(uint8_t *) &((struct mg_l2addr *) (ifp->mac))->addr.ieee64)) {
|
||||
MG_DEBUG(("IPV6CP cfg, IFCID: %M", mg_print_ieee64,
|
||||
&((struct mg_l2addr *) (ifp->mac))->addr.ieee64));
|
||||
ipv6cp->code = MG_PPP_IPV6CP_CFG_REQ;
|
||||
ppp_tx_frame(ifp, MG_PPP_PROTO_IPV6CP, ipv6cpp, len);
|
||||
} else {
|
||||
@@ -459,7 +460,7 @@ static bool ppp_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
p = ppp_tx_frame_header(ifp, MG_PPP_PROTO_LCP);
|
||||
memmove(p, &rej, sizeof(rej)); // LCP reject
|
||||
memmove(p + sizeof(rej), ppp, msglen); // rejected PPP message
|
||||
ppp_tx_frame_footer(ifp, msglen + sizeof(rej), p + msglen + sizeof(rej));
|
||||
ppp_tx_frame_trailer(ifp, msglen + sizeof(rej), p + msglen + sizeof(rej));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -483,7 +484,8 @@ bool mg_l2_ppp_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
|
||||
extern struct mg_l2addr s_mapip;
|
||||
|
||||
struct mg_l2addr *mg_l2_ppp_getaddr(uint8_t *frame) {
|
||||
struct mg_l2addr *mg_l2_ppp_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) {
|
||||
(void) ifp;
|
||||
(void) frame;
|
||||
return &s_mapip; // bogus
|
||||
}
|
||||
@@ -514,7 +516,6 @@ bool mg_l2_ppp_ip6get(struct mg_l2addr *l2addr, uint8_t *opts, uint8_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t mg_l2_ppp_ip6put(struct mg_l2addr *l2addr, uint8_t *opts) {
|
||||
(void) l2addr;
|
||||
(void) opts;
|
||||
@@ -527,40 +528,31 @@ static size_t pppoe_tx_frame(struct mg_tcpip_if *ifp, uint8_t code, uint16_t id,
|
||||
uint8_t *data, size_t datasz,
|
||||
struct mg_l2addr *dst) {
|
||||
uint8_t *l2p = (uint8_t *) ifp->tx.buf;
|
||||
uint8_t *p = pppoe_header(MG_TCPIP_L2PROTO_PPPoE_DISC, code, id,
|
||||
uint8_t *p = pppoe_header(ifp, MG_TCPIP_L2PROTO_PPPoE_DISC, code, id,
|
||||
(struct mg_l2addr *) ifp->mac, dst, l2p);
|
||||
memmove(p, data, datasz);
|
||||
return mg_l2_driver_output(ifp, pppoe_footer(datasz, p + datasz));
|
||||
return mg_l2_driver_output(ifp, pppoe_trailer(ifp, datasz, p + datasz));
|
||||
}
|
||||
|
||||
bool mg_l2_pppoe_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) {
|
||||
<<<<<<< HEAD
|
||||
if (expired_1000ms && s_state == MG_PPPoE_ST_DISC &&
|
||||
ifp->state == MG_TCPIP_STATE_LINK_UP) {
|
||||
=======
|
||||
if (expired_1000ms && s_state == 0 && ifp->driver_up) {
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
uint16_t tags[2];
|
||||
tags[0] = mg_htons(0x0101); // Service Request
|
||||
tags[1] = mg_htons(0x0000); // Any
|
||||
pppoe_tx_frame(ifp, MG_PPPoE_PADI, 0, (uint8_t *) tags, sizeof(tags),
|
||||
mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL));
|
||||
MG_DEBUG(("Sent PADI"));
|
||||
<<<<<<< HEAD
|
||||
} else if (expired_1000ms && (s_state != MG_PPPoE_ST_SESS ||
|
||||
ifp->state == MG_TCPIP_STATE_DOWN)) {
|
||||
s_state = MG_PPPoE_ST_DISC;
|
||||
=======
|
||||
} else if (expired_1000ms && (s_state != 2 || !ifp->driver_up)) {
|
||||
s_state = 0;
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
}
|
||||
return mg_l2_ppp_poll(ifp, expired_1000ms);
|
||||
}
|
||||
|
||||
extern bool mg_l2_eth_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
struct mg_str *pay, struct mg_str *raw);
|
||||
extern struct mg_l2addr *mg_l2_eth_getaddr(uint8_t *);
|
||||
extern struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *, uint8_t *);
|
||||
|
||||
bool mg_l2_pppoe_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
struct mg_str *pay, struct mg_str *raw) {
|
||||
@@ -571,12 +563,8 @@ bool mg_l2_pppoe_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
if (pay->len < sizeof(*pppoe)) return false; // Truncated
|
||||
if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_DISC) {
|
||||
MG_VERBOSE(("PPPoE_DISC"));
|
||||
<<<<<<< HEAD
|
||||
if (s_state == MG_PPPoE_ST_DISC && pppoe->code == MG_PPPoE_PADO &&
|
||||
pppoe->id == 0) {
|
||||
=======
|
||||
if (s_state == 0 && pppoe->code == MG_PPPoE_PADO && pppoe->id == 0) {
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
uint16_t tags[2];
|
||||
bool has_cookie = false;
|
||||
size_t len = pay->len - sizeof(*pppoe);
|
||||
@@ -603,39 +591,24 @@ bool mg_l2_pppoe_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto,
|
||||
taglen = sizeof(tags);
|
||||
}
|
||||
pppoe_tx_frame(ifp, MG_PPPoE_PADR, 0, p, taglen,
|
||||
mg_l2_eth_getaddr((uint8_t *) raw->buf));
|
||||
mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf));
|
||||
MG_DEBUG(("Sent PADR"));
|
||||
<<<<<<< HEAD
|
||||
s_state = MG_PPPoE_ST_REQ;
|
||||
} else if (s_state == MG_PPPoE_ST_REQ && pppoe->code == MG_PPPoE_PADS) {
|
||||
s_id = pppoe->id;
|
||||
memcpy(&ifp->gwmac, mg_l2_eth_getaddr((uint8_t *) raw->buf)->addr.mac, 6);
|
||||
memcpy(&ifp->gwmac,
|
||||
mg_l2_eth_getaddr(ifp, (uint8_t *) raw->buf)->addr.mac, 6);
|
||||
MG_DEBUG(("PPPoE session 0x%04x started", mg_ntohs(s_id)));
|
||||
s_state = MG_PPPoE_ST_SESS;
|
||||
} else if (s_state == MG_PPPoE_ST_SESS && pppoe->code == MG_PPPoE_PADT &&
|
||||
=======
|
||||
s_state = 1;
|
||||
} else if (s_state == 1 && pppoe->code == MG_PPPoE_PADS) {
|
||||
s_id = pppoe->id;
|
||||
memcpy(&ifp->gwmac, mg_l2_eth_getaddr((uint8_t *) raw->buf)->addr.mac, 6);
|
||||
MG_DEBUG(("PPPoE session 0x%04x started", mg_ntohs(s_id)));
|
||||
s_state = 2;
|
||||
} else if (s_state == 2 && pppoe->code == MG_PPPoE_PADT &&
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
pppoe->id == s_id) {
|
||||
MG_ERROR(("Got PADT"));
|
||||
s_id = 0;
|
||||
s_link = false;
|
||||
<<<<<<< HEAD
|
||||
s_state = MG_PPPoE_ST_DISC;
|
||||
}
|
||||
} else if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_SESS &&
|
||||
s_state == MG_PPPoE_ST_SESS) {
|
||||
=======
|
||||
s_state = 0;
|
||||
}
|
||||
} else if (eth_proto == MG_TCPIP_L2PROTO_PPPoE_SESS && s_state == 2) {
|
||||
>>>>>>> 3b7ca757 (Add L2 PPP and PPPoE)
|
||||
pay->buf = (char *) (pppoe + 1);
|
||||
pay->len = pay->len - sizeof(*pppoe);
|
||||
return ppp_rx(ifp, proto, pay, raw);
|
||||
|
||||
Reference in new issue
Block a user