mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-06 15:51:25 +00:00
cleanup source and add some more IPV6 tests
This commit is contained in:
1 parent
27897d5514
commit
2b408e85e9
4 files changed
+138
-127
No files matched your search
@@ -74,7 +74,7 @@ jobs:
|
|||||||
- uses: webfactory/ssh-agent@v0.9.1
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
with:
|
with:
|
||||||
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0 > log
|
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; export IPV6=0; else export IPV6=1 ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} > log
|
||||||
- if: success() || failure()
|
- if: success() || failure()
|
||||||
run: |
|
run: |
|
||||||
cat log
|
cat log
|
||||||
@@ -92,7 +92,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: make -C test ${{ matrix.target }}
|
- run: make -C test ${{ matrix.target }} IPV6=1
|
||||||
s390:
|
s390:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
|
|||||||
+30
-33
@@ -4997,19 +4997,19 @@ struct dhcp6 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pseudoip {
|
struct pseudoip {
|
||||||
uint32_t src; // Source IP
|
uint32_t src; // Source IP
|
||||||
uint32_t dst; // Destination IP
|
uint32_t dst; // Destination IP
|
||||||
uint8_t zero;
|
uint8_t zero;
|
||||||
uint8_t proto; // Upper level protocol
|
uint8_t proto; // Upper level protocol
|
||||||
uint16_t len; // Datagram length
|
uint16_t len; // Datagram length
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pseudoip6 {
|
struct pseudoip6 {
|
||||||
uint64_t src[2]; // Source IP
|
uint64_t src[2]; // Source IP
|
||||||
uint64_t dst[2]; // Destination IP
|
uint64_t dst[2]; // Destination IP
|
||||||
uint32_t plen; // Payload length
|
uint32_t plen; // Payload length
|
||||||
uint8_t zero[3];
|
uint8_t zero[3];
|
||||||
uint8_t next; // Upper level protocol
|
uint8_t next; // Upper level protocol
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__DCC__)
|
#if defined(__DCC__)
|
||||||
@@ -5113,8 +5113,8 @@ static uint16_t pcsum(void *d, void *p, size_t plen) {
|
|||||||
pip.zero = 0;
|
pip.zero = 0;
|
||||||
pip.proto = ip->proto;
|
pip.proto = ip->proto;
|
||||||
pip.len = mg_htons((uint16_t) plen);
|
pip.len = mg_htons((uint16_t) plen);
|
||||||
sum = csumup(0, &pip, sizeof(pip)); // even length
|
sum = csumup(0, &pip, sizeof(pip)); // even length
|
||||||
sum = csumup(sum, p, plen); // possibly odd length: last
|
sum = csumup(sum, p, plen); // possibly odd length: last
|
||||||
return csumfin(sum);
|
return csumfin(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5127,7 +5127,8 @@ static bool udpcsum_ok(void *d, void *u) {
|
|||||||
|
|
||||||
static bool tcpcsum_ok(void *d, void *t) {
|
static bool tcpcsum_ok(void *d, void *t) {
|
||||||
struct ip *ip = (struct ip *) d;
|
struct ip *ip = (struct ip *) d;
|
||||||
return (pcsum(d, t, (size_t)(mg_ntohs(ip->len) - (ip->ver & 0x0F) * 4)) == 0);
|
return (pcsum(d, t, (size_t) (mg_ntohs(ip->len) - (ip->ver & 0x0F) * 4)) ==
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
@@ -5140,14 +5141,14 @@ static uint16_t p6csum(void *d, void *p, size_t plen) {
|
|||||||
pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0;
|
pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0;
|
||||||
pip6.plen = mg_htonl((uint32_t) plen);
|
pip6.plen = mg_htonl((uint32_t) plen);
|
||||||
pip6.next = ip6->next;
|
pip6.next = ip6->next;
|
||||||
sum = csumup(0, &pip6, sizeof(pip6)); // even length
|
sum = csumup(0, &pip6, sizeof(pip6)); // even length
|
||||||
sum = csumup(sum, p, plen); // possibly odd length: last
|
sum = csumup(sum, p, plen); // possibly odd length: last
|
||||||
return csumfin(sum);
|
return csumfin(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool udp6csum_ok(void *d, void *u) {
|
static bool udp6csum_ok(void *d, void *u) {
|
||||||
struct udp *udp = (struct udp *) u;
|
struct udp *udp = (struct udp *) u;
|
||||||
if (udp->csum == 0) return false; // mandatory in IPv6
|
if (udp->csum == 0) return false; // mandatory in IPv6
|
||||||
if (udp->csum == 0xFFFF) udp->csum = 0;
|
if (udp->csum == 0xFFFF) udp->csum = 0;
|
||||||
return (p6csum(d, u, (size_t) mg_ntohs(udp->len)) == 0);
|
return (p6csum(d, u, (size_t) mg_ntohs(udp->len)) == 0);
|
||||||
}
|
}
|
||||||
@@ -5175,15 +5176,9 @@ static void ip6sn(uint64_t *addr, uint64_t *sn_addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct mg_addr ip6_allrouters = {
|
static const struct mg_addr ip6_allrouters = {
|
||||||
.addr = {.ip = {0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}},
|
{{0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}}, 0, 0, true};
|
||||||
.port = 0,
|
|
||||||
.scope_id = 0,
|
|
||||||
.is_ip6 = true};
|
|
||||||
static const struct mg_addr ip6_allnodes = {
|
static const struct mg_addr ip6_allnodes = {
|
||||||
.addr = {.ip = {0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}},
|
{{0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}}, 0, 0, true};
|
||||||
.port = 0,
|
|
||||||
.scope_id = 0,
|
|
||||||
.is_ip6 = true};
|
|
||||||
|
|
||||||
#define MG_IP6MATCH(a, b) (a[0] == b[0] && a[1] == b[1])
|
#define MG_IP6MATCH(a, b) (a[0] == b[0] && a[1] == b[1])
|
||||||
#endif
|
#endif
|
||||||
@@ -5392,10 +5387,11 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport &&
|
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport &&
|
||||||
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL))) // IP or IPv6 to same dest
|
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL))) // IP or IPv6 to same dest
|
||||||
break;
|
break;
|
||||||
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
|
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
|
||||||
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL)) && lsn == (bool) c->is_listening &&
|
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL)) &&
|
||||||
|
lsn == (bool) c->is_listening &&
|
||||||
(lsn || c->rem.port == pkt->tcp->sport))
|
(lsn || c->rem.port == pkt->tcp->sport))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -5752,13 +5748,13 @@ static void fill_prefix(uint8_t *dst, uint8_t *src, uint8_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match_prefix(uint8_t *new, uint8_t *cur, uint8_t len) {
|
static bool match_prefix(uint8_t *newp, uint8_t *curp, uint8_t len) {
|
||||||
uint8_t full = len / 8;
|
uint8_t full = len / 8;
|
||||||
uint8_t rem = len % 8;
|
uint8_t rem = len % 8;
|
||||||
if (full > 0 && memcmp(cur, new, full) != 0) return false;
|
if (full > 0 && memcmp(curp, newp, full) != 0) return false;
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
|
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
|
||||||
if (cur[full] != (new[full] & mask)) return false;
|
if (curp[full] != (newp[full] & mask)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -5943,7 +5939,7 @@ static bool rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
s = (struct connstate *) (c + 1);
|
s = (struct connstate *) (c + 1);
|
||||||
c->rem.port = pkt->udp->sport;
|
c->rem.port = pkt->udp->sport;
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (c->loc.is_ip6) { // matching of v4/v6 to dest is done bt getpeer()
|
if (c->loc.is_ip6) { // matching of v4/v6 to dest is done bt getpeer()
|
||||||
if (!udp6csum_ok(pkt->ip6, pkt->udp)) return false;
|
if (!udp6csum_ok(pkt->ip6, pkt->udp)) return false;
|
||||||
c->rem.addr.ip6[0] = pkt->ip6->src[0],
|
c->rem.addr.ip6[0] = pkt->ip6->src[0],
|
||||||
c->rem.addr.ip6[1] = pkt->ip6->src[1], c->rem.is_ip6 = true;
|
c->rem.addr.ip6[1] = pkt->ip6->src[1], c->rem.is_ip6 = true;
|
||||||
@@ -5983,21 +5979,22 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Handle any options first, here, to determine header size
|
// Handle any options first, here, to determine header size
|
||||||
if (flags & TH_SYN) { // Send MSS
|
if (flags & TH_SYN) { // Send MSS
|
||||||
uint16_t mss;
|
uint16_t mss;
|
||||||
#if MG_ENABLE_IPV6 // RFC-9293 3.7.1; RFC-6691 2
|
#if MG_ENABLE_IPV6 // RFC-9293 3.7.1; RFC-6691 2
|
||||||
mss = (uint16_t) (ifp->mtu - 60);
|
mss = (uint16_t) (ifp->mtu - 60);
|
||||||
#else
|
#else
|
||||||
mss = (uint16_t) (ifp->mtu - 40);
|
mss = (uint16_t) (ifp->mtu - 40);
|
||||||
#endif
|
#endif
|
||||||
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
||||||
opts[1] = mg_htons(mss);
|
opts[1] = mg_htons(mss);
|
||||||
hlen += sizeof(opts); // always whole number of 32-bit words
|
hlen += sizeof(opts); // always whole number of 32-bit words
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ip_dst->is_ip6) {
|
if (ip_dst->is_ip6) {
|
||||||
ip6 = tx_ip6(ifp, l2_dst, 6, ip_src->addr.ip6, ip_dst->addr.ip6, hlen + len);
|
ip6 =
|
||||||
|
tx_ip6(ifp, l2_dst, 6, ip_src->addr.ip6, ip_dst->addr.ip6, hlen + len);
|
||||||
tcp = (struct tcp *) (ip6 + 1);
|
tcp = (struct tcp *) (ip6 + 1);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -6006,8 +6003,8 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
|||||||
tcp = (struct tcp *) (ip + 1);
|
tcp = (struct tcp *) (ip + 1);
|
||||||
}
|
}
|
||||||
memset(tcp, 0, sizeof(*tcp));
|
memset(tcp, 0, sizeof(*tcp));
|
||||||
memmove(tcp + 1, opts, hlen - sizeof(*tcp)); // copy opts if any
|
memmove(tcp + 1, opts, hlen - sizeof(*tcp)); // copy opts if any
|
||||||
if (buf != NULL && len) memmove((uint8_t *)tcp + hlen, buf, len);
|
if (buf != NULL && len) memmove((uint8_t *) tcp + hlen, buf, len);
|
||||||
tcp->sport = ip_src->port;
|
tcp->sport = ip_src->port;
|
||||||
tcp->dport = ip_dst->port;
|
tcp->dport = ip_dst->port;
|
||||||
tcp->seq = seq;
|
tcp->seq = seq;
|
||||||
@@ -6360,7 +6357,7 @@ static void handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) {
|
|||||||
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||||
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
|
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
|
||||||
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
|
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
|
||||||
#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done by getpeer()
|
#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done by getpeer()
|
||||||
if (pkt->ip6 != NULL && !tcp6csum_ok(pkt->ip6, pkt->tcp)) return;
|
if (pkt->ip6 != NULL && !tcp6csum_ok(pkt->ip6, pkt->tcp)) return;
|
||||||
#endif
|
#endif
|
||||||
if (pkt->ip != NULL && !tcpcsum_ok(pkt->ip, pkt->tcp)) return;
|
if (pkt->ip != NULL && !tcpcsum_ok(pkt->ip, pkt->tcp)) return;
|
||||||
|
|||||||
+30
-33
@@ -152,19 +152,19 @@ struct dhcp6 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pseudoip {
|
struct pseudoip {
|
||||||
uint32_t src; // Source IP
|
uint32_t src; // Source IP
|
||||||
uint32_t dst; // Destination IP
|
uint32_t dst; // Destination IP
|
||||||
uint8_t zero;
|
uint8_t zero;
|
||||||
uint8_t proto; // Upper level protocol
|
uint8_t proto; // Upper level protocol
|
||||||
uint16_t len; // Datagram length
|
uint16_t len; // Datagram length
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pseudoip6 {
|
struct pseudoip6 {
|
||||||
uint64_t src[2]; // Source IP
|
uint64_t src[2]; // Source IP
|
||||||
uint64_t dst[2]; // Destination IP
|
uint64_t dst[2]; // Destination IP
|
||||||
uint32_t plen; // Payload length
|
uint32_t plen; // Payload length
|
||||||
uint8_t zero[3];
|
uint8_t zero[3];
|
||||||
uint8_t next; // Upper level protocol
|
uint8_t next; // Upper level protocol
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__DCC__)
|
#if defined(__DCC__)
|
||||||
@@ -268,8 +268,8 @@ static uint16_t pcsum(void *d, void *p, size_t plen) {
|
|||||||
pip.zero = 0;
|
pip.zero = 0;
|
||||||
pip.proto = ip->proto;
|
pip.proto = ip->proto;
|
||||||
pip.len = mg_htons((uint16_t) plen);
|
pip.len = mg_htons((uint16_t) plen);
|
||||||
sum = csumup(0, &pip, sizeof(pip)); // even length
|
sum = csumup(0, &pip, sizeof(pip)); // even length
|
||||||
sum = csumup(sum, p, plen); // possibly odd length: last
|
sum = csumup(sum, p, plen); // possibly odd length: last
|
||||||
return csumfin(sum);
|
return csumfin(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,8 @@ static bool udpcsum_ok(void *d, void *u) {
|
|||||||
|
|
||||||
static bool tcpcsum_ok(void *d, void *t) {
|
static bool tcpcsum_ok(void *d, void *t) {
|
||||||
struct ip *ip = (struct ip *) d;
|
struct ip *ip = (struct ip *) d;
|
||||||
return (pcsum(d, t, (size_t)(mg_ntohs(ip->len) - (ip->ver & 0x0F) * 4)) == 0);
|
return (pcsum(d, t, (size_t) (mg_ntohs(ip->len) - (ip->ver & 0x0F) * 4)) ==
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
@@ -295,14 +296,14 @@ static uint16_t p6csum(void *d, void *p, size_t plen) {
|
|||||||
pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0;
|
pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0;
|
||||||
pip6.plen = mg_htonl((uint32_t) plen);
|
pip6.plen = mg_htonl((uint32_t) plen);
|
||||||
pip6.next = ip6->next;
|
pip6.next = ip6->next;
|
||||||
sum = csumup(0, &pip6, sizeof(pip6)); // even length
|
sum = csumup(0, &pip6, sizeof(pip6)); // even length
|
||||||
sum = csumup(sum, p, plen); // possibly odd length: last
|
sum = csumup(sum, p, plen); // possibly odd length: last
|
||||||
return csumfin(sum);
|
return csumfin(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool udp6csum_ok(void *d, void *u) {
|
static bool udp6csum_ok(void *d, void *u) {
|
||||||
struct udp *udp = (struct udp *) u;
|
struct udp *udp = (struct udp *) u;
|
||||||
if (udp->csum == 0) return false; // mandatory in IPv6
|
if (udp->csum == 0) return false; // mandatory in IPv6
|
||||||
if (udp->csum == 0xFFFF) udp->csum = 0;
|
if (udp->csum == 0xFFFF) udp->csum = 0;
|
||||||
return (p6csum(d, u, (size_t) mg_ntohs(udp->len)) == 0);
|
return (p6csum(d, u, (size_t) mg_ntohs(udp->len)) == 0);
|
||||||
}
|
}
|
||||||
@@ -330,15 +331,9 @@ static void ip6sn(uint64_t *addr, uint64_t *sn_addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct mg_addr ip6_allrouters = {
|
static const struct mg_addr ip6_allrouters = {
|
||||||
.addr = {.ip = {0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}},
|
{{0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02}}, 0, 0, true};
|
||||||
.port = 0,
|
|
||||||
.scope_id = 0,
|
|
||||||
.is_ip6 = true};
|
|
||||||
static const struct mg_addr ip6_allnodes = {
|
static const struct mg_addr ip6_allnodes = {
|
||||||
.addr = {.ip = {0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}},
|
{{0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}}, 0, 0, true};
|
||||||
.port = 0,
|
|
||||||
.scope_id = 0,
|
|
||||||
.is_ip6 = true};
|
|
||||||
|
|
||||||
#define MG_IP6MATCH(a, b) (a[0] == b[0] && a[1] == b[1])
|
#define MG_IP6MATCH(a, b) (a[0] == b[0] && a[1] == b[1])
|
||||||
#endif
|
#endif
|
||||||
@@ -547,10 +542,11 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport &&
|
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport &&
|
||||||
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL))) // IP or IPv6 to same dest
|
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL))) // IP or IPv6 to same dest
|
||||||
break;
|
break;
|
||||||
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
|
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
|
||||||
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL)) && lsn == (bool) c->is_listening &&
|
!(c->loc.is_ip6 ^ (pkt->ip6 != NULL)) &&
|
||||||
|
lsn == (bool) c->is_listening &&
|
||||||
(lsn || c->rem.port == pkt->tcp->sport))
|
(lsn || c->rem.port == pkt->tcp->sport))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -907,13 +903,13 @@ static void fill_prefix(uint8_t *dst, uint8_t *src, uint8_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match_prefix(uint8_t *new, uint8_t *cur, uint8_t len) {
|
static bool match_prefix(uint8_t *newp, uint8_t *curp, uint8_t len) {
|
||||||
uint8_t full = len / 8;
|
uint8_t full = len / 8;
|
||||||
uint8_t rem = len % 8;
|
uint8_t rem = len % 8;
|
||||||
if (full > 0 && memcmp(cur, new, full) != 0) return false;
|
if (full > 0 && memcmp(curp, newp, full) != 0) return false;
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
|
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
|
||||||
if (cur[full] != (new[full] & mask)) return false;
|
if (curp[full] != (newp[full] & mask)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1098,7 +1094,7 @@ static bool rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
|||||||
s = (struct connstate *) (c + 1);
|
s = (struct connstate *) (c + 1);
|
||||||
c->rem.port = pkt->udp->sport;
|
c->rem.port = pkt->udp->sport;
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (c->loc.is_ip6) { // matching of v4/v6 to dest is done bt getpeer()
|
if (c->loc.is_ip6) { // matching of v4/v6 to dest is done bt getpeer()
|
||||||
if (!udp6csum_ok(pkt->ip6, pkt->udp)) return false;
|
if (!udp6csum_ok(pkt->ip6, pkt->udp)) return false;
|
||||||
c->rem.addr.ip6[0] = pkt->ip6->src[0],
|
c->rem.addr.ip6[0] = pkt->ip6->src[0],
|
||||||
c->rem.addr.ip6[1] = pkt->ip6->src[1], c->rem.is_ip6 = true;
|
c->rem.addr.ip6[1] = pkt->ip6->src[1], c->rem.is_ip6 = true;
|
||||||
@@ -1138,21 +1134,22 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Handle any options first, here, to determine header size
|
// Handle any options first, here, to determine header size
|
||||||
if (flags & TH_SYN) { // Send MSS
|
if (flags & TH_SYN) { // Send MSS
|
||||||
uint16_t mss;
|
uint16_t mss;
|
||||||
#if MG_ENABLE_IPV6 // RFC-9293 3.7.1; RFC-6691 2
|
#if MG_ENABLE_IPV6 // RFC-9293 3.7.1; RFC-6691 2
|
||||||
mss = (uint16_t) (ifp->mtu - 60);
|
mss = (uint16_t) (ifp->mtu - 60);
|
||||||
#else
|
#else
|
||||||
mss = (uint16_t) (ifp->mtu - 40);
|
mss = (uint16_t) (ifp->mtu - 40);
|
||||||
#endif
|
#endif
|
||||||
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
||||||
opts[1] = mg_htons(mss);
|
opts[1] = mg_htons(mss);
|
||||||
hlen += sizeof(opts); // always whole number of 32-bit words
|
hlen += sizeof(opts); // always whole number of 32-bit words
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ip_dst->is_ip6) {
|
if (ip_dst->is_ip6) {
|
||||||
ip6 = tx_ip6(ifp, l2_dst, 6, ip_src->addr.ip6, ip_dst->addr.ip6, hlen + len);
|
ip6 =
|
||||||
|
tx_ip6(ifp, l2_dst, 6, ip_src->addr.ip6, ip_dst->addr.ip6, hlen + len);
|
||||||
tcp = (struct tcp *) (ip6 + 1);
|
tcp = (struct tcp *) (ip6 + 1);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -1161,8 +1158,8 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
|||||||
tcp = (struct tcp *) (ip + 1);
|
tcp = (struct tcp *) (ip + 1);
|
||||||
}
|
}
|
||||||
memset(tcp, 0, sizeof(*tcp));
|
memset(tcp, 0, sizeof(*tcp));
|
||||||
memmove(tcp + 1, opts, hlen - sizeof(*tcp)); // copy opts if any
|
memmove(tcp + 1, opts, hlen - sizeof(*tcp)); // copy opts if any
|
||||||
if (buf != NULL && len) memmove((uint8_t *)tcp + hlen, buf, len);
|
if (buf != NULL && len) memmove((uint8_t *) tcp + hlen, buf, len);
|
||||||
tcp->sport = ip_src->port;
|
tcp->sport = ip_src->port;
|
||||||
tcp->dport = ip_dst->port;
|
tcp->dport = ip_dst->port;
|
||||||
tcp->seq = seq;
|
tcp->seq = seq;
|
||||||
@@ -1515,7 +1512,7 @@ static void handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) {
|
|||||||
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||||
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
|
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
|
||||||
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
|
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
|
||||||
#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done by getpeer()
|
#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done by getpeer()
|
||||||
if (pkt->ip6 != NULL && !tcp6csum_ok(pkt->ip6, pkt->tcp)) return;
|
if (pkt->ip6 != NULL && !tcp6csum_ok(pkt->ip6, pkt->tcp)) return;
|
||||||
#endif
|
#endif
|
||||||
if (pkt->ip != NULL && !tcpcsum_ok(pkt->ip, pkt->tcp)) return;
|
if (pkt->ip != NULL && !tcpcsum_ok(pkt->ip, pkt->tcp)) return;
|
||||||
|
|||||||
+76
-59
@@ -41,19 +41,18 @@ struct ipp {
|
|||||||
static void test_csum(void) {
|
static void test_csum(void) {
|
||||||
uint8_t ip[20] = {0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x11,
|
uint8_t ip[20] = {0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x11,
|
||||||
0x94, 0xcf, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01};
|
0x94, 0xcf, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01};
|
||||||
uint8_t pseudo_udp_odd[53] = {0xc0, 0xa8, 0x45, 0x58, 0x08, 0x08, 0x08, 0x08, 0x00,
|
uint8_t pseudo_udp_odd[53] = {
|
||||||
0x11, 0x00, 0x29, 0xad, 0x67, 0x00, 0x35, 0x00, 0x29,
|
0xc0, 0xa8, 0x45, 0x58, 0x08, 0x08, 0x08, 0x08, 0x00, 0x11, 0x00,
|
||||||
0xaf, 0xf8, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00,
|
0x29, 0xad, 0x67, 0x00, 0x35, 0x00, 0x29, 0xaf, 0xf8, 0x00, 0x01,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x74, 0x69, 0x6d,
|
0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||||
0x65, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
|
0x74, 0x69, 0x6d, 0x65, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||||
0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01};
|
0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01};
|
||||||
|
|
||||||
ASSERT(ipcsum(ip, 20) == 0);
|
ASSERT(ipcsum(ip, 20) == 0);
|
||||||
ASSERT(ipcsum(pseudo_udp_odd, 53) == 0);
|
ASSERT(ipcsum(pseudo_udp_odd, 53) == 0);
|
||||||
// UDP and TCP checksum calc funcions use the same basic calls as ipcsum()
|
// UDP and TCP checksum calc funcions use the same basic calls as ipcsum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if !MG_ENABLE_IPV6
|
#if !MG_ENABLE_IPV6
|
||||||
#define udp6csum_ok(d, u) true
|
#define udp6csum_ok(d, u) true
|
||||||
#define tcp6csum_ok(d, t) true
|
#define tcp6csum_ok(d, t) true
|
||||||
@@ -220,7 +219,8 @@ static void create_tcp_seg(struct eth *e, struct ipp *ipp, uint32_t seq,
|
|||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ipp->ip6 != NULL) {
|
if (ipp->ip6 != NULL) {
|
||||||
struct ip6 *ip = ipp->ip6;
|
struct ip6 *ip = ipp->ip6;
|
||||||
struct tcp *tcp = (struct tcp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
struct tcp *tcp =
|
||||||
|
(struct tcp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
||||||
ip->plen = mg_htons((uint16_t) (4 * (t.off >> 4) + payload_len));
|
ip->plen = mg_htons((uint16_t) (4 * (t.off >> 4) + payload_len));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
memcpy(tcp, &t, sizeof(t));
|
memcpy(tcp, &t, sizeof(t));
|
||||||
@@ -234,10 +234,11 @@ static void create_tcp_seg(struct eth *e, struct ipp *ipp, uint32_t seq,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct ip *ip = ipp->ip4;
|
struct ip *ip = ipp->ip4;
|
||||||
struct tcp *tcp = (struct tcp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
struct tcp *tcp =
|
||||||
|
(struct tcp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
||||||
ip->len =
|
ip->len =
|
||||||
mg_htons((uint16_t) (sizeof(*ip) + 4 * (t.off >> 4) + payload_len));
|
mg_htons((uint16_t) (sizeof(*ip) + 4 * (t.off >> 4) + payload_len));
|
||||||
ip->csum = ipcsum(ip, sizeof(*ip)); // no options
|
ip->csum = ipcsum(ip, sizeof(*ip)); // no options
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
ip->csum = 0;
|
ip->csum = 0;
|
||||||
memcpy(tcp, &t, sizeof(t));
|
memcpy(tcp, &t, sizeof(t));
|
||||||
@@ -270,12 +271,12 @@ static void init_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
|||||||
mif->driver_data = &s_driver_data;
|
mif->driver_data = &s_driver_data;
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ipp->ip6 != NULL) {
|
if (ipp->ip6 != NULL) {
|
||||||
mif->ip6[0] = mg_htonll(0x1000000000000000);
|
mif->ip6[0] = mg_htonll(0x100000000000000);
|
||||||
mif->prefix[0] = 1;
|
mif->prefix[0] = 1;
|
||||||
mif->prefix_len = 64;
|
mif->prefix_len = 64;
|
||||||
mif->gw6[0] = mg_htonll(0x1000000000000000);
|
mif->gw6[0] = mg_htonll(0x100000000000000);
|
||||||
mif->gw6_ready = true;
|
mif->gw6_ready = true;
|
||||||
mif->state = MG_TCPIP_STATE_READY; // so DHCP stops
|
mif->state = MG_TCPIP_STATE_READY; // so DHCP stops
|
||||||
mif->state6 = MG_TCPIP_STATE_READY; // so mg_send() works and RS stops
|
mif->state6 = MG_TCPIP_STATE_READY; // so mg_send() works and RS stops
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -283,7 +284,7 @@ static void init_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
|||||||
mif->ip = mg_htonl(0x1000000);
|
mif->ip = mg_htonl(0x1000000);
|
||||||
mif->gw = mg_htonl(0x1000000);
|
mif->gw = mg_htonl(0x1000000);
|
||||||
mif->gw_ready = true;
|
mif->gw_ready = true;
|
||||||
mif->mask = 255; // use router, to avoid firing an ARP request
|
mif->mask = 255; // use router, to avoid firing an ARP request
|
||||||
mif->state = MG_TCPIP_STATE_READY; // so mg_send() works and DHCP stops
|
mif->state = MG_TCPIP_STATE_READY; // so mg_send() works and DHCP stops
|
||||||
}
|
}
|
||||||
mg_tcpip_init(mgr, mif);
|
mg_tcpip_init(mgr, mif);
|
||||||
@@ -301,7 +302,7 @@ static void init_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
|||||||
ip->ver = 0x60;
|
ip->ver = 0x60;
|
||||||
ip->next = proto;
|
ip->next = proto;
|
||||||
// must be outside of Mongoose network to avoid firing NS requests
|
// must be outside of Mongoose network to avoid firing NS requests
|
||||||
ip->src[0] = mg_htonll(0x2000000000000000);
|
ip->src[0] = mg_htonll(0x200000000000000);
|
||||||
ip->dst[0] = mif->ip6[0];
|
ip->dst[0] = mif->ip6[0];
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -364,7 +365,8 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct ip6 ip6;
|
struct ip6 ip6;
|
||||||
struct ipp ipp;
|
struct ipp ipp;
|
||||||
struct tcp *t = (struct tcp *) (s_driver_data.buf + sizeof(e) + (!ipv6 ? sizeof(ip) : sizeof(ip6)));
|
struct tcp *t = (struct tcp *) (s_driver_data.buf + sizeof(e) +
|
||||||
|
(!ipv6 ? sizeof(ip) : sizeof(ip6)));
|
||||||
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
||||||
struct ip6 *i6 = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
struct ip6 *i6 = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
||||||
uint64_t start, now;
|
uint64_t start, now;
|
||||||
@@ -385,7 +387,8 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
ASSERT(t->seq == mg_htonl(0));
|
ASSERT(t->seq == mg_htonl(0));
|
||||||
ASSERT(t->ack == mg_htonl(1235));
|
ASSERT(t->ack == mg_htonl(1235));
|
||||||
if (ipv6) {
|
if (ipv6) {
|
||||||
ASSERT(i6->src[0] == mg_htonll(0x1000000000000000) && i6->src[1] == 0 && i6->dst[0] == mg_htonll(0x2000000000000000) && i6->dst[1] == 0);
|
ASSERT(i6->src[0] == mg_htonll(0x100000000000000) && i6->src[1] == 0 &&
|
||||||
|
i6->dst[0] == mg_htonll(0x200000000000000) && i6->dst[1] == 0);
|
||||||
ASSERT(tcp6csum_ok(i6, t));
|
ASSERT(tcp6csum_ok(i6, t));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
@@ -441,7 +444,8 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
ASSERT(t->flags == TH_RST);
|
ASSERT(t->flags == TH_RST);
|
||||||
ASSERT(t->seq == mg_htonl(4321));
|
ASSERT(t->seq == mg_htonl(4321));
|
||||||
if (ipv6) {
|
if (ipv6) {
|
||||||
ASSERT(i6->src[0] == mg_htonll(0x1000000000000000) && i6->src[1] == 0 && i6->dst[0] == mg_htonll(0x2000000000000000) && i6->dst[1] == 0);
|
ASSERT(i6->src[0] == mg_htonll(0x100000000000000) && i6->src[1] == 0 &&
|
||||||
|
i6->dst[0] == mg_htonll(0x200000000000000) && i6->dst[1] == 0);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
}
|
}
|
||||||
@@ -479,7 +483,8 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
ASSERT((t->flags == TH_ACK));
|
ASSERT((t->flags == TH_ACK));
|
||||||
ASSERT((t->ack == mg_htonl(1001))); // expecting 1001, dude
|
ASSERT((t->ack == mg_htonl(1001))); // expecting 1001, dude
|
||||||
if (ipv6) {
|
if (ipv6) {
|
||||||
ASSERT(i6->src[0] == mg_htonll(0x1000000000000000) && i6->src[1] == 0 && i6->dst[0] == mg_htonll(0x2000000000000000) && i6->dst[1] == 0);
|
ASSERT(i6->src[0] == mg_htonll(0x100000000000000) && i6->src[1] == 0 &&
|
||||||
|
i6->dst[0] == mg_htonll(0x200000000000000) && i6->dst[1] == 0);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
}
|
}
|
||||||
@@ -623,8 +628,9 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
now = mg_millis() - start;
|
now = mg_millis() - start;
|
||||||
} while (now < 2 * MG_TCPIP_ACK_MS); // keep timeout below 1s (DHCP discover)
|
} while (now < 2 * MG_TCPIP_ACK_MS); // keep timeout below 1s (DHCP discover)
|
||||||
// ASSERT(now < 2 * MG_TCPIP_ACK_MS); ******** WE FAIL THIS, Mongoose does not
|
// ASSERT(now < 2 * MG_TCPIP_ACK_MS); ******** WE FAIL THIS, Mongoose does
|
||||||
// retransmit, FIN is not an additional element in the stream ASSERT((t->seq
|
// not retransmit, FIN is not an additional element in the stream
|
||||||
|
// ASSERT((t->seq
|
||||||
// == mg_htonl(2))); ASSERT((t->ack == mg_htonl(1001))); ASSERT(t->flags ==
|
// == mg_htonl(2))); ASSERT((t->ack == mg_htonl(1001))); ASSERT(t->flags ==
|
||||||
// (TH_FIN | TH_ACK)); // Mongoose retransmits FIN
|
// (TH_FIN | TH_ACK)); // Mongoose retransmits FIN
|
||||||
// send FIN + ACK
|
// send FIN + ACK
|
||||||
@@ -698,11 +704,12 @@ static void test_tcp_basics(bool ipv6) {
|
|||||||
ASSERT((t->flags == TH_SYN));
|
ASSERT((t->flags == TH_SYN));
|
||||||
ASSERT(event == 255);
|
ASSERT(event == 255);
|
||||||
if (ipv6) {
|
if (ipv6) {
|
||||||
ASSERT(i6->src[0] == mg_htonll(0x1000000000000000) && i6->src[1] == 0 && i6->dst[0] == mg_htonll(0x2000000000000000) && i6->dst[1] == 0);
|
ASSERT(i6->src[0] == mg_htonll(0x100000000000000) && i6->src[1] == 0 &&
|
||||||
|
i6->dst[0] == mg_htonll(0x200000000000000) && i6->dst[1] == 0);
|
||||||
ASSERT(tcp6csum_ok(i6, t));
|
ASSERT(tcp6csum_ok(i6, t));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
ASSERT(tcpcsum_ok(i, t));
|
ASSERT(tcpcsum_ok(i, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalid SYN + ACK to connecting client (after SYN...), send ACK != seq
|
// invalid SYN + ACK to connecting client (after SYN...), send ACK != seq
|
||||||
@@ -949,7 +956,7 @@ static void test_tcp_backlog(void) {
|
|||||||
while (!received_response(&s_driver_data) || i->proto != 6)
|
while (!received_response(&s_driver_data) || i->proto != 6)
|
||||||
mg_mgr_poll(&mgr, 0);
|
mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(t->flags == (TH_SYN | TH_ACK));
|
ASSERT(t->flags == (TH_SYN | TH_ACK));
|
||||||
seqnos[j] = ntohl(t->seq);
|
seqnos[j] = mg_ntohl(t->seq);
|
||||||
MG_VERBOSE(("SEQ: %p", seqnos[j]));
|
MG_VERBOSE(("SEQ: %p", seqnos[j]));
|
||||||
}
|
}
|
||||||
// check backlog is full and MSS are there
|
// check backlog is full and MSS are there
|
||||||
@@ -999,7 +1006,7 @@ static void test_tcp_backlog(void) {
|
|||||||
|
|
||||||
static void test_tcp(bool ipv6) {
|
static void test_tcp(bool ipv6) {
|
||||||
test_tcp_basics(ipv6);
|
test_tcp_basics(ipv6);
|
||||||
if(!ipv6) {
|
if (!ipv6) {
|
||||||
test_tcp_backlog();
|
test_tcp_backlog();
|
||||||
test_tcp_retransmit();
|
test_tcp_retransmit();
|
||||||
}
|
}
|
||||||
@@ -1022,7 +1029,8 @@ static void create_udp_dat(struct eth *e, struct ipp *ipp, uint16_t sport,
|
|||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ipp->ip6 != NULL) {
|
if (ipp->ip6 != NULL) {
|
||||||
struct ip6 *ip = ipp->ip6;
|
struct ip6 *ip = ipp->ip6;
|
||||||
struct udp *udp = (struct udp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
struct udp *udp =
|
||||||
|
(struct udp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
||||||
ip->plen = mg_htons((uint16_t) (sizeof(u) + payload_len));
|
ip->plen = mg_htons((uint16_t) (sizeof(u) + payload_len));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
memcpy(udp, &u, sizeof(u));
|
memcpy(udp, &u, sizeof(u));
|
||||||
@@ -1033,9 +1041,10 @@ static void create_udp_dat(struct eth *e, struct ipp *ipp, uint16_t sport,
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct ip *ip = ipp->ip4;
|
struct ip *ip = ipp->ip4;
|
||||||
struct udp *udp = (struct udp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
struct udp *udp =
|
||||||
|
(struct udp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
||||||
ip->len = mg_htons((uint16_t) (sizeof(*ip) + sizeof(u) + payload_len));
|
ip->len = mg_htons((uint16_t) (sizeof(*ip) + sizeof(u) + payload_len));
|
||||||
ip->csum = ipcsum(ip, sizeof(*ip)); // no options
|
ip->csum = ipcsum(ip, sizeof(*ip)); // no options
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||||
ip->csum = 0;
|
ip->csum = 0;
|
||||||
memcpy(udp, &u, sizeof(u));
|
memcpy(udp, &u, sizeof(u));
|
||||||
@@ -1052,7 +1061,7 @@ static void init_udp_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
|||||||
init_tests(mgr, e, ipp, driver, mif, 17); // 17 -> UDP
|
init_tests(mgr, e, ipp, driver, mif, 17); // 17 -> UDP
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
if (ipp->ip6 != NULL) {
|
if (ipp->ip6 != NULL) {
|
||||||
mif->state = MG_TCPIP_STATE_READY; // so DHCP stops
|
mif->state = MG_TCPIP_STATE_READY; // so DHCP stops
|
||||||
mif->state6 = MG_TCPIP_STATE_READY; // so mg_send() works and RS stops
|
mif->state6 = MG_TCPIP_STATE_READY; // so mg_send() works and RS stops
|
||||||
mg_listen(mgr, "udp://[::]:888", f, NULL);
|
mg_listen(mgr, "udp://[::]:888", f, NULL);
|
||||||
} else
|
} else
|
||||||
@@ -1070,7 +1079,8 @@ static void test_udp(bool ipv6) {
|
|||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct ip6 ip6;
|
struct ip6 ip6;
|
||||||
struct ipp ipp;
|
struct ipp ipp;
|
||||||
struct udp *u = (struct udp *) (s_driver_data.buf + sizeof(e) + (!ipv6 ? sizeof(ip) : sizeof(ip6)));
|
struct udp *u = (struct udp *) (s_driver_data.buf + sizeof(e) +
|
||||||
|
(!ipv6 ? sizeof(ip) : sizeof(ip6)));
|
||||||
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
||||||
struct ip6 *i6 = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
struct ip6 *i6 = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
||||||
struct mg_tcpip_driver driver;
|
struct mg_tcpip_driver driver;
|
||||||
@@ -1097,7 +1107,8 @@ static void test_udp(bool ipv6) {
|
|||||||
ASSERT(u->len == mg_htons(sizeof(*u) + 3));
|
ASSERT(u->len == mg_htons(sizeof(*u) + 3));
|
||||||
ASSERT(*((char *) (u + 1)) == 'P');
|
ASSERT(*((char *) (u + 1)) == 'P');
|
||||||
if (ipv6) {
|
if (ipv6) {
|
||||||
ASSERT(i6->src[0] == mg_htonll(0x1000000000000000) && i6->src[1] == 0 && i6->dst[0] == mg_htonll(0x2000000000000000) && i6->dst[1] == 0);
|
ASSERT(i6->src[0] == mg_htonll(0x100000000000000) && i6->src[1] == 0 &&
|
||||||
|
i6->dst[0] == mg_htonll(0x200000000000000) && i6->dst[1] == 0);
|
||||||
ASSERT(udp6csum_ok(i6, u));
|
ASSERT(udp6csum_ok(i6, u));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
@@ -1109,9 +1120,10 @@ static void test_udp(bool ipv6) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void create_icmp_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
static void create_icmp_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
||||||
uint8_t code, size_t payload_len) {
|
uint8_t code, size_t payload_len) {
|
||||||
struct ip *ip = ipp->ip4;
|
struct ip *ip = ipp->ip4;
|
||||||
struct icmp i, *icmp = (struct icmp *)(s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
struct icmp i,
|
||||||
|
*icmp = (struct icmp *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip));
|
||||||
memset(&i, 0, sizeof(i));
|
memset(&i, 0, sizeof(i));
|
||||||
i.type = type;
|
i.type = type;
|
||||||
i.code = code;
|
i.code = code;
|
||||||
@@ -1127,8 +1139,8 @@ static void create_icmp_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void init_icmp_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
static void init_icmp_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
||||||
struct mg_tcpip_driver *driver,
|
struct mg_tcpip_driver *driver,
|
||||||
struct mg_tcpip_if *mif) {
|
struct mg_tcpip_if *mif) {
|
||||||
init_tests(mgr, e, ipp, driver, mif, 1); // 1 -> ICMP
|
init_tests(mgr, e, ipp, driver, mif, 1); // 1 -> ICMP
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
mif->state6 = MG_TCPIP_STATE_READY; // so RS stops
|
mif->state6 = MG_TCPIP_STATE_READY; // so RS stops
|
||||||
@@ -1141,7 +1153,8 @@ static void test_icmp_basics(void) {
|
|||||||
struct eth e;
|
struct eth e;
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct ipp ipp;
|
struct ipp ipp;
|
||||||
struct icmp *icmp = (struct icmp *) (s_driver_data.buf + sizeof(e) + sizeof(ip));
|
struct icmp *icmp =
|
||||||
|
(struct icmp *) (s_driver_data.buf + sizeof(e) + sizeof(ip));
|
||||||
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
struct ip *i = (struct ip *) (s_driver_data.buf + sizeof(e));
|
||||||
struct mg_tcpip_driver driver;
|
struct mg_tcpip_driver driver;
|
||||||
struct mg_tcpip_if mif;
|
struct mg_tcpip_if mif;
|
||||||
@@ -1150,18 +1163,18 @@ static void test_icmp_basics(void) {
|
|||||||
ipp.ip6 = NULL;
|
ipp.ip6 = NULL;
|
||||||
init_icmp_tests(&mgr, &e, &ipp, &driver, &mif);
|
init_icmp_tests(&mgr, &e, &ipp, &driver, &mif);
|
||||||
|
|
||||||
create_icmp_dat(&e, &ipp, 8, 0, 0); // Echo Request
|
create_icmp_dat(&e, &ipp, 8, 0, 0); // Echo Request
|
||||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
ASSERT(i->proto == 1);
|
ASSERT(i->proto == 1);
|
||||||
ASSERT(i->len == mg_htons(sizeof(*i) + sizeof(*icmp) + 0));
|
ASSERT(i->len == mg_htons(sizeof(*i) + sizeof(*icmp) + 0));
|
||||||
ASSERT(ipcsum_ok(i)); // Bonus, not tested elsewhere
|
ASSERT(ipcsum_ok(i)); // Bonus, not tested elsewhere
|
||||||
ASSERT(icmp->type == 0); // Echo Reply
|
ASSERT(icmp->type == 0); // Echo Reply
|
||||||
ASSERT(icmp->code == 0);
|
ASSERT(icmp->code == 0);
|
||||||
ASSERT(icmpcsum_ok(icmp, sizeof(*icmp) + 0));
|
ASSERT(icmpcsum_ok(icmp, sizeof(*icmp) + 0));
|
||||||
|
|
||||||
create_icmp_dat(&e, &ipp, 8, 0, 69); // Echo Request
|
create_icmp_dat(&e, &ipp, 8, 0, 69); // Echo Request
|
||||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
ASSERT(i->src == mg_htonl(0x1000000) && i->dst == mg_htonl(0x2000000));
|
||||||
@@ -1179,29 +1192,31 @@ static void test_icmp(void) {
|
|||||||
test_icmp_basics();
|
test_icmp_basics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if MG_ENABLE_IPV6
|
#if MG_ENABLE_IPV6
|
||||||
static void create_icmp6_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
static void create_icmp6_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
||||||
uint8_t code, uint8_t *payload, size_t payload_len) {
|
uint8_t code, uint8_t *payload,
|
||||||
|
size_t payload_len) {
|
||||||
struct ip6 *ip6 = ipp->ip6;
|
struct ip6 *ip6 = ipp->ip6;
|
||||||
struct icmp6 i6, *icmp6 = (struct icmp6 *)(s_driver_data.buf + sizeof(*e) + sizeof(*ip6));
|
struct icmp6 i6,
|
||||||
|
*icmp6 = (struct icmp6 *) (s_driver_data.buf + sizeof(*e) + sizeof(*ip6));
|
||||||
memset(&i6, 0, sizeof(i6));
|
memset(&i6, 0, sizeof(i6));
|
||||||
i6.type = type;
|
i6.type = type;
|
||||||
i6.code = code;
|
i6.code = code;
|
||||||
if (payload != NULL)
|
if (payload != NULL)
|
||||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip6) + sizeof(*icmp6), payload, payload_len);
|
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip6) + sizeof(*icmp6),
|
||||||
|
payload, payload_len);
|
||||||
ip6->plen = mg_htons((uint16_t) (sizeof(*icmp6) + payload_len));
|
ip6->plen = mg_htons((uint16_t) (sizeof(*icmp6) + payload_len));
|
||||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||||
memcpy(s_driver_data.buf + sizeof(*e), ip6, sizeof(*ip6));
|
memcpy(s_driver_data.buf + sizeof(*e), ip6, sizeof(*ip6));
|
||||||
memcpy(icmp6, &i6, sizeof(i6));
|
memcpy(icmp6, &i6, sizeof(i6));
|
||||||
icmp6->csum = p6csum(ip6, icmp6, sizeof (*icmp6) + payload_len);
|
icmp6->csum = p6csum(ip6, icmp6, sizeof(*icmp6) + payload_len);
|
||||||
s_driver_data.len = sizeof(*e) + sizeof(*ip6) + sizeof(*icmp6) + payload_len;
|
s_driver_data.len = sizeof(*e) + sizeof(*ip6) + sizeof(*icmp6) + payload_len;
|
||||||
if (s_driver_data.len < 64) s_driver_data.len = 64; // add padding if needed
|
if (s_driver_data.len < 64) s_driver_data.len = 64; // add padding if needed
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_icmp6_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
static void init_icmp6_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
||||||
struct mg_tcpip_driver *driver,
|
struct mg_tcpip_driver *driver,
|
||||||
struct mg_tcpip_if *mif) {
|
struct mg_tcpip_if *mif) {
|
||||||
init_tests(mgr, e, ipp, driver, mif, 58); // 58 -> ICMPv6
|
init_tests(mgr, e, ipp, driver, mif, 58); // 58 -> ICMPv6
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1210,31 +1225,33 @@ static void test_icmp6_basics(void) {
|
|||||||
struct eth e;
|
struct eth e;
|
||||||
struct ip6 ip6;
|
struct ip6 ip6;
|
||||||
struct ipp ipp;
|
struct ipp ipp;
|
||||||
struct icmp6 *icmp6 = (struct icmp6 *) (s_driver_data.buf + sizeof(e) + sizeof(ip6));
|
struct icmp6 *icmp6 =
|
||||||
|
(struct icmp6 *) (s_driver_data.buf + sizeof(e) + sizeof(ip6));
|
||||||
struct ip6 *i = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
struct ip6 *i = (struct ip6 *) (s_driver_data.buf + sizeof(e));
|
||||||
struct mg_tcpip_driver driver;
|
struct mg_tcpip_driver driver;
|
||||||
struct mg_tcpip_if mif;
|
struct mg_tcpip_if mif;
|
||||||
uint8_t payload[28], *p = (uint8_t *)(icmp6 + 1);
|
uint8_t payload[28], *p = (uint8_t *) (icmp6 + 1);
|
||||||
|
|
||||||
|
|
||||||
ipp.ip4 = NULL;
|
ipp.ip4 = NULL;
|
||||||
ipp.ip6 = &ip6;
|
ipp.ip6 = &ip6;
|
||||||
init_icmp6_tests(&mgr, &e, &ipp, &driver, &mif);
|
init_icmp6_tests(&mgr, &e, &ipp, &driver, &mif);
|
||||||
|
|
||||||
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 0); // Echo Request
|
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 0); // Echo Request
|
||||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(i->src[0] == mg_htonll(0x1000000000000000) && i->src[1] == 0 && i->dst[0] == mg_htonll(0x2000000000000000) && i->dst[1] == 0);
|
ASSERT(i->src[0] == mg_htonll(0x100000000000000) && i->src[1] == 0 &&
|
||||||
|
i->dst[0] == mg_htonll(0x200000000000000) && i->dst[1] == 0);
|
||||||
ASSERT(i->next == 58);
|
ASSERT(i->next == 58);
|
||||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 0));
|
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 0));
|
||||||
ASSERT(icmp6->type == 129); // Echo Reply
|
ASSERT(icmp6->type == 129); // Echo Reply
|
||||||
ASSERT(icmp6->code == 0);
|
ASSERT(icmp6->code == 0);
|
||||||
ASSERT(icmp6csum_ok(i, icmp6));
|
ASSERT(icmp6csum_ok(i, icmp6));
|
||||||
|
|
||||||
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 69); // Echo Request
|
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 69); // Echo Request
|
||||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(i->src[0] == mg_htonll(0x1000000000000000) && i->src[1] == 0 && i->dst[0] == mg_htonll(0x2000000000000000) && i->dst[1] == 0);
|
ASSERT(i->src[0] == mg_htonll(0x100000000000000) && i->src[1] == 0 &&
|
||||||
|
i->dst[0] == mg_htonll(0x200000000000000) && i->dst[1] == 0);
|
||||||
ASSERT(i->next == 58);
|
ASSERT(i->next == 58);
|
||||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 69));
|
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 69));
|
||||||
ASSERT(icmp6->type == 129); // Echo Reply
|
ASSERT(icmp6->type == 129); // Echo Reply
|
||||||
@@ -1249,15 +1266,16 @@ static void test_icmp6_basics(void) {
|
|||||||
create_icmp6_dat(&e, &ipp, 135, 0, payload, 28);
|
create_icmp6_dat(&e, &ipp, 135, 0, payload, 28);
|
||||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||||
ASSERT(i->src[0] == mg_htonll(0x1000000000000000) && i->src[1] == 0 && i->dst[0] == mg_htonll(0x2000000000000000) && i->dst[1] == 0);
|
ASSERT(i->src[0] == mg_htonll(0x100000000000000) && i->src[1] == 0 &&
|
||||||
|
i->dst[0] == mg_htonll(0x200000000000000) && i->dst[1] == 0);
|
||||||
ASSERT(i->next == 58);
|
ASSERT(i->next == 58);
|
||||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 28));
|
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 28));
|
||||||
ASSERT(icmp6->type == 136); // Neighbor Advertisement
|
ASSERT(icmp6->type == 136); // Neighbor Advertisement
|
||||||
ASSERT(icmp6->code == 0);
|
ASSERT(icmp6->code == 0);
|
||||||
ASSERT(p[0] == 0x60); // solicited + override
|
ASSERT(p[0] == 0x60); // solicited + override
|
||||||
ASSERT(memcmp(p + 4, mif.ip6, 16) == 0); // target address
|
ASSERT(memcmp(p + 4, mif.ip6, 16) == 0); // target address
|
||||||
ASSERT(p[20] == 2); // target hwaddr
|
ASSERT(p[20] == 2); // target hwaddr
|
||||||
ASSERT(p[21] == 1); // hwaddr len
|
ASSERT(p[21] == 1); // hwaddr len
|
||||||
ASSERT(memcmp(p + 22, mif.mac, 6) == 0);
|
ASSERT(memcmp(p + 22, mif.mac, 6) == 0);
|
||||||
|
|
||||||
s_driver_data.len = 0;
|
s_driver_data.len = 0;
|
||||||
@@ -1269,7 +1287,6 @@ static void test_icmp6(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DASHBOARD(x) \
|
#define DASHBOARD(x) \
|
||||||
printf("HEALTH_DASHBOARD\t\"%s\": %s,\n", x, s_error ? "false" : "true");
|
printf("HEALTH_DASHBOARD\t\"%s\": %s,\n", x, s_error ? "false" : "true");
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user