mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-14 10:20:01 +00:00
Merge pull request #3479 from cesanta/vlans
Add support for 802.1Q VLANs
This commit is contained in:
9 files changed
+377
-277
No files matched your search
+170
-122
@@ -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;
|
||||
}
|
||||
@@ -3752,7 +3790,8 @@ struct pppoe { // RFC-2516, "A Method for Transmitting PPP Over Ethernet
|
||||
|
||||
#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;
|
||||
static uint16_t s_id;
|
||||
|
||||
@@ -3794,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
|
||||
@@ -3837,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_);
|
||||
@@ -3846,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);
|
||||
@@ -3867,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
|
||||
@@ -3883,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,
|
||||
@@ -4013,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"));
|
||||
@@ -4044,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 {
|
||||
@@ -4105,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;
|
||||
}
|
||||
@@ -4129,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
|
||||
}
|
||||
@@ -4160,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;
|
||||
@@ -4173,10 +4224,10 @@ 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) {
|
||||
@@ -4197,7 +4248,7 @@ bool mg_l2_pppoe_poll(struct mg_tcpip_if *ifp, bool 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) {
|
||||
@@ -4236,12 +4287,13 @@ 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"));
|
||||
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 &&
|
||||
@@ -5677,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
|
||||
@@ -5853,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,
|
||||
@@ -5861,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) {
|
||||
@@ -5890,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
|
||||
@@ -5947,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);
|
||||
}
|
||||
|
||||
@@ -6065,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));
|
||||
@@ -6076,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));
|
||||
@@ -6124,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6178,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
|
||||
@@ -6232,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));
|
||||
@@ -6248,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);
|
||||
@@ -6276,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
|
||||
@@ -6581,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"));
|
||||
@@ -6691,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,
|
||||
|
||||
+18
-16
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
+45
-14
@@ -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;
|
||||
}
|
||||
|
||||
+57
-43
@@ -94,7 +94,8 @@ struct pppoe { // RFC-2516, "A Method for Transmitting PPP Over Ethernet
|
||||
|
||||
#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;
|
||||
static uint16_t s_id;
|
||||
|
||||
@@ -136,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
|
||||
@@ -179,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_);
|
||||
@@ -188,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);
|
||||
@@ -209,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
|
||||
@@ -225,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,
|
||||
@@ -355,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"));
|
||||
@@ -386,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 {
|
||||
@@ -447,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;
|
||||
}
|
||||
@@ -471,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
|
||||
}
|
||||
@@ -502,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;
|
||||
@@ -515,10 +528,10 @@ 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) {
|
||||
@@ -539,7 +552,7 @@ bool mg_l2_pppoe_poll(struct mg_tcpip_if *ifp, bool 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) {
|
||||
@@ -578,12 +591,13 @@ 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"));
|
||||
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 &&
|
||||
|
||||
+27
-31
@@ -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,
|
||||
|
||||
+4
-3
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user