Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 227 additions & 5 deletions src/test/unit/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,219 @@ START_TEST(test_udp_sendto_and_recvfrom)
(struct wolfIP_sockaddr *)&from, &from_len);
ck_assert_int_eq(ret, (int)sizeof(payload));
ck_assert_mem_eq(rxbuf, payload, sizeof(payload));
ck_assert_uint_eq(from.sin_port, remote_port);
ck_assert_uint_eq(from.sin_port, ee16(remote_port));
}
END_TEST

START_TEST(test_udp_recvfrom_sets_remote_ip)
{
struct wolfIP s;
int sd;
struct wolfIP_sockaddr_in sin;
uint8_t payload[4] = {0xAA, 0xBB, 0xCC, 0xDD};
uint8_t rxbuf[4] = {0};
struct wolfIP_sockaddr_in from;
socklen_t from_len = sizeof(from);
int ret;
ip4 local_ip = 0x0A000001U;
ip4 remote_ip = 0x0A000002U;
uint16_t local_port = 4001;
uint16_t remote_port = 5001;
struct tsocket *ts;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, local_ip, 0xFFFFFF00U, 0);

sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
ck_assert_int_gt(sd, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(local_port);
sin.sin_addr.s_addr = ee32(local_ip);
ret = wolfIP_sock_bind(&s, sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin));
ck_assert_int_eq(ret, 0);

ts = &s.udpsockets[SOCKET_UNMARK(sd)];
ck_assert_uint_eq(ts->remote_ip, 0);

inject_udp_datagram(&s, TEST_PRIMARY_IF, remote_ip, local_ip, remote_port, local_port,
payload, sizeof(payload));

memset(&from, 0, sizeof(from));
ret = wolfIP_sock_recvfrom(&s, sd, rxbuf, sizeof(rxbuf), 0,
(struct wolfIP_sockaddr *)&from, &from_len);
ck_assert_int_eq(ret, (int)sizeof(payload));
ck_assert_mem_eq(rxbuf, payload, sizeof(payload));
ck_assert_uint_eq(from.sin_addr.s_addr, ee32(remote_ip));
ck_assert_uint_eq(ts->remote_ip, remote_ip);
}
END_TEST

START_TEST(test_udp_recvfrom_null_src_addr_len)
{
struct wolfIP s;
int sd;
struct wolfIP_sockaddr_in sin;
uint8_t payload[4] = {0x11, 0x22, 0x33, 0x44};
uint8_t rxbuf[4] = {0};
int ret;
ip4 local_ip = 0x0A000001U;
ip4 remote_ip = 0x0A000002U;
uint16_t local_port = 4002;
uint16_t remote_port = 5002;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, local_ip, 0xFFFFFF00U, 0);

sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
ck_assert_int_gt(sd, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(local_port);
sin.sin_addr.s_addr = ee32(local_ip);
ret = wolfIP_sock_bind(&s, sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin));
ck_assert_int_eq(ret, 0);

inject_udp_datagram(&s, TEST_PRIMARY_IF, remote_ip, local_ip, remote_port, local_port,
payload, sizeof(payload));

ret = wolfIP_sock_recvfrom(&s, sd, rxbuf, sizeof(rxbuf), 0, NULL, NULL);
ck_assert_int_eq(ret, (int)sizeof(payload));
ck_assert_mem_eq(rxbuf, payload, sizeof(payload));
}
END_TEST

START_TEST(test_udp_recvfrom_preserves_remote_ip)
{
struct wolfIP s;
int sd;
struct wolfIP_sockaddr_in sin;
uint8_t payload[4] = {0x55, 0x66, 0x77, 0x88};
uint8_t rxbuf[4] = {0};
struct wolfIP_sockaddr_in from;
socklen_t from_len = sizeof(from);
int ret;
ip4 local_ip = 0x0A000001U;
ip4 remote_ip = 0x0A000002U;
ip4 preset_remote_ip = 0x0A000099U;
uint16_t local_port = 4003;
uint16_t remote_port = 5003;
struct tsocket *ts;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, local_ip, 0xFFFFFF00U, 0);

sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
ck_assert_int_gt(sd, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(local_port);
sin.sin_addr.s_addr = ee32(local_ip);
ret = wolfIP_sock_bind(&s, sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin));
ck_assert_int_eq(ret, 0);

ts = &s.udpsockets[SOCKET_UNMARK(sd)];
ts->remote_ip = preset_remote_ip;

inject_udp_datagram(&s, TEST_PRIMARY_IF, remote_ip, local_ip, remote_port, local_port,
payload, sizeof(payload));

memset(&from, 0, sizeof(from));
ret = wolfIP_sock_recvfrom(&s, sd, rxbuf, sizeof(rxbuf), 0,
(struct wolfIP_sockaddr *)&from, &from_len);
ck_assert_int_eq(ret, (int)sizeof(payload));
ck_assert_mem_eq(rxbuf, payload, sizeof(payload));
ck_assert_uint_eq(from.sin_addr.s_addr, ee32(remote_ip));
ck_assert_uint_eq(ts->remote_ip, preset_remote_ip);
}
END_TEST

START_TEST(test_udp_recvfrom_null_addrlen)
{
struct wolfIP s;
int sd;
struct wolfIP_sockaddr_in sin;
uint8_t payload[4] = {0x9A, 0xBC, 0xDE, 0xF0};
uint8_t rxbuf[4] = {0};
struct wolfIP_sockaddr_in from;
int ret;
ip4 local_ip = 0x0A000001U;
ip4 remote_ip = 0x0A000002U;
uint16_t local_port = 4004;
uint16_t remote_port = 5004;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, local_ip, 0xFFFFFF00U, 0);

sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
ck_assert_int_gt(sd, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(local_port);
sin.sin_addr.s_addr = ee32(local_ip);
ret = wolfIP_sock_bind(&s, sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin));
ck_assert_int_eq(ret, 0);

inject_udp_datagram(&s, TEST_PRIMARY_IF, remote_ip, local_ip, remote_port, local_port,
payload, sizeof(payload));

memset(&from, 0, sizeof(from));
ret = wolfIP_sock_recvfrom(&s, sd, rxbuf, sizeof(rxbuf), 0,
(struct wolfIP_sockaddr *)&from, NULL);
ck_assert_int_eq(ret, -WOLFIP_EINVAL);
}
END_TEST

START_TEST(test_udp_recvfrom_src_equals_local_ip_does_not_persist_remote)
{
struct wolfIP s;
int sd;
struct wolfIP_sockaddr_in sin;
uint8_t payload[4] = {0x01, 0x02, 0x03, 0x04};
uint8_t rxbuf[4] = {0};
struct wolfIP_sockaddr_in from;
socklen_t from_len = sizeof(from);
int ret;
ip4 local_ip = 0x0A000001U;
uint16_t local_port = 4005;
uint16_t remote_port = 5005;
struct tsocket *ts;

wolfIP_init(&s);
mock_link_init(&s);
wolfIP_ipconfig_set(&s, local_ip, 0xFFFFFF00U, 0);

sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_UDP);
ck_assert_int_gt(sd, 0);

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(local_port);
sin.sin_addr.s_addr = ee32(local_ip);
ret = wolfIP_sock_bind(&s, sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin));
ck_assert_int_eq(ret, 0);

ts = &s.udpsockets[SOCKET_UNMARK(sd)];
ck_assert_uint_eq(ts->remote_ip, 0);

inject_udp_datagram(&s, TEST_PRIMARY_IF, local_ip, local_ip, remote_port, local_port,
payload, sizeof(payload));

memset(&from, 0, sizeof(from));
ret = wolfIP_sock_recvfrom(&s, sd, rxbuf, sizeof(rxbuf), 0,
(struct wolfIP_sockaddr *)&from, &from_len);
ck_assert_int_eq(ret, (int)sizeof(payload));
ck_assert_mem_eq(rxbuf, payload, sizeof(payload));
ck_assert_uint_eq(from.sin_addr.s_addr, ee32(local_ip));
ck_assert_uint_eq(ts->remote_ip, 0);
}
END_TEST

Expand Down Expand Up @@ -1449,13 +1661,13 @@ START_TEST(test_sock_recvfrom_short_addrlen)
ck_assert_int_gt(udp_sd, 0);
alen = (socklen_t)1;
ck_assert_int_eq(wolfIP_sock_recvfrom(&s, udp_sd, buf, sizeof(buf), 0,
(struct wolfIP_sockaddr *)&sin, &alen), -1);
(struct wolfIP_sockaddr *)&sin, &alen), -WOLFIP_EINVAL);

icmp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_ICMP);
ck_assert_int_gt(icmp_sd, 0);
alen = (socklen_t)1;
ck_assert_int_eq(wolfIP_sock_recvfrom(&s, icmp_sd, buf, sizeof(buf), 0,
(struct wolfIP_sockaddr *)&sin, &alen), -1);
(struct wolfIP_sockaddr *)&sin, &alen), -WOLFIP_EINVAL);
}
END_TEST
START_TEST(test_dns_query_and_callback_a)
Expand Down Expand Up @@ -4275,7 +4487,7 @@ START_TEST(test_sock_recvfrom_udp_short_addrlen)
ck_assert_int_gt(udp_sd, 0);

ck_assert_int_eq(wolfIP_sock_recvfrom(&s, udp_sd, buf, sizeof(buf), 0,
(struct wolfIP_sockaddr *)&sin, &alen), -1);
(struct wolfIP_sockaddr *)&sin, &alen), -WOLFIP_EINVAL);
}
END_TEST

Expand All @@ -4294,7 +4506,7 @@ START_TEST(test_sock_recvfrom_icmp_short_addrlen)
ck_assert_int_gt(icmp_sd, 0);

ck_assert_int_eq(wolfIP_sock_recvfrom(&s, icmp_sd, buf, sizeof(buf), 0,
(struct wolfIP_sockaddr *)&sin, &alen), -1);
(struct wolfIP_sockaddr *)&sin, &alen), -WOLFIP_EINVAL);
}
END_TEST

Expand Down Expand Up @@ -12082,6 +12294,16 @@ Suite *wolf_suite(void)
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_sendto_and_recvfrom);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_recvfrom_sets_remote_ip);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_recvfrom_null_src_addr_len);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_recvfrom_preserves_remote_ip);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_recvfrom_null_addrlen);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_udp_recvfrom_src_equals_local_ip_does_not_persist_remote);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_dns_query_and_callback_a);
suite_add_tcase(s, tc_proto);
tcase_add_test(tc_proto, test_dhcp_parse_offer_and_ack);
Expand Down
17 changes: 13 additions & 4 deletions src/wolfip.c
Original file line number Diff line number Diff line change
Expand Up @@ -2647,17 +2647,24 @@ int wolfIP_sock_recvfrom(struct wolfIP *s, int sockfd, void *buf, size_t len, in
if (SOCKET_UNMARK(sockfd) >= MAX_UDPSOCKETS)
return -WOLFIP_EINVAL;
ts = &s->udpsockets[SOCKET_UNMARK(sockfd)];
if (sin && !addrlen)
return -WOLFIP_EINVAL;
if (sin && *addrlen < sizeof(struct wolfIP_sockaddr_in))
return -1;
return -WOLFIP_EINVAL;
if (addrlen) *addrlen = sizeof(struct wolfIP_sockaddr_in);
if (fifo_len(&ts->sock.udp.rxbuf) == 0)
return -WOLFIP_EAGAIN;
desc = fifo_peek(&ts->sock.udp.rxbuf);
udp = (struct wolfIP_udp_datagram *)(ts->rxmem + desc->pos + sizeof(*desc));
if (ts->remote_ip == 0) {
ip4 src_ip = ee32(udp->ip.src);
if (src_ip != ts->local_ip)
ts->remote_ip = src_ip;
}
if (sin) {
sin->sin_family = AF_INET;
sin->sin_port = ee16(udp->src_port);
sin->sin_addr.s_addr = ee32(ts->remote_ip);
sin->sin_port = udp->src_port;
sin->sin_addr.s_addr = udp->ip.src;
}
seg_len = ee16(udp->len) - UDP_HEADER_LEN;
if (seg_len > len)
Expand All @@ -2670,8 +2677,10 @@ int wolfIP_sock_recvfrom(struct wolfIP *s, int sockfd, void *buf, size_t len, in
if (SOCKET_UNMARK(sockfd) >= MAX_ICMPSOCKETS)
return -WOLFIP_EINVAL;
ts = &s->icmpsockets[SOCKET_UNMARK(sockfd)];
if (sin && !addrlen)
return -WOLFIP_EINVAL;
if (sin && *addrlen < sizeof(struct wolfIP_sockaddr_in))
return -1;
return -WOLFIP_EINVAL;
if (addrlen)
*addrlen = sizeof(struct wolfIP_sockaddr_in);
desc = fifo_peek(&ts->sock.udp.rxbuf);
Expand Down