From ba47e29c28ab962b9323c92ebaa37c93ee017d1d Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Fri, 13 Mar 2026 08:53:36 -0300 Subject: [PATCH] Add L2 PPP and PPPoE --- mongoose.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ mongoose.h | 1 + src/l2_ppp.c | 12 ++++++++++ src/net_builtin.h | 1 + 4 files changed, 71 insertions(+) diff --git a/mongoose.c b/mongoose.c index 34733661..13a4d2d4 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3740,6 +3740,7 @@ 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 @@ -3748,6 +3749,12 @@ struct pppoe { // RFC-2516, "A Method for Transmitting PPP Over Ethernet static bool s_link = false; // ******************************************* 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; +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) static uint16_t s_id; void mg_l2_ppp_init(struct mg_tcpip_if *ifp) { @@ -3764,7 +3771,12 @@ 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; +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) return s_link; } @@ -4106,17 +4118,26 @@ static size_t pppoe_tx_frame(struct mg_tcpip_if *ifp, uint8_t code, uint16_t id, extern struct mg_l2addr *mg_l2_eth_mapip(enum mg_l2addrtype, struct mg_addr *); 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) { +>>>>>>> 668f10fc (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; +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) } return mg_l2_ppp_poll(ifp, expired_1000ms); } @@ -4134,8 +4155,12 @@ 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) { +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) uint16_t tags[2]; bool has_cookie = false; size_t len = pay->len - sizeof(*pppoe); @@ -4164,6 +4189,7 @@ bool mg_l2_pppoe_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, pppoe_tx_frame(ifp, MG_PPPoE_PADR, 0, p, taglen, mg_l2_eth_getaddr((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; @@ -4171,14 +4197,29 @@ bool mg_l2_pppoe_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, 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 && +>>>>>>> 668f10fc (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) { +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) pay->buf = (char *) (pppoe + 1); pay->len = pay->len - sizeof(*pppoe); return ppp_rx(ifp, proto, pay, raw); @@ -7193,7 +7234,11 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { pkt.raw.len = len; pkt.l2 = (uint8_t *) pkt.raw.buf; if (!mg_l2_rx(ifp, &proto, &pkt.pay, &pkt.raw)) return; +<<<<<<< HEAD if (ifp->state < MG_TCPIP_STATE_UP) return; // discard while L2 is not up +======= + if (ifp->state == MG_TCPIP_STATE_DOWN) return; // discard while L2 is not up +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) if (proto == MG_TCPIP_L2PROTO_ARP) { pkt.arp = (struct arp *) (pkt.pay.buf); if (pkt.pay.len < sizeof(*pkt.arp)) return; // Truncated @@ -7319,9 +7364,17 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) { drv_up = ifp->driver->poll ? ifp->driver->poll(ifp, expired_1000ms) : true; l2_up = mg_l2_poll(ifp, expired_1000ms); // Handle L2 up/down link status; if (expired_1000ms) { // ifp->state rules over state6 +<<<<<<< HEAD mg_ip_link(ifp, drv_up, l2_up); // Handle IPv4 mg_ip6_link(ifp, drv_up, l2_up); // Handle IPv6 if (ifp->state < MG_TCPIP_STATE_UP) MG_ERROR(("Network is down")); +======= + bool up = drv_up & l2_up; + ifp->driver_up = drv_up; // update physical link state + mg_ip_link(ifp, up); // Handle IPv4 + mg_ip6_link(ifp, up); // Handle IPv6 + if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down")); +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL); } } @@ -7345,7 +7398,11 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) { mg_queue_del(&ifp->recv_queue, len); } } +<<<<<<< HEAD if (ifp->state < MG_TCPIP_STATE_UP) return; // need to let L2 do its job +======= + if (ifp->state == MG_TCPIP_STATE_DOWN) return; // need to let L2 do its job +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) // Process timeouts for (c = ifp->mgr->conns; c != NULL; c = c->next) { diff --git a/mongoose.h b/mongoose.h index 09f07d48..880a19e6 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3346,6 +3346,7 @@ struct mg_tcpip_if { #define MG_TCPIP_STATE_IP 4 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_READY 5 // Interface has fully come up, ready to work bool gw_ready; // We've got a hw address for the router + bool driver_up; // Driver reports link state is up #if MG_ENABLE_IPV6 uint8_t gw6mac[sizeof(struct mg_l2addr)]; // IPV6 Router's hw address uint8_t state6; // Current IPv6 state diff --git a/src/l2_ppp.c b/src/l2_ppp.c index 0f744c94..bb290776 100644 --- a/src/l2_ppp.c +++ b/src/l2_ppp.c @@ -82,6 +82,7 @@ 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 @@ -90,6 +91,12 @@ struct pppoe { // RFC-2516, "A Method for Transmitting PPP Over Ethernet static bool s_link = false; // ******************************************* 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; +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) static uint16_t s_id; void mg_l2_ppp_init(struct mg_tcpip_if *ifp) { @@ -106,7 +113,12 @@ 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; +>>>>>>> 668f10fc (Add L2 PPP and PPPoE) return s_link; } diff --git a/src/net_builtin.h b/src/net_builtin.h index 00f8770d..0949d4d6 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -88,6 +88,7 @@ struct mg_tcpip_if { #define MG_TCPIP_STATE_IP 4 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_READY 5 // Interface has fully come up, ready to work bool gw_ready; // We've got a hw address for the router + bool driver_up; // Driver reports link state is up #if MG_ENABLE_IPV6 uint8_t gw6mac[sizeof(struct mg_l2addr)]; // IPV6 Router's hw address uint8_t state6; // Current IPv6 state