mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-18 10:59:45 +00:00
add more tests, fix NDP
This commit is contained in:
1 parent
9ed98cecff
commit
21fbf9cdc5
3 files changed
+122
-10
No files matched your search
+6
-4
@@ -5525,7 +5525,7 @@ static void tx_ndp_na(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
||||
memcpy(data + 4, ip_src, 16); // Target address
|
||||
data[20] = 2; // 4.6.1, target hwaddr
|
||||
data[21] = mg_l2_ip6put(ifp->l2type, l2, data + 22); // option length / 8
|
||||
tx_icmp6(ifp, l2_dst, ip_src, ip_dst, 136, 0, data, 20 + 8 * data[21]);
|
||||
tx_icmp6(ifp, l2_dst, ip_src, ip_dst, 136, 0, data, 20 + (size_t)(8 * data[21]));
|
||||
}
|
||||
|
||||
static void onstate6change(struct mg_tcpip_if *ifp);
|
||||
@@ -5565,12 +5565,14 @@ static void rx_ndp_ns(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (pkt->pay.len < sizeof(target)) return;
|
||||
memcpy(target, pkt->pay.buf + 4, sizeof(target));
|
||||
if (MG_IP6MATCH(target, ifp->ip6ll) || MG_IP6MATCH(target, ifp->ip6)) {
|
||||
uint64_t req[2]; // requester address
|
||||
uint8_t l2[sizeof(struct mg_l2addr)];
|
||||
uint8_t len, *opts = (uint8_t *) pkt->pay.buf + 20;
|
||||
if (*opts++ != 2) return; // no target hwaddr
|
||||
if (*opts++ != 1) return; // no requester hwaddr (source)
|
||||
len = *opts++; // check valid hwaddr and get it
|
||||
if (!mg_l2_ip6get(ifp->l2type, l2, opts, len)) return;
|
||||
tx_ndp_na(ifp, l2, target, pkt->ip6->src, true, ifp->mac);
|
||||
req[0] = pkt->ip6->src[0], req[1] = pkt->ip6->src[1]; // align to 64-bit
|
||||
tx_ndp_na(ifp, l2, target, req, true, ifp->mac);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5743,7 +5745,7 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
return; // safety net for lousy networks
|
||||
if (plen > room) plen = room; // Copy (truncated) RX payload to TX
|
||||
// Echo Reply, 4.2
|
||||
tx_icmp6(ifp, l2addr, pkt->ip6->dst, pkt->ip6->src, 129, 0,
|
||||
tx_icmp6(ifp, l2addr, target, ips.addr.ip6, 129, 0,
|
||||
pkt->pay.buf, plen);
|
||||
}
|
||||
} break;
|
||||
|
||||
+6
-4
@@ -714,7 +714,7 @@ static void tx_ndp_na(struct mg_tcpip_if *ifp, uint8_t *l2_dst,
|
||||
memcpy(data + 4, ip_src, 16); // Target address
|
||||
data[20] = 2; // 4.6.1, target hwaddr
|
||||
data[21] = mg_l2_ip6put(ifp->l2type, l2, data + 22); // option length / 8
|
||||
tx_icmp6(ifp, l2_dst, ip_src, ip_dst, 136, 0, data, 20 + 8 * data[21]);
|
||||
tx_icmp6(ifp, l2_dst, ip_src, ip_dst, 136, 0, data, 20 + (size_t)(8 * data[21]));
|
||||
}
|
||||
|
||||
static void onstate6change(struct mg_tcpip_if *ifp);
|
||||
@@ -754,12 +754,14 @@ static void rx_ndp_ns(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (pkt->pay.len < sizeof(target)) return;
|
||||
memcpy(target, pkt->pay.buf + 4, sizeof(target));
|
||||
if (MG_IP6MATCH(target, ifp->ip6ll) || MG_IP6MATCH(target, ifp->ip6)) {
|
||||
uint64_t req[2]; // requester address
|
||||
uint8_t l2[sizeof(struct mg_l2addr)];
|
||||
uint8_t len, *opts = (uint8_t *) pkt->pay.buf + 20;
|
||||
if (*opts++ != 2) return; // no target hwaddr
|
||||
if (*opts++ != 1) return; // no requester hwaddr (source)
|
||||
len = *opts++; // check valid hwaddr and get it
|
||||
if (!mg_l2_ip6get(ifp->l2type, l2, opts, len)) return;
|
||||
tx_ndp_na(ifp, l2, target, pkt->ip6->src, true, ifp->mac);
|
||||
req[0] = pkt->ip6->src[0], req[1] = pkt->ip6->src[1]; // align to 64-bit
|
||||
tx_ndp_na(ifp, l2, target, req, true, ifp->mac);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +934,7 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
return; // safety net for lousy networks
|
||||
if (plen > room) plen = room; // Copy (truncated) RX payload to TX
|
||||
// Echo Reply, 4.2
|
||||
tx_icmp6(ifp, l2addr, pkt->ip6->dst, pkt->ip6->src, 129, 0,
|
||||
tx_icmp6(ifp, l2addr, target, ips.addr.ip6, 129, 0,
|
||||
pkt->pay.buf, plen);
|
||||
}
|
||||
} break;
|
||||
|
||||
+110
-2
@@ -1096,6 +1096,10 @@ static void init_icmp_tests(struct mg_mgr *mgr, struct eth *e, struct ipp *ipp,
|
||||
struct mg_tcpip_driver *driver,
|
||||
struct mg_tcpip_if *mif) {
|
||||
init_tests(mgr, e, ipp, driver, mif, 1); // 1 -> ICMP
|
||||
#if MG_ENABLE_IPV6
|
||||
mif->state6 = MG_TCPIP_STATE_READY; // so RS stops
|
||||
mg_mgr_poll(mgr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_icmp_basics(void) {
|
||||
@@ -1112,7 +1116,7 @@ static void test_icmp_basics(void) {
|
||||
ipp.ip6 = NULL;
|
||||
init_icmp_tests(&mgr, &e, &ipp, &driver, &mif);
|
||||
|
||||
create_icmp_dat(&e, &ipp, 8, 0, 0);
|
||||
create_icmp_dat(&e, &ipp, 8, 0, 0); // Echo Request
|
||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(i->src == 1 && i->dst == 2);
|
||||
@@ -1123,7 +1127,7 @@ static void test_icmp_basics(void) {
|
||||
ASSERT(icmp->code == 0);
|
||||
ASSERT(ipcsum(icmp, sizeof(*icmp) + 0) == 0);
|
||||
|
||||
create_icmp_dat(&e, &ipp, 8, 0, 69);
|
||||
create_icmp_dat(&e, &ipp, 8, 0, 69); // Echo Request
|
||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(i->src == 1 && i->dst == 2);
|
||||
@@ -1142,6 +1146,106 @@ static void test_icmp(void) {
|
||||
}
|
||||
|
||||
|
||||
#if MG_ENABLE_IPV6
|
||||
static uint16_t icmp6csum(struct ip6 *ip6, size_t len) {
|
||||
uint32_t cs;
|
||||
struct icmp6 *icmp6 = (struct icmp6 *) (ip6 + 1);
|
||||
cs = csumup(0, icmp6, sizeof(*icmp6));
|
||||
cs = csumup(cs, icmp6 + 1, len);
|
||||
cs = csumup(cs, ip6->src, 16);
|
||||
cs = csumup(cs, ip6->dst, 16);
|
||||
cs += (uint32_t) (58 + sizeof(*icmp6) + len);
|
||||
return csumfin(cs);
|
||||
}
|
||||
|
||||
static void create_icmp6_dat(struct eth *e, struct ipp *ipp, uint8_t type,
|
||||
uint8_t code, uint8_t *payload, size_t payload_len) {
|
||||
struct icmp6 icmp6;
|
||||
struct ip6 *ip6 = ipp->ip6;
|
||||
memset(&icmp6, 0, sizeof(icmp6));
|
||||
icmp6.type = type;
|
||||
icmp6.code = code;
|
||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||
ip6->plen = mg_htons((uint16_t) (sizeof(icmp6) + payload_len));
|
||||
memcpy(s_driver_data.buf + sizeof(*e), ip6, sizeof(*ip6));
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip6), &icmp6, sizeof(icmp6));
|
||||
if (payload != NULL)
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip6) + sizeof(icmp6), payload, payload_len);
|
||||
s_driver_data.len = sizeof(*e) + sizeof(*ip6) + sizeof(icmp6) + payload_len;
|
||||
icmp6.csum = icmp6csum((struct ip6 *)(s_driver_data.buf + sizeof(*e)), payload_len);
|
||||
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,
|
||||
struct mg_tcpip_driver *driver,
|
||||
struct mg_tcpip_if *mif) {
|
||||
init_tests(mgr, e, ipp, driver, mif, 58); // 58 -> ICMPv6
|
||||
}
|
||||
|
||||
static void test_icmp6_basics(void) {
|
||||
struct mg_mgr mgr;
|
||||
struct eth e;
|
||||
struct ip6 ip6;
|
||||
struct ipp ipp;
|
||||
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 mg_tcpip_driver driver;
|
||||
struct mg_tcpip_if mif;
|
||||
uint8_t payload[28], *p = (uint8_t *)(icmp6 + 1);
|
||||
|
||||
|
||||
ipp.ip4 = NULL;
|
||||
ipp.ip6 = &ip6;
|
||||
init_icmp6_tests(&mgr, &e, &ipp, &driver, &mif);
|
||||
|
||||
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 0); // Echo Request
|
||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(i->src[0] == 1 && i->src[1] == 0 && i->dst[0] == 2 && i->dst[1] == 0);
|
||||
ASSERT(i->next == 58);
|
||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 0));
|
||||
ASSERT(icmp6->type == 129); // Echo Reply
|
||||
ASSERT(icmp6->code == 0);
|
||||
ASSERT(icmp6csum(i, 0) == 0);
|
||||
|
||||
create_icmp6_dat(&e, &ipp, 128, 0, NULL, 69); // Echo Request
|
||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(i->src[0] == 1 && i->src[1] == 0 && i->dst[0] == 2 && i->dst[1] == 0);
|
||||
ASSERT(i->next == 58);
|
||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 69));
|
||||
ASSERT(icmp6->type == 129); // Echo Reply
|
||||
ASSERT(icmp6->code == 0);
|
||||
ASSERT(icmp6csum(i, 69) == 0);
|
||||
|
||||
// Neighbor Solicitation
|
||||
memset(payload, 0, sizeof(payload));
|
||||
memcpy(payload + 4, mif.ip6, 16);
|
||||
payload[20] = 1; // source hwaddr
|
||||
payload[21] = 1; // hwaddr len
|
||||
create_icmp6_dat(&e, &ipp, 135, 0, payload, 28);
|
||||
mg_mgr_poll(&mgr, 0); // make sure we clean former stuff in buffer
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(i->src[0] == 1 && i->src[1] == 0 && i->dst[0] == 2 && i->dst[1] == 0);
|
||||
ASSERT(i->next == 58);
|
||||
ASSERT(i->plen == mg_htons(sizeof(*icmp6) + 28));
|
||||
ASSERT(icmp6->type == 136); // Neighbor Advertisement
|
||||
ASSERT(icmp6->code == 0);
|
||||
ASSERT(p[0] == 0x60); // solicited + override
|
||||
ASSERT(memcmp(p + 4, mif.ip6, 16) == 0); // target address
|
||||
ASSERT(p[20] == 2); // target hwaddr
|
||||
ASSERT(p[21] == 1); // hwaddr len
|
||||
ASSERT(memcmp(p + 22, mif.mac, 6) == 0);
|
||||
|
||||
s_driver_data.len = 0;
|
||||
mg_mgr_free(&mgr);
|
||||
}
|
||||
|
||||
static void test_icmp6(void) {
|
||||
test_icmp6_basics();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define DASHBOARD(x) \
|
||||
printf("HEALTH_DASHBOARD\t\"%s\": %s,\n", x, s_error ? "false" : "true");
|
||||
@@ -1172,6 +1276,10 @@ int main(void) {
|
||||
DASHBOARD("udp");
|
||||
|
||||
#if MG_ENABLE_IPV6
|
||||
s_error = false;
|
||||
test_icmp6();
|
||||
DASHBOARD("icmp6");
|
||||
|
||||
s_error = false;
|
||||
test_state6change();
|
||||
DASHBOARD("state6change");
|
||||
|
||||
Reference in new issue
Block a user