Skip to content

Commit d64e536

Browse files
committed
Fix socket local_ip selection with multi_if
1 parent 4539903 commit d64e536

2 files changed

Lines changed: 288 additions & 38 deletions

File tree

src/test/unit/unit.c

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,56 @@ static void reset_heap(void) {
102102
heap.size = 0;
103103
}
104104

105+
static void setup_stack_with_two_ifaces(struct wolfIP *s, ip4 primary_ip, ip4 secondary_ip)
106+
{
107+
wolfIP_init(s);
108+
mock_link_init(s);
109+
mock_link_init_idx(s, TEST_SECOND_IF, NULL);
110+
wolfIP_ipconfig_set(s, primary_ip, 0xFFFFFF00U, 0);
111+
wolfIP_ipconfig_set_ex(s, TEST_SECOND_IF, secondary_ip, 0xFFFFFF00U, 0);
112+
}
113+
114+
static void inject_tcp_syn(struct wolfIP *s, unsigned int if_idx, ip4 dst_ip, uint16_t dst_port)
115+
{
116+
struct wolfIP_tcp_seg syn;
117+
struct wolfIP_ll_dev *ll = wolfIP_getdev_ex(s, if_idx);
118+
union transport_pseudo_header ph;
119+
static const uint8_t src_mac[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60};
120+
121+
ck_assert_ptr_nonnull(ll);
122+
memset(&syn, 0, sizeof(syn));
123+
memcpy(syn.ip.eth.dst, ll->mac, 6);
124+
memcpy(syn.ip.eth.src, src_mac, 6);
125+
syn.ip.eth.type = ee16(ETH_TYPE_IP);
126+
syn.ip.ver_ihl = 0x45;
127+
syn.ip.ttl = 64;
128+
syn.ip.proto = WI_IPPROTO_TCP;
129+
syn.ip.len = ee16(IP_HEADER_LEN + TCP_HEADER_LEN);
130+
syn.ip.src = ee32(0x0A0000A1U);
131+
syn.ip.dst = ee32(dst_ip);
132+
syn.ip.csum = 0;
133+
iphdr_set_checksum(&syn.ip);
134+
135+
syn.src_port = ee16(40000);
136+
syn.dst_port = ee16(dst_port);
137+
syn.seq = ee32(1);
138+
syn.ack = 0;
139+
syn.hlen = TCP_HEADER_LEN << 2;
140+
syn.flags = 0x02;
141+
syn.win = ee16(65535);
142+
syn.csum = 0;
143+
syn.urg = 0;
144+
145+
memset(&ph, 0, sizeof(ph));
146+
ph.ph.src = syn.ip.src;
147+
ph.ph.dst = syn.ip.dst;
148+
ph.ph.proto = WI_IPPROTO_TCP;
149+
ph.ph.len = ee16(TCP_HEADER_LEN);
150+
syn.csum = ee16(transport_checksum(&ph, &syn.src_port));
151+
152+
tcp_input(s, if_idx, &syn, sizeof(struct wolfIP_eth_frame) + IP_HEADER_LEN + TCP_HEADER_LEN);
153+
}
154+
105155

106156
START_TEST(test_fifo_init)
107157
{
@@ -934,6 +984,155 @@ START_TEST(test_loopback_dest_not_forwarded)
934984
}
935985
END_TEST
936986

987+
START_TEST(test_tcp_listen_rejects_wrong_interface)
988+
{
989+
struct wolfIP s;
990+
const ip4 primary_ip = 0xC0A80001U;
991+
const ip4 secondary_ip = 0xC0A80101U;
992+
const uint16_t listen_port = 12345;
993+
int listen_fd;
994+
struct wolfIP_sockaddr_in addr;
995+
struct tsocket *listener;
996+
997+
setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
998+
999+
listen_fd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, 0);
1000+
ck_assert_int_ge(listen_fd, 0);
1001+
listener = &s.tcpsockets[listen_fd & ~MARK_TCP_SOCKET];
1002+
1003+
memset(&addr, 0, sizeof(addr));
1004+
addr.sin_family = AF_INET;
1005+
addr.sin_port = ee16(listen_port);
1006+
addr.sin_addr.s_addr = ee32(primary_ip);
1007+
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_fd, (struct wolfIP_sockaddr *)&addr, sizeof(addr)), 0);
1008+
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_fd, 1), 0);
1009+
1010+
inject_tcp_syn(&s, TEST_SECOND_IF, secondary_ip, listen_port);
1011+
1012+
ck_assert_int_eq(listener->sock.tcp.state, TCP_LISTEN);
1013+
ck_assert_int_eq(listener->events & CB_EVENT_READABLE, 0);
1014+
}
1015+
END_TEST
1016+
1017+
START_TEST(test_tcp_listen_accepts_bound_interface)
1018+
{
1019+
struct wolfIP s;
1020+
const ip4 primary_ip = 0xC0A80002U;
1021+
const ip4 secondary_ip = 0xC0A80101U;
1022+
const uint16_t listen_port = 23456;
1023+
int listen_fd;
1024+
int client_fd;
1025+
struct wolfIP_sockaddr_in addr;
1026+
struct tsocket *listener;
1027+
struct tsocket *client;
1028+
1029+
setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
1030+
1031+
listen_fd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, 0);
1032+
ck_assert_int_ge(listen_fd, 0);
1033+
listener = &s.tcpsockets[listen_fd & ~MARK_TCP_SOCKET];
1034+
1035+
memset(&addr, 0, sizeof(addr));
1036+
addr.sin_family = AF_INET;
1037+
addr.sin_port = ee16(listen_port);
1038+
addr.sin_addr.s_addr = ee32(secondary_ip);
1039+
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_fd, (struct wolfIP_sockaddr *)&addr, sizeof(addr)), 0);
1040+
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_fd, 1), 0);
1041+
1042+
inject_tcp_syn(&s, TEST_SECOND_IF, secondary_ip, listen_port);
1043+
1044+
ck_assert_int_eq(listener->sock.tcp.state, TCP_SYN_RCVD);
1045+
ck_assert_uint_eq(listener->local_ip, secondary_ip);
1046+
ck_assert_uint_eq(listener->if_idx, TEST_SECOND_IF);
1047+
1048+
client_fd = wolfIP_sock_accept(&s, listen_fd, NULL, NULL);
1049+
ck_assert_int_ge(client_fd, 0);
1050+
client = &s.tcpsockets[client_fd & ~MARK_TCP_SOCKET];
1051+
ck_assert_uint_eq(client->local_ip, secondary_ip);
1052+
ck_assert_uint_eq(client->bound_local_ip, secondary_ip);
1053+
ck_assert_int_eq(client->sock.tcp.state, TCP_ESTABLISHED);
1054+
}
1055+
END_TEST
1056+
1057+
START_TEST(test_tcp_listen_accepts_any_interface)
1058+
{
1059+
struct wolfIP s;
1060+
const ip4 primary_ip = 0xC0A80005U;
1061+
const ip4 secondary_ip = 0xC0A80105U;
1062+
const uint16_t listen_port = 34567;
1063+
int listen_fd;
1064+
int client_fd;
1065+
struct wolfIP_sockaddr_in addr;
1066+
struct tsocket *listener;
1067+
struct tsocket *client;
1068+
1069+
setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
1070+
1071+
listen_fd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, 0);
1072+
ck_assert_int_ge(listen_fd, 0);
1073+
listener = &s.tcpsockets[listen_fd & ~MARK_TCP_SOCKET];
1074+
1075+
memset(&addr, 0, sizeof(addr));
1076+
addr.sin_family = AF_INET;
1077+
addr.sin_port = ee16(listen_port);
1078+
addr.sin_addr.s_addr = ee32(IPADDR_ANY);
1079+
ck_assert_int_eq(wolfIP_sock_bind(&s, listen_fd, (struct wolfIP_sockaddr *)&addr, sizeof(addr)), 0);
1080+
ck_assert_int_eq(wolfIP_sock_listen(&s, listen_fd, 1), 0);
1081+
1082+
inject_tcp_syn(&s, TEST_SECOND_IF, secondary_ip, listen_port);
1083+
1084+
ck_assert_int_eq(listener->sock.tcp.state, TCP_SYN_RCVD);
1085+
ck_assert_uint_eq(listener->local_ip, secondary_ip);
1086+
ck_assert_uint_eq(listener->if_idx, TEST_SECOND_IF);
1087+
1088+
client_fd = wolfIP_sock_accept(&s, listen_fd, NULL, NULL);
1089+
ck_assert_int_ge(client_fd, 0);
1090+
client = &s.tcpsockets[client_fd & ~MARK_TCP_SOCKET];
1091+
ck_assert_uint_eq(client->local_ip, secondary_ip);
1092+
ck_assert_int_eq(client->sock.tcp.state, TCP_ESTABLISHED);
1093+
}
1094+
END_TEST
1095+
1096+
START_TEST(test_sock_connect_selects_local_ip_multi_if)
1097+
{
1098+
struct wolfIP s;
1099+
const ip4 primary_ip = 0xC0A80009U;
1100+
const ip4 secondary_ip = 0xC0A80109U;
1101+
const ip4 remote_primary = 0xC0A800AAU;
1102+
const ip4 remote_secondary = 0xC0A801A1U;
1103+
int udp_fd;
1104+
int tcp_fd;
1105+
struct wolfIP_sockaddr_in dst;
1106+
struct tsocket *ts;
1107+
int ret;
1108+
1109+
setup_stack_with_two_ifaces(&s, primary_ip, secondary_ip);
1110+
1111+
udp_fd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, 0);
1112+
ck_assert_int_ge(udp_fd, 0);
1113+
memset(&dst, 0, sizeof(dst));
1114+
dst.sin_family = AF_INET;
1115+
dst.sin_port = ee16(5555);
1116+
dst.sin_addr.s_addr = ee32(remote_secondary);
1117+
ck_assert_int_eq(wolfIP_sock_connect(&s, udp_fd, (struct wolfIP_sockaddr *)&dst, sizeof(dst)), 0);
1118+
ts = &s.udpsockets[udp_fd & ~MARK_UDP_SOCKET];
1119+
ck_assert_uint_eq(ts->local_ip, secondary_ip);
1120+
ck_assert_uint_eq(ts->if_idx, TEST_SECOND_IF);
1121+
1122+
tcp_fd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_STREAM, 0);
1123+
ck_assert_int_ge(tcp_fd, 0);
1124+
memset(&dst, 0, sizeof(dst));
1125+
dst.sin_family = AF_INET;
1126+
dst.sin_port = ee16(8080);
1127+
dst.sin_addr.s_addr = ee32(remote_primary);
1128+
ret = wolfIP_sock_connect(&s, tcp_fd, (struct wolfIP_sockaddr *)&dst, sizeof(dst));
1129+
ck_assert_int_eq(ret, -WOLFIP_EAGAIN);
1130+
ts = &s.tcpsockets[tcp_fd & ~MARK_TCP_SOCKET];
1131+
ck_assert_uint_eq(ts->local_ip, primary_ip);
1132+
ck_assert_uint_eq(ts->if_idx, TEST_PRIMARY_IF);
1133+
}
1134+
END_TEST
1135+
9371136

9381137
// Test for `transport_checksum` calculation
9391138
START_TEST(test_transport_checksum) {
@@ -1136,6 +1335,14 @@ Suite *wolf_suite(void)
11361335
suite_add_tcase(s, tc_proto);
11371336
tcase_add_test(tc_proto, test_loopback_dest_not_forwarded);
11381337
suite_add_tcase(s, tc_proto);
1338+
tcase_add_test(tc_proto, test_tcp_listen_rejects_wrong_interface);
1339+
suite_add_tcase(s, tc_proto);
1340+
tcase_add_test(tc_proto, test_tcp_listen_accepts_bound_interface);
1341+
suite_add_tcase(s, tc_proto);
1342+
tcase_add_test(tc_proto, test_tcp_listen_accepts_any_interface);
1343+
suite_add_tcase(s, tc_proto);
1344+
tcase_add_test(tc_proto, test_sock_connect_selects_local_ip_multi_if);
1345+
suite_add_tcase(s, tc_proto);
11391346

11401347
tcase_add_test(tc_utils, test_transport_checksum);
11411348
suite_add_tcase(s, tc_proto);

0 commit comments

Comments
 (0)