From caa84f048d5920f2f7b8294ba4b256c4e4a0641e Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Wed, 18 Mar 2026 14:06:27 -0300 Subject: [PATCH] Add support for 802.1Q VLANs --- mongoose.c | 349 ++++++++++++++-------------- mongoose.h | 104 +++++---- src/l2.c | 75 +++--- src/l2.h | 27 +-- src/l2_eth.c | 59 +++-- src/l2_ppp.c | 141 +++++------ src/net_builtin.c | 58 +++-- src/net_builtin.h | 7 +- tutorials/pico-sdk/pico-rmii/main.c | 2 +- 9 files changed, 412 insertions(+), 410 deletions(-) diff --git a/mongoose.c b/mongoose.c index cd7287b3..49bb1146 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3336,14 +3336,12 @@ long mg_json_get_long(struct mg_str json, const char *path, long dflt) { // L2 API void mg_l2_init(struct mg_tcpip_if *ifp); bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms); -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame); -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *cur); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur); bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -// TODO(): ? bool mg_l2_rx(enum mg_l2type type, struct mg_l2opts *opts, uint8_t -// *addr, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame); uint8_t *mg_l2_mapip(enum mg_l2type type, enum mg_l2addrtype addrtype, struct mg_addr *ip); #if MG_ENABLE_IPV6 @@ -3358,10 +3356,10 @@ size_t mg_l2_driver_output(struct mg_tcpip_if *ifp, size_t len); // clang-format off extern void mg_l2_eth_init(struct mg_tcpip_if *); extern bool mg_l2_eth_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_eth_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_eth_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_eth_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_eth_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_eth_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -extern struct mg_l2addr *mg_l2_eth_getaddr(uint8_t *); +extern struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *, uint8_t *); extern struct mg_l2addr *mg_l2_eth_mapip(enum mg_l2addrtype, struct mg_addr *); #if MG_ENABLE_IPV6 extern bool mg_l2_eth_genip6(uint64_t *, uint8_t, struct mg_l2addr *); @@ -3371,10 +3369,10 @@ extern uint8_t mg_l2_eth_ip6put(struct mg_l2addr *, uint8_t *); extern void mg_l2_ppp_init(struct mg_tcpip_if *); extern bool mg_l2_ppp_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_ppp_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_ppp_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_ppp_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_ppp_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_ppp_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -extern struct mg_l2addr *mg_l2_ppp_getaddr(uint8_t *); +extern struct mg_l2addr *mg_l2_ppp_getaddr(struct mg_tcpip_if *, uint8_t *); extern struct mg_l2addr *mg_l2_ppp_mapip(enum mg_l2addrtype, struct mg_addr *); #if MG_ENABLE_IPV6 extern bool mg_l2_ppp_genip6(uint64_t *, uint8_t, struct mg_l2addr *); @@ -3383,16 +3381,16 @@ extern uint8_t mg_l2_ppp_ip6put(struct mg_l2addr *, uint8_t *); #endif extern void mg_l2_pppoe_init(struct mg_tcpip_if *); extern bool mg_l2_pppoe_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_pppoe_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_pppoe_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_pppoe_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_pppoe_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_pppoe_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); typedef void (*l2_init_fn)(struct mg_tcpip_if *); typedef bool (*l2_poll_fn)(struct mg_tcpip_if *, bool); -typedef uint8_t *((*l2_header_fn)(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *)); -typedef size_t (*l2_footer_fn)(size_t, uint8_t *); +typedef uint8_t *((*l2_header_fn)(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *)); +typedef size_t (*l2_trailer_fn)(struct mg_tcpip_if *, size_t, uint8_t *); typedef bool (*l2_rx_fn)(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -typedef struct mg_l2addr (*(*l2_getaddr_fn)(uint8_t *)); +typedef struct mg_l2addr (*(*l2_getaddr_fn)(struct mg_tcpip_if *, uint8_t *)); typedef struct mg_l2addr (*(*l2_mapip_fn)(enum mg_l2addrtype, struct mg_addr *)); #if MG_ENABLE_IPV6 typedef bool (*l2_genip6_fn)(uint64_t *, uint8_t, struct mg_l2addr *); @@ -3401,17 +3399,26 @@ typedef uint8_t (*l2_ip6put_fn)(struct mg_l2addr *, uint8_t *); #endif // clang-format on -static const l2_init_fn l2_init[] = {mg_l2_eth_init, mg_l2_ppp_init, mg_l2_pppoe_init}; -static const l2_poll_fn l2_poll[] = {mg_l2_eth_poll, mg_l2_ppp_poll, mg_l2_pppoe_poll}; -static const l2_header_fn l2_header[] = {mg_l2_eth_header, mg_l2_ppp_header, mg_l2_pppoe_header}; -static const l2_footer_fn l2_footer[] = {mg_l2_eth_footer, mg_l2_ppp_footer, mg_l2_pppoe_footer}; +static const l2_init_fn l2_init[] = {mg_l2_eth_init, mg_l2_ppp_init, + mg_l2_pppoe_init}; +static const l2_poll_fn l2_poll[] = {mg_l2_eth_poll, mg_l2_ppp_poll, + mg_l2_pppoe_poll}; +static const l2_header_fn l2_header[] = {mg_l2_eth_header, mg_l2_ppp_header, + mg_l2_pppoe_header}; +static const l2_trailer_fn l2_trailer[] = {mg_l2_eth_trailer, mg_l2_ppp_trailer, + mg_l2_pppoe_trailer}; static const l2_rx_fn l2_rx[] = {mg_l2_eth_rx, mg_l2_ppp_rx, mg_l2_pppoe_rx}; -static const l2_getaddr_fn l2_getaddr[] = {mg_l2_eth_getaddr, mg_l2_ppp_getaddr, mg_l2_ppp_getaddr}; -static const l2_mapip_fn l2_mapip[] = {mg_l2_eth_mapip, mg_l2_ppp_mapip, mg_l2_ppp_mapip}; +static const l2_getaddr_fn l2_getaddr[] = {mg_l2_eth_getaddr, mg_l2_ppp_getaddr, + mg_l2_ppp_getaddr}; +static const l2_mapip_fn l2_mapip[] = {mg_l2_eth_mapip, mg_l2_ppp_mapip, + mg_l2_ppp_mapip}; #if MG_ENABLE_IPV6 -static const l2_genip6_fn l2_genip6[] = {mg_l2_eth_genip6, mg_l2_ppp_genip6, mg_l2_ppp_genip6}; -static const l2_ip6get_fn l2_ip6get[] = {mg_l2_eth_ip6get, mg_l2_ppp_ip6get, mg_l2_ppp_ip6get}; -static const l2_ip6put_fn l2_ip6put[] = {mg_l2_eth_ip6put, mg_l2_ppp_ip6put, mg_l2_ppp_ip6put}; +static const l2_genip6_fn l2_genip6[] = {mg_l2_eth_genip6, mg_l2_ppp_genip6, + mg_l2_ppp_genip6}; +static const l2_ip6get_fn l2_ip6get[] = {mg_l2_eth_ip6get, mg_l2_ppp_ip6get, + mg_l2_ppp_ip6get}; +static const l2_ip6put_fn l2_ip6put[] = {mg_l2_eth_ip6put, mg_l2_ppp_ip6put, + mg_l2_ppp_ip6put}; #endif void mg_l2_init(struct mg_tcpip_if *ifp) { @@ -3422,14 +3429,14 @@ bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) { return l2_poll[ifp->l2type](ifp, expired_1000ms); } -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame) { - return l2_header[type](proto, (struct mg_l2addr *) src, - (struct mg_l2addr *) dst, frame); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame) { + return l2_header[ifp->l2type](ifp, proto, (struct mg_l2addr *) src, + (struct mg_l2addr *) dst, frame); } -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *frame) { - return l2_footer[type](len, frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *frame) { + return l2_trailer[ifp->l2type](ifp, len, frame); } bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, @@ -3437,8 +3444,8 @@ bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, return l2_rx[ifp->l2type](ifp, proto, pay, raw); } -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame) { - return (uint8_t *) l2_getaddr[type](frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) { + return (uint8_t *) l2_getaddr[ifp->l2type](ifp, frame); } struct mg_l2addr s_mapip; @@ -3495,6 +3502,12 @@ struct eth { uint16_t type; // Ethernet type }; +struct qtag { + uint16_t tpid; // Ethernet 802.1Q type + uint16_t tci; // PCP, DEI, VLAN id +#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF)) +}; + #if defined(__DCC__) #pragma pack(0) #else @@ -3511,7 +3524,7 @@ static const uint16_t eth_types[] = { }; void mg_l2_eth_init(struct mg_tcpip_if *ifp) { - struct mg_l2addr *l2addr = (struct mg_l2addr *)ifp->mac; + struct mg_l2addr *l2addr = (struct mg_l2addr *) ifp->mac; // If MAC is not set, make a random one if (l2addr->addr.mac[0] == 0 && l2addr->addr.mac[1] == 0 && l2addr->addr.mac[2] == 0 && l2addr->addr.mac[3] == 0 && @@ -3531,18 +3544,32 @@ bool mg_l2_eth_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) { return true; } -uint8_t *mg_l2_eth_header(enum mg_l2proto proto, struct mg_l2addr *src, - struct mg_l2addr *dst, uint8_t *frame) { +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) { + struct eth_data *d = &ifp->l2data.eth; struct eth *eth = (struct eth *) frame; - eth->type = mg_htons(eth_types[(unsigned int) proto]); + uint8_t *hlp; + hlp = (uint8_t *) (eth + 1); memcpy(eth->src, src->addr.mac, sizeof(eth->dst)); memcpy(eth->dst, dst->addr.mac, sizeof(eth->dst)); - return (uint8_t *) (eth + 1); + if (d->vlan_id == 0) { // Traditional plain frame + eth->type = mg_htons(eth_types[(unsigned int) proto]); + } else { // Add 802.1Q tag + struct qtag *qtag = (struct qtag *) ð->type; + qtag->tpid = mg_htons(0x8100); + qtag->tci = mg_htons(d->vlan_id); // PCP = default (best-effort) + hlp += sizeof(*qtag); + *(uint16_t *) (qtag + 1) = mg_htons(eth_types[(unsigned int) proto]); + } + return hlp; } -size_t mg_l2_eth_footer(size_t len, uint8_t *cur) { +size_t mg_l2_eth_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) { + struct eth_data *d = &ifp->l2data.eth; // there is no len field in Ethernet, CRC is hw-calculated; pad to 64 - CRC - size_t ethlen = len + sizeof(struct eth); + size_t ethlen = + len + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0); (void) cur; return ethlen >= 60 ? ethlen : 60; } @@ -3553,26 +3580,36 @@ struct mg_l2addr *mg_l2_eth_mapip(enum mg_l2addrtype addrtype, bool mg_l2_eth_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw) { struct eth *eth = (struct eth *) raw->buf; + struct eth_data *d = &ifp->l2data.eth; uint16_t type, len; unsigned int i; - if (raw->len < sizeof(*eth)) return false; // Truncated - runt? + size_t hdrlen = + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0); + if (raw->len < hdrlen) return false; // Truncated - runt? len = (uint16_t) raw->len; + if (d->vlan_id == 0) { // We don't handle VLANs + type = mg_ntohs(eth->type); + } else { // We do, check 802.1Q tag + struct qtag *qtag = (struct qtag *) ð->type; + if (qtag->tpid != mg_htons(0x8100)) return false; // Untagged frame + if (mg_ntohs(VLAN_ID(qtag->tci)) != VLAN_ID(d->vlan_id)) + return false; // Not our VLAN + type = mg_ntohs(*(uint16_t *) (qtag + 1)); + } if (ifp->enable_mac_check && memcmp(eth->dst, ifp->mac, sizeof(eth->dst)) != 0 && memcmp(eth->dst, mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL), sizeof(eth->dst)) != 0) return false; // TODO(): add multicast addresses - if (ifp->enable_crc32_check && len > sizeof(*eth) + 4) { + if (ifp->enable_fcs_check && len > hdrlen + 4) { uint32_t crc; len -= 4; // TODO(scaprile): check on bigendian crc = mg_crc32(0, (const char *) raw->buf, len); if (memcmp((void *) ((size_t) raw->buf + len), &crc, sizeof(crc))) return false; } - pay->buf = (char *) (eth + 1); - pay->len = len - sizeof(*eth); - - type = mg_htons(eth->type); + pay->buf = ((char *) eth) + hdrlen; + pay->len = len - hdrlen; for (i = 0; i < sizeof(eth_types) / sizeof(uint16_t); i++) { if (type == eth_types[i]) break; } @@ -3586,7 +3623,8 @@ bool mg_l2_eth_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, return true; } -struct mg_l2addr *mg_l2_eth_getaddr(uint8_t *frame) { +struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) { + (void) ifp; // address field is before a possible 802.1Q tag struct eth *eth = (struct eth *) frame; return (struct mg_l2addr *) ð->src; } @@ -3746,21 +3784,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) { @@ -3777,12 +3809,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; } @@ -3806,31 +3833,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 @@ -3849,7 +3881,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_); @@ -3858,19 +3890,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); @@ -3879,15 +3912,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 @@ -3895,7 +3928,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, @@ -4025,15 +4058,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")); @@ -4056,9 +4092,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 { @@ -4117,7 +4156,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; } @@ -4141,7 +4180,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 } @@ -4172,7 +4212,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; @@ -4185,40 +4224,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) { @@ -4229,12 +4259,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); @@ -4261,39 +4287,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); @@ -5718,12 +5729,12 @@ struct pkt { // L2 API void mg_l2_init(struct mg_tcpip_if *ifp); -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame); -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *cur); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur); bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame); uint8_t *mg_l2_mapip(enum mg_l2type type, enum mg_l2addrtype addrtype, struct mg_addr *ip); #if MG_ENABLE_IPV6 @@ -5894,7 +5905,7 @@ static size_t driver_output(struct mg_tcpip_if *ifp, size_t len) { void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { uint8_t *l2p = (uint8_t *) ifp->tx.buf; struct arp *arp = (struct arp *) mg_l2_header( - ifp->l2type, MG_TCPIP_L2PROTO_ARP, ifp->mac, + ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_mapip(ifp->l2type, MG_TCPIP_L2ADDR_BCAST, NULL), l2p); memset(arp, 0, sizeof(*arp)); arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6, @@ -5902,8 +5913,7 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip; memcpy(arp->sha, ifp->mac, sizeof(arp->sha)); if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha)); - driver_output(ifp, - mg_l2_footer(ifp->l2type, sizeof(*arp), (uint8_t *) (arp + 1))); + driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1))); } static void onstatechange(struct mg_tcpip_if *ifp) { @@ -5931,7 +5941,7 @@ static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *l2_dst, uint8_t proto, uint32_t ip_src, uint32_t ip_dst, size_t plen) { // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct ip *ip = (struct ip *) mg_l2_header(ifp->l2type, MG_TCPIP_L2PROTO_IPV4, + struct ip *ip = (struct ip *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV4, ifp->mac, l2_dst, l2p); memset(ip, 0, sizeof(*ip)); ip->ver = 0x45; // Version 4, header length 5 words @@ -5988,7 +5998,7 @@ static bool tx_udp(struct mg_tcpip_if *ifp, uint8_t *l2_dst, { udp->csum = pcsum(ip, udp, sizeof(*udp) + len); } - l2_len = mg_l2_footer(ifp->l2type, l2_len, l3p + l2_len); + l2_len = mg_l2_trailer(ifp, l2_len, l3p + l2_len); return (driver_output(ifp, l2_len) == l2_len); } @@ -6106,9 +6116,8 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // ARP request. Make a response, then send // MG_VERBOSE(("ARP req from %M", mg_print_ip4, &pkt->arp->spa)); uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct arp *arp = - (struct arp *) mg_l2_header(ifp->l2type, MG_TCPIP_L2PROTO_ARP, ifp->mac, - mg_l2_getaddr(ifp->l2type, pkt->l2), l2p); + struct arp *arp = (struct arp *) mg_l2_header( + ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_getaddr(ifp, pkt->l2), l2p); *arp = *pkt->arp; arp->op = mg_htons(2); memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha)); @@ -6117,8 +6126,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { arp->spa = ifp->ip; MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac, ifp->mac)); - driver_output( - ifp, mg_l2_footer(ifp->l2type, sizeof(*arp), (uint8_t *) (arp + 1))); + driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1))); } else if (pkt->arp->op == mg_htons(2)) { if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; // MG_VERBOSE(("ARP resp from %M", mg_print_ip4, &pkt->arp->spa)); @@ -6165,8 +6173,8 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { memset(icmp, 0, sizeof(*icmp)); // Set csum, type, code to 0 memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen); - driver_output(ifp, mg_l2_footer(ifp->l2type, hlen + plen, - (uint8_t *) ip + hlen + plen)); + driver_output( + ifp, mg_l2_trailer(ifp, hlen + plen, (uint8_t *) ip + hlen + plen)); } } @@ -6219,8 +6227,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->lease_expire = ifp->now + lease * 1000; MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); // assume DHCP server = router until ARP resolves - memcpy(ifp->gwmac, mg_l2_getaddr(ifp->l2type, pkt->l2), - sizeof(ifp->gwmac)); + memcpy(ifp->gwmac, mg_l2_getaddr(ifp, pkt->l2), sizeof(ifp->gwmac)); ifp->gw_ready = true; // NOTE(): actual gw ARP won't retry now ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->state = MG_TCPIP_STATE_IP; // BOUND state @@ -6273,7 +6280,7 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) { memcpy(&res.options, opts, sizeof(opts)); res.magic = pkt->dhcp->magic; res.xid = pkt->dhcp->xid; - mac = mg_l2_getaddr(ifp->l2type, pkt->l2); + mac = mg_l2_getaddr(ifp, pkt->l2); if (ifp->enable_get_gateway) { ifp->gw = res.yiaddr; // set gw IP, best-effort gwmac as DHCP server's memcpy(ifp->gwmac, mac, sizeof(ifp->gwmac)); @@ -6289,8 +6296,8 @@ static struct ip6 *tx_ip6(struct mg_tcpip_if *ifp, uint8_t *l2_dst, size_t plen) { // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct ip6 *ip6 = (struct ip6 *) mg_l2_header( - ifp->l2type, MG_TCPIP_L2PROTO_IPV6, ifp->mac, l2_dst, l2p); + struct ip6 *ip6 = (struct ip6 *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV6, + ifp->mac, l2_dst, l2p); memset(ip6, 0, sizeof(*ip6)); ip6->ver = 0x60; // Version 6, traffic class 0 ip6->plen = mg_htons((uint16_t) plen); @@ -6317,8 +6324,8 @@ static void tx_icmp6(struct mg_tcpip_if *ifp, uint8_t *l2_dst, uint64_t *ip_src, icmp6->csum = 0; // RFC-4443 2.3, RFC-8200 8.1 icmp6->csum = p6csum(ip6, icmp6, sizeof(*icmp6) + len); driver_output(ifp, - mg_l2_footer(ifp->l2type, sizeof(*ip6) + sizeof(*icmp6) + len, - (uint8_t *) (ip6 + 1) + sizeof(*icmp6) + len)); + mg_l2_trailer(ifp, sizeof(*ip6) + sizeof(*icmp6) + len, + (uint8_t *) (ip6 + 1) + sizeof(*icmp6) + len)); } // Neighbor Discovery Protocol, RFC-4861 @@ -6622,16 +6629,16 @@ static uint8_t *get_return_l2addr(struct mg_tcpip_if *ifp, struct mg_addr *rem, if (rem->is_ip6) { if (rem->addr.ip6[0] == ifp->ip6ll[0] || match_prefix((uint8_t *) rem->addr.ip6, ifp->prefix, ifp->prefix_len)) - return mg_l2_getaddr(ifp->l2type, pkt->l2); // same LAN, get from frame - if (ifp->gw6_ready) // use the router - return ifp->gw6mac; // ignore source address in frame + return mg_l2_getaddr(ifp, pkt->l2); // same LAN, get from frame + if (ifp->gw6_ready) // use the router + return ifp->gw6mac; // ignore source address in frame } else #endif { if (ifp->ip != 0 && ((rem->addr.ip4 & ifp->mask) == (ifp->ip & ifp->mask))) - return mg_l2_getaddr(ifp->l2type, pkt->l2); // same LAN, get from frame - if (ifp->gw_ready) // use the router - return ifp->gwmac; // ignore source address in frame + return mg_l2_getaddr(ifp, pkt->l2); // same LAN, get from frame + if (ifp->gw_ready) // use the router + return ifp->gwmac; // ignore source address in frame } MG_ERROR(("%M %s: No way back, can't respond", mg_print_ip_port, rem, is_udp ? "UDP" : "TCP")); @@ -6732,8 +6739,8 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst, MG_VERBOSE(("TCP %M -> %M fl %x len %u", mg_print_ip_port, ip_src, mg_print_ip_port, ip_dst, tcp->flags, len)); return driver_output( - ifp, mg_l2_footer(ifp->l2type, PDIFF(l3p, (uint8_t *) tcp + hlen + len), - (uint8_t *) tcp + hlen + len)); + ifp, mg_l2_trailer(ifp, PDIFF(l3p, (uint8_t *) tcp + hlen + len), + (uint8_t *) tcp + hlen + len)); } static size_t tx_tcp_ctrlresp(struct mg_tcpip_if *ifp, struct pkt *pkt, @@ -7316,11 +7323,7 @@ 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 ->>>>>>> 3b7ca757 (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 @@ -7454,17 +7457,9 @@ 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")); ->>>>>>> 3b7ca757 (Add L2 PPP and PPPoE) mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL); } } @@ -7488,11 +7483,7 @@ 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 ->>>>>>> 3b7ca757 (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 070a23cd..98f8d2fd 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3210,7 +3210,7 @@ bool mg_wifi_ap_stop(void); #if MG_ENABLE_TCPIP // no config defaults to 0 => Ethernet -enum mg_l2type { MG_TCPIP_L2_ETH = 0, MG_TCPIP_L2_PPP, MG_TCPIP_L2_PPPoE}; +enum mg_l2type { MG_TCPIP_L2_ETH = 0, MG_TCPIP_L2_PPP, MG_TCPIP_L2_PPPoE }; #if defined(__DCC__) #pragma pack(1) @@ -3226,24 +3226,25 @@ struct mg_l2addr { } addr; }; +// L2 using L2 (PPPoE) must inherit the lower layer first, so they overlap +struct eth_data { + uint16_t vlan_id; +}; +struct pppoe_data { // (struct eth_data *) &pppoe_data = pppoedata.eth + struct eth_data eth; +}; + +union mg_l2data { + struct eth_data eth; + struct pppoe_data pppoe; +}; + #if defined(__DCC__) #pragma pack(0) #else #pragma pack(pop) #endif -#if 0 -TODO(): ? -struct eth_opts { - bool enable_crc32_check; // Do a CRC check on RX frames and strip it - bool enable_mac_check; // Do a MAC check on RX frames -}; -struct mg_l2opts { - union { - struct eth_opts eth; - }; -}; -#endif enum mg_l2proto { MG_TCPIP_L2PROTO_IPV4 = 0, @@ -3308,8 +3309,8 @@ struct mg_tcpip_if { bool enable_get_gateway; // DCHP server sets client as gateway bool enable_req_dns; // DCHP client requests DNS server bool enable_req_sntp; // DCHP client requests SNTP server - bool enable_crc32_check; // Do a CRC check on RX frames and strip it - bool enable_mac_check; // Do a MAC check on RX frames + bool enable_fcs_check; // Do a FCS check on RX frames and strip it + bool enable_mac_check; // Do a hw addr check on RX frames bool update_mac_hash_table; // Signal drivers to update MAC controller struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data @@ -3331,7 +3332,8 @@ struct mg_tcpip_if { // Internal state, user can use it but should not change it uint8_t gwmac[sizeof(struct mg_l2addr)]; // Router's hw address - enum mg_l2type l2type; // Ethernet, PPP, etc. + enum mg_l2type l2type; // Ethernet, PPP, etc. (l2.h) + union mg_l2data l2data; // config and state for L2 (l2.h) char *dns4_url; // DNS server URL uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state @@ -4034,41 +4036,6 @@ struct mg_tcpip_driver_tms570_data { -#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7 - -struct mg_tcpip_driver_xmc7_data { - int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 - uint8_t phy_addr; -}; - -#ifndef MG_TCPIP_PHY_ADDR -#define MG_TCPIP_PHY_ADDR 0 -#endif - -#ifndef MG_DRIVER_MDC_CR -#define MG_DRIVER_MDC_CR 3 -#endif - -#define MG_TCPIP_DRIVER_INIT(mgr) \ - do { \ - static struct mg_tcpip_driver_xmc7_data driver_data_; \ - static struct mg_tcpip_if mif_; \ - driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ - driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ - mif_.ip = MG_TCPIP_IP; \ - mif_.mask = MG_TCPIP_MASK; \ - mif_.gw = MG_TCPIP_GW; \ - mif_.driver = &mg_tcpip_driver_xmc7; \ - mif_.driver_data = &driver_data_; \ - MG_SET_MAC_ADDRESS(mif_.mac); \ - mg_tcpip_init(mgr, &mif_); \ - MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \ - } while (0) - -#endif - - - #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC struct mg_tcpip_driver_xmc_data { @@ -4115,6 +4082,41 @@ struct mg_tcpip_driver_xmc_data { #endif + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7 + +struct mg_tcpip_driver_xmc7_data { + int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 + uint8_t phy_addr; +}; + +#ifndef MG_TCPIP_PHY_ADDR +#define MG_TCPIP_PHY_ADDR 0 +#endif + +#ifndef MG_DRIVER_MDC_CR +#define MG_DRIVER_MDC_CR 3 +#endif + +#define MG_TCPIP_DRIVER_INIT(mgr) \ + do { \ + static struct mg_tcpip_driver_xmc7_data driver_data_; \ + static struct mg_tcpip_if mif_; \ + driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ + driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ + mif_.ip = MG_TCPIP_IP; \ + mif_.mask = MG_TCPIP_MASK; \ + mif_.gw = MG_TCPIP_GW; \ + mif_.driver = &mg_tcpip_driver_xmc7; \ + mif_.driver_data = &driver_data_; \ + MG_SET_MAC_ADDRESS(mif_.mac); \ + mg_tcpip_init(mgr, &mif_); \ + MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \ + } while (0) + +#endif + + #ifdef __cplusplus } #endif diff --git a/src/l2.c b/src/l2.c index 88adcfac..824a6ef0 100644 --- a/src/l2.c +++ b/src/l2.c @@ -7,14 +7,12 @@ // L2 API void mg_l2_init(struct mg_tcpip_if *ifp); bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms); -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame); -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *cur); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur); bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -// TODO(): ? bool mg_l2_rx(enum mg_l2type type, struct mg_l2opts *opts, uint8_t -// *addr, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame); uint8_t *mg_l2_mapip(enum mg_l2type type, enum mg_l2addrtype addrtype, struct mg_addr *ip); #if MG_ENABLE_IPV6 @@ -29,10 +27,10 @@ size_t mg_l2_driver_output(struct mg_tcpip_if *ifp, size_t len); // clang-format off extern void mg_l2_eth_init(struct mg_tcpip_if *); extern bool mg_l2_eth_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_eth_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_eth_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_eth_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_eth_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_eth_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -extern struct mg_l2addr *mg_l2_eth_getaddr(uint8_t *); +extern struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *, uint8_t *); extern struct mg_l2addr *mg_l2_eth_mapip(enum mg_l2addrtype, struct mg_addr *); #if MG_ENABLE_IPV6 extern bool mg_l2_eth_genip6(uint64_t *, uint8_t, struct mg_l2addr *); @@ -42,10 +40,10 @@ extern uint8_t mg_l2_eth_ip6put(struct mg_l2addr *, uint8_t *); extern void mg_l2_ppp_init(struct mg_tcpip_if *); extern bool mg_l2_ppp_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_ppp_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_ppp_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_ppp_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_ppp_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_ppp_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -extern struct mg_l2addr *mg_l2_ppp_getaddr(uint8_t *); +extern struct mg_l2addr *mg_l2_ppp_getaddr(struct mg_tcpip_if *, uint8_t *); extern struct mg_l2addr *mg_l2_ppp_mapip(enum mg_l2addrtype, struct mg_addr *); #if MG_ENABLE_IPV6 extern bool mg_l2_ppp_genip6(uint64_t *, uint8_t, struct mg_l2addr *); @@ -54,16 +52,16 @@ extern uint8_t mg_l2_ppp_ip6put(struct mg_l2addr *, uint8_t *); #endif extern void mg_l2_pppoe_init(struct mg_tcpip_if *); extern bool mg_l2_pppoe_poll(struct mg_tcpip_if *, bool); -extern uint8_t *mg_l2_pppoe_header(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); -extern size_t mg_l2_pppoe_footer(size_t, uint8_t *); +extern uint8_t *mg_l2_pppoe_header(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *); +extern size_t mg_l2_pppoe_trailer(struct mg_tcpip_if *, size_t, uint8_t *); extern bool mg_l2_pppoe_rx(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); typedef void (*l2_init_fn)(struct mg_tcpip_if *); typedef bool (*l2_poll_fn)(struct mg_tcpip_if *, bool); -typedef uint8_t *((*l2_header_fn)(enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *)); -typedef size_t (*l2_footer_fn)(size_t, uint8_t *); +typedef uint8_t *((*l2_header_fn)(struct mg_tcpip_if *, enum mg_l2proto, struct mg_l2addr *, struct mg_l2addr *, uint8_t *)); +typedef size_t (*l2_trailer_fn)(struct mg_tcpip_if *, size_t, uint8_t *); typedef bool (*l2_rx_fn)(struct mg_tcpip_if *, enum mg_l2proto *, struct mg_str *, struct mg_str *); -typedef struct mg_l2addr (*(*l2_getaddr_fn)(uint8_t *)); +typedef struct mg_l2addr (*(*l2_getaddr_fn)(struct mg_tcpip_if *, uint8_t *)); typedef struct mg_l2addr (*(*l2_mapip_fn)(enum mg_l2addrtype, struct mg_addr *)); #if MG_ENABLE_IPV6 typedef bool (*l2_genip6_fn)(uint64_t *, uint8_t, struct mg_l2addr *); @@ -72,17 +70,26 @@ typedef uint8_t (*l2_ip6put_fn)(struct mg_l2addr *, uint8_t *); #endif // clang-format on -static const l2_init_fn l2_init[] = {mg_l2_eth_init, mg_l2_ppp_init, mg_l2_pppoe_init}; -static const l2_poll_fn l2_poll[] = {mg_l2_eth_poll, mg_l2_ppp_poll, mg_l2_pppoe_poll}; -static const l2_header_fn l2_header[] = {mg_l2_eth_header, mg_l2_ppp_header, mg_l2_pppoe_header}; -static const l2_footer_fn l2_footer[] = {mg_l2_eth_footer, mg_l2_ppp_footer, mg_l2_pppoe_footer}; +static const l2_init_fn l2_init[] = {mg_l2_eth_init, mg_l2_ppp_init, + mg_l2_pppoe_init}; +static const l2_poll_fn l2_poll[] = {mg_l2_eth_poll, mg_l2_ppp_poll, + mg_l2_pppoe_poll}; +static const l2_header_fn l2_header[] = {mg_l2_eth_header, mg_l2_ppp_header, + mg_l2_pppoe_header}; +static const l2_trailer_fn l2_trailer[] = {mg_l2_eth_trailer, mg_l2_ppp_trailer, + mg_l2_pppoe_trailer}; static const l2_rx_fn l2_rx[] = {mg_l2_eth_rx, mg_l2_ppp_rx, mg_l2_pppoe_rx}; -static const l2_getaddr_fn l2_getaddr[] = {mg_l2_eth_getaddr, mg_l2_ppp_getaddr, mg_l2_ppp_getaddr}; -static const l2_mapip_fn l2_mapip[] = {mg_l2_eth_mapip, mg_l2_ppp_mapip, mg_l2_ppp_mapip}; +static const l2_getaddr_fn l2_getaddr[] = {mg_l2_eth_getaddr, mg_l2_ppp_getaddr, + mg_l2_ppp_getaddr}; +static const l2_mapip_fn l2_mapip[] = {mg_l2_eth_mapip, mg_l2_ppp_mapip, + mg_l2_ppp_mapip}; #if MG_ENABLE_IPV6 -static const l2_genip6_fn l2_genip6[] = {mg_l2_eth_genip6, mg_l2_ppp_genip6, mg_l2_ppp_genip6}; -static const l2_ip6get_fn l2_ip6get[] = {mg_l2_eth_ip6get, mg_l2_ppp_ip6get, mg_l2_ppp_ip6get}; -static const l2_ip6put_fn l2_ip6put[] = {mg_l2_eth_ip6put, mg_l2_ppp_ip6put, mg_l2_ppp_ip6put}; +static const l2_genip6_fn l2_genip6[] = {mg_l2_eth_genip6, mg_l2_ppp_genip6, + mg_l2_ppp_genip6}; +static const l2_ip6get_fn l2_ip6get[] = {mg_l2_eth_ip6get, mg_l2_ppp_ip6get, + mg_l2_ppp_ip6get}; +static const l2_ip6put_fn l2_ip6put[] = {mg_l2_eth_ip6put, mg_l2_ppp_ip6put, + mg_l2_ppp_ip6put}; #endif void mg_l2_init(struct mg_tcpip_if *ifp) { @@ -93,14 +100,14 @@ bool mg_l2_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) { return l2_poll[ifp->l2type](ifp, expired_1000ms); } -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame) { - return l2_header[type](proto, (struct mg_l2addr *) src, - (struct mg_l2addr *) dst, frame); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame) { + return l2_header[ifp->l2type](ifp, proto, (struct mg_l2addr *) src, + (struct mg_l2addr *) dst, frame); } -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *frame) { - return l2_footer[type](len, frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *frame) { + return l2_trailer[ifp->l2type](ifp, len, frame); } bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, @@ -108,8 +115,8 @@ bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, return l2_rx[ifp->l2type](ifp, proto, pay, raw); } -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame) { - return (uint8_t *) l2_getaddr[type](frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) { + return (uint8_t *) l2_getaddr[ifp->l2type](ifp, frame); } struct mg_l2addr s_mapip; diff --git a/src/l2.h b/src/l2.h index a9194754..7a80f736 100644 --- a/src/l2.h +++ b/src/l2.h @@ -6,7 +6,7 @@ #if MG_ENABLE_TCPIP // no config defaults to 0 => Ethernet -enum mg_l2type { MG_TCPIP_L2_ETH = 0, MG_TCPIP_L2_PPP, MG_TCPIP_L2_PPPoE}; +enum mg_l2type { MG_TCPIP_L2_ETH = 0, MG_TCPIP_L2_PPP, MG_TCPIP_L2_PPPoE }; #if defined(__DCC__) #pragma pack(1) @@ -22,24 +22,25 @@ struct mg_l2addr { } addr; }; +// L2 using L2 (PPPoE) must inherit the lower layer first, so they overlap +struct eth_data { + uint16_t vlan_id; +}; +struct pppoe_data { // (struct eth_data *) &pppoe_data = pppoedata.eth + struct eth_data eth; +}; + +union mg_l2data { + struct eth_data eth; + struct pppoe_data pppoe; +}; + #if defined(__DCC__) #pragma pack(0) #else #pragma pack(pop) #endif -#if 0 -TODO(): ? -struct eth_opts { - bool enable_crc32_check; // Do a CRC check on RX frames and strip it - bool enable_mac_check; // Do a MAC check on RX frames -}; -struct mg_l2opts { - union { - struct eth_opts eth; - }; -}; -#endif enum mg_l2proto { MG_TCPIP_L2PROTO_IPV4 = 0, diff --git a/src/l2_eth.c b/src/l2_eth.c index 1f3a29c2..288155bc 100644 --- a/src/l2_eth.c +++ b/src/l2_eth.c @@ -19,6 +19,12 @@ struct eth { uint16_t type; // Ethernet type }; +struct qtag { + uint16_t tpid; // Ethernet 802.1Q type + uint16_t tci; // PCP, DEI, VLAN id +#define VLAN_ID(x) ((uint16_t) ((x) &0x0FFF)) +}; + #if defined(__DCC__) #pragma pack(0) #else @@ -35,7 +41,7 @@ static const uint16_t eth_types[] = { }; void mg_l2_eth_init(struct mg_tcpip_if *ifp) { - struct mg_l2addr *l2addr = (struct mg_l2addr *)ifp->mac; + struct mg_l2addr *l2addr = (struct mg_l2addr *) ifp->mac; // If MAC is not set, make a random one if (l2addr->addr.mac[0] == 0 && l2addr->addr.mac[1] == 0 && l2addr->addr.mac[2] == 0 && l2addr->addr.mac[3] == 0 && @@ -55,18 +61,32 @@ bool mg_l2_eth_poll(struct mg_tcpip_if *ifp, bool expired_1000ms) { return true; } -uint8_t *mg_l2_eth_header(enum mg_l2proto proto, struct mg_l2addr *src, - struct mg_l2addr *dst, uint8_t *frame) { +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) { + struct eth_data *d = &ifp->l2data.eth; struct eth *eth = (struct eth *) frame; - eth->type = mg_htons(eth_types[(unsigned int) proto]); + uint8_t *hlp; + hlp = (uint8_t *) (eth + 1); memcpy(eth->src, src->addr.mac, sizeof(eth->dst)); memcpy(eth->dst, dst->addr.mac, sizeof(eth->dst)); - return (uint8_t *) (eth + 1); + if (d->vlan_id == 0) { // Traditional plain frame + eth->type = mg_htons(eth_types[(unsigned int) proto]); + } else { // Add 802.1Q tag + struct qtag *qtag = (struct qtag *) ð->type; + qtag->tpid = mg_htons(0x8100); + qtag->tci = mg_htons(d->vlan_id); // PCP = default (best-effort) + hlp += sizeof(*qtag); + *(uint16_t *) (qtag + 1) = mg_htons(eth_types[(unsigned int) proto]); + } + return hlp; } -size_t mg_l2_eth_footer(size_t len, uint8_t *cur) { +size_t mg_l2_eth_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) { + struct eth_data *d = &ifp->l2data.eth; // there is no len field in Ethernet, CRC is hw-calculated; pad to 64 - CRC - size_t ethlen = len + sizeof(struct eth); + size_t ethlen = + len + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0); (void) cur; return ethlen >= 60 ? ethlen : 60; } @@ -77,26 +97,36 @@ struct mg_l2addr *mg_l2_eth_mapip(enum mg_l2addrtype addrtype, bool mg_l2_eth_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw) { struct eth *eth = (struct eth *) raw->buf; + struct eth_data *d = &ifp->l2data.eth; uint16_t type, len; unsigned int i; - if (raw->len < sizeof(*eth)) return false; // Truncated - runt? + size_t hdrlen = + sizeof(struct eth) + (d->vlan_id != 0 ? sizeof(struct qtag) : 0); + if (raw->len < hdrlen) return false; // Truncated - runt? len = (uint16_t) raw->len; + if (d->vlan_id == 0) { // We don't handle VLANs + type = mg_ntohs(eth->type); + } else { // We do, check 802.1Q tag + struct qtag *qtag = (struct qtag *) ð->type; + if (qtag->tpid != mg_htons(0x8100)) return false; // Untagged frame + if (mg_ntohs(VLAN_ID(qtag->tci)) != VLAN_ID(d->vlan_id)) + return false; // Not our VLAN + type = mg_ntohs(*(uint16_t *) (qtag + 1)); + } if (ifp->enable_mac_check && memcmp(eth->dst, ifp->mac, sizeof(eth->dst)) != 0 && memcmp(eth->dst, mg_l2_eth_mapip(MG_TCPIP_L2ADDR_BCAST, NULL), sizeof(eth->dst)) != 0) return false; // TODO(): add multicast addresses - if (ifp->enable_crc32_check && len > sizeof(*eth) + 4) { + if (ifp->enable_fcs_check && len > hdrlen + 4) { uint32_t crc; len -= 4; // TODO(scaprile): check on bigendian crc = mg_crc32(0, (const char *) raw->buf, len); if (memcmp((void *) ((size_t) raw->buf + len), &crc, sizeof(crc))) return false; } - pay->buf = (char *) (eth + 1); - pay->len = len - sizeof(*eth); - - type = mg_htons(eth->type); + pay->buf = ((char *) eth) + hdrlen; + pay->len = len - hdrlen; for (i = 0; i < sizeof(eth_types) / sizeof(uint16_t); i++) { if (type == eth_types[i]) break; } @@ -110,7 +140,8 @@ bool mg_l2_eth_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, return true; } -struct mg_l2addr *mg_l2_eth_getaddr(uint8_t *frame) { +struct mg_l2addr *mg_l2_eth_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame) { + (void) ifp; // address field is before a possible 802.1Q tag struct eth *eth = (struct eth *) frame; return (struct mg_l2addr *) ð->src; } diff --git a/src/l2_ppp.c b/src/l2_ppp.c index 2f708177..fa1ccb24 100644 --- a/src/l2_ppp.c +++ b/src/l2_ppp.c @@ -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); diff --git a/src/net_builtin.c b/src/net_builtin.c index 7bacab06..ae81ba99 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -192,12 +192,12 @@ struct pkt { // L2 API void mg_l2_init(struct mg_tcpip_if *ifp); -uint8_t *mg_l2_header(enum mg_l2type type, enum mg_l2proto proto, uint8_t *src, - uint8_t *dst, uint8_t *frame); -size_t mg_l2_footer(enum mg_l2type type, size_t len, uint8_t *cur); +uint8_t *mg_l2_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto, + uint8_t *src, uint8_t *dst, uint8_t *frame); +size_t mg_l2_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur); bool mg_l2_rx(struct mg_tcpip_if *ifp, enum mg_l2proto *proto, struct mg_str *pay, struct mg_str *raw); -uint8_t *mg_l2_getaddr(enum mg_l2type type, uint8_t *frame); +uint8_t *mg_l2_getaddr(struct mg_tcpip_if *ifp, uint8_t *frame); uint8_t *mg_l2_mapip(enum mg_l2type type, enum mg_l2addrtype addrtype, struct mg_addr *ip); #if MG_ENABLE_IPV6 @@ -368,7 +368,7 @@ static size_t driver_output(struct mg_tcpip_if *ifp, size_t len) { void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { uint8_t *l2p = (uint8_t *) ifp->tx.buf; struct arp *arp = (struct arp *) mg_l2_header( - ifp->l2type, MG_TCPIP_L2PROTO_ARP, ifp->mac, + ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_mapip(ifp->l2type, MG_TCPIP_L2ADDR_BCAST, NULL), l2p); memset(arp, 0, sizeof(*arp)); arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6, @@ -376,8 +376,7 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip; memcpy(arp->sha, ifp->mac, sizeof(arp->sha)); if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha)); - driver_output(ifp, - mg_l2_footer(ifp->l2type, sizeof(*arp), (uint8_t *) (arp + 1))); + driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1))); } static void onstatechange(struct mg_tcpip_if *ifp) { @@ -405,7 +404,7 @@ static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *l2_dst, uint8_t proto, uint32_t ip_src, uint32_t ip_dst, size_t plen) { // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct ip *ip = (struct ip *) mg_l2_header(ifp->l2type, MG_TCPIP_L2PROTO_IPV4, + struct ip *ip = (struct ip *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV4, ifp->mac, l2_dst, l2p); memset(ip, 0, sizeof(*ip)); ip->ver = 0x45; // Version 4, header length 5 words @@ -462,7 +461,7 @@ static bool tx_udp(struct mg_tcpip_if *ifp, uint8_t *l2_dst, { udp->csum = pcsum(ip, udp, sizeof(*udp) + len); } - l2_len = mg_l2_footer(ifp->l2type, l2_len, l3p + l2_len); + l2_len = mg_l2_trailer(ifp, l2_len, l3p + l2_len); return (driver_output(ifp, l2_len) == l2_len); } @@ -580,9 +579,8 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // ARP request. Make a response, then send // MG_VERBOSE(("ARP req from %M", mg_print_ip4, &pkt->arp->spa)); uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct arp *arp = - (struct arp *) mg_l2_header(ifp->l2type, MG_TCPIP_L2PROTO_ARP, ifp->mac, - mg_l2_getaddr(ifp->l2type, pkt->l2), l2p); + struct arp *arp = (struct arp *) mg_l2_header( + ifp, MG_TCPIP_L2PROTO_ARP, ifp->mac, mg_l2_getaddr(ifp, pkt->l2), l2p); *arp = *pkt->arp; arp->op = mg_htons(2); memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha)); @@ -591,8 +589,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { arp->spa = ifp->ip; MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac, ifp->mac)); - driver_output( - ifp, mg_l2_footer(ifp->l2type, sizeof(*arp), (uint8_t *) (arp + 1))); + driver_output(ifp, mg_l2_trailer(ifp, sizeof(*arp), (uint8_t *) (arp + 1))); } else if (pkt->arp->op == mg_htons(2)) { if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; // MG_VERBOSE(("ARP resp from %M", mg_print_ip4, &pkt->arp->spa)); @@ -639,8 +636,8 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { memset(icmp, 0, sizeof(*icmp)); // Set csum, type, code to 0 memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen); - driver_output(ifp, mg_l2_footer(ifp->l2type, hlen + plen, - (uint8_t *) ip + hlen + plen)); + driver_output( + ifp, mg_l2_trailer(ifp, hlen + plen, (uint8_t *) ip + hlen + plen)); } } @@ -693,8 +690,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->lease_expire = ifp->now + lease * 1000; MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); // assume DHCP server = router until ARP resolves - memcpy(ifp->gwmac, mg_l2_getaddr(ifp->l2type, pkt->l2), - sizeof(ifp->gwmac)); + memcpy(ifp->gwmac, mg_l2_getaddr(ifp, pkt->l2), sizeof(ifp->gwmac)); ifp->gw_ready = true; // NOTE(): actual gw ARP won't retry now ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->state = MG_TCPIP_STATE_IP; // BOUND state @@ -747,7 +743,7 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) { memcpy(&res.options, opts, sizeof(opts)); res.magic = pkt->dhcp->magic; res.xid = pkt->dhcp->xid; - mac = mg_l2_getaddr(ifp->l2type, pkt->l2); + mac = mg_l2_getaddr(ifp, pkt->l2); if (ifp->enable_get_gateway) { ifp->gw = res.yiaddr; // set gw IP, best-effort gwmac as DHCP server's memcpy(ifp->gwmac, mac, sizeof(ifp->gwmac)); @@ -763,8 +759,8 @@ static struct ip6 *tx_ip6(struct mg_tcpip_if *ifp, uint8_t *l2_dst, size_t plen) { // ifp->tx.buf is 8-bit aligned, keep other headers as pointers, see pkt uint8_t *l2p = (uint8_t *) ifp->tx.buf; - struct ip6 *ip6 = (struct ip6 *) mg_l2_header( - ifp->l2type, MG_TCPIP_L2PROTO_IPV6, ifp->mac, l2_dst, l2p); + struct ip6 *ip6 = (struct ip6 *) mg_l2_header(ifp, MG_TCPIP_L2PROTO_IPV6, + ifp->mac, l2_dst, l2p); memset(ip6, 0, sizeof(*ip6)); ip6->ver = 0x60; // Version 6, traffic class 0 ip6->plen = mg_htons((uint16_t) plen); @@ -791,8 +787,8 @@ static void tx_icmp6(struct mg_tcpip_if *ifp, uint8_t *l2_dst, uint64_t *ip_src, icmp6->csum = 0; // RFC-4443 2.3, RFC-8200 8.1 icmp6->csum = p6csum(ip6, icmp6, sizeof(*icmp6) + len); driver_output(ifp, - mg_l2_footer(ifp->l2type, sizeof(*ip6) + sizeof(*icmp6) + len, - (uint8_t *) (ip6 + 1) + sizeof(*icmp6) + len)); + mg_l2_trailer(ifp, sizeof(*ip6) + sizeof(*icmp6) + len, + (uint8_t *) (ip6 + 1) + sizeof(*icmp6) + len)); } // Neighbor Discovery Protocol, RFC-4861 @@ -1096,16 +1092,16 @@ static uint8_t *get_return_l2addr(struct mg_tcpip_if *ifp, struct mg_addr *rem, if (rem->is_ip6) { if (rem->addr.ip6[0] == ifp->ip6ll[0] || match_prefix((uint8_t *) rem->addr.ip6, ifp->prefix, ifp->prefix_len)) - return mg_l2_getaddr(ifp->l2type, pkt->l2); // same LAN, get from frame - if (ifp->gw6_ready) // use the router - return ifp->gw6mac; // ignore source address in frame + return mg_l2_getaddr(ifp, pkt->l2); // same LAN, get from frame + if (ifp->gw6_ready) // use the router + return ifp->gw6mac; // ignore source address in frame } else #endif { if (ifp->ip != 0 && ((rem->addr.ip4 & ifp->mask) == (ifp->ip & ifp->mask))) - return mg_l2_getaddr(ifp->l2type, pkt->l2); // same LAN, get from frame - if (ifp->gw_ready) // use the router - return ifp->gwmac; // ignore source address in frame + return mg_l2_getaddr(ifp, pkt->l2); // same LAN, get from frame + if (ifp->gw_ready) // use the router + return ifp->gwmac; // ignore source address in frame } MG_ERROR(("%M %s: No way back, can't respond", mg_print_ip_port, rem, is_udp ? "UDP" : "TCP")); @@ -1206,8 +1202,8 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst, MG_VERBOSE(("TCP %M -> %M fl %x len %u", mg_print_ip_port, ip_src, mg_print_ip_port, ip_dst, tcp->flags, len)); return driver_output( - ifp, mg_l2_footer(ifp->l2type, PDIFF(l3p, (uint8_t *) tcp + hlen + len), - (uint8_t *) tcp + hlen + len)); + ifp, mg_l2_trailer(ifp, PDIFF(l3p, (uint8_t *) tcp + hlen + len), + (uint8_t *) tcp + hlen + len)); } static size_t tx_tcp_ctrlresp(struct mg_tcpip_if *ifp, struct pkt *pkt, diff --git a/src/net_builtin.h b/src/net_builtin.h index 49504816..da918e0e 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -47,8 +47,8 @@ struct mg_tcpip_if { bool enable_get_gateway; // DCHP server sets client as gateway bool enable_req_dns; // DCHP client requests DNS server bool enable_req_sntp; // DCHP client requests SNTP server - bool enable_crc32_check; // Do a CRC check on RX frames and strip it - bool enable_mac_check; // Do a MAC check on RX frames + bool enable_fcs_check; // Do a FCS check on RX frames and strip it + bool enable_mac_check; // Do a hw addr check on RX frames bool update_mac_hash_table; // Signal drivers to update MAC controller struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data @@ -70,7 +70,8 @@ struct mg_tcpip_if { // Internal state, user can use it but should not change it uint8_t gwmac[sizeof(struct mg_l2addr)]; // Router's hw address - enum mg_l2type l2type; // Ethernet, PPP, etc. + enum mg_l2type l2type; // Ethernet, PPP, etc. (l2.h) + union mg_l2data l2data; // config and state for L2 (l2.h) char *dns4_url; // DNS server URL uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state diff --git a/tutorials/pico-sdk/pico-rmii/main.c b/tutorials/pico-sdk/pico-rmii/main.c index f41eb814..9b9008f3 100644 --- a/tutorials/pico-sdk/pico-rmii/main.c +++ b/tutorials/pico-sdk/pico-rmii/main.c @@ -43,7 +43,7 @@ int main(void) { .mac = {2, 0, 1, 2, 3, 5}, .ip = 0, .enable_mac_check = true, - .enable_crc32_check = true, + .enable_fcs_check = true, .driver = &mg_tcpip_driver_rp2040_rmii, .driver_data = &driver_data, };