1 #include "test_ip4.h"
2
3 #include "lwip/icmp.h"
4 #include "lwip/ip4.h"
5 #include "lwip/etharp.h"
6 #include "lwip/inet_chksum.h"
7 #include "lwip/stats.h"
8 #include "lwip/prot/ip.h"
9 #include "lwip/prot/ip4.h"
10
11 #include "lwip/tcpip.h"
12
13 #if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
14 #error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
15 #endif
16
17 static struct netif test_netif;
18 static ip4_addr_t test_ipaddr, test_netmask, test_gw;
19 static int linkoutput_ctr;
20 static int linkoutput_byte_ctr;
21 static u16_t linkoutput_pkt_len;
22 static u8_t linkoutput_pkt[100];
23
24 /* reference internal lwip variable in netif.c */
25
26 static err_t
test_netif_linkoutput(struct netif * netif,struct pbuf * p)27 test_netif_linkoutput(struct netif *netif, struct pbuf *p)
28 {
29 fail_unless(netif == &test_netif);
30 fail_unless(p != NULL);
31 linkoutput_ctr++;
32 linkoutput_byte_ctr += p->tot_len;
33 /* Copy start of packet into buffer */
34 linkoutput_pkt_len = pbuf_copy_partial(p, linkoutput_pkt, sizeof(linkoutput_pkt), 0);
35 return ERR_OK;
36 }
37
38 static err_t
test_netif_init(struct netif * netif)39 test_netif_init(struct netif *netif)
40 {
41 fail_unless(netif != NULL);
42 netif->linkoutput = test_netif_linkoutput;
43 netif->output = etharp_output;
44 netif->mtu = 1500;
45 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
46 netif->hwaddr_len = ETHARP_HWADDR_LEN;
47 return ERR_OK;
48 }
49
50 static void
test_netif_add(void)51 test_netif_add(void)
52 {
53 IP4_ADDR(&test_gw, 192,168,0,1);
54 IP4_ADDR(&test_ipaddr, 192,168,0,1);
55 IP4_ADDR(&test_netmask, 255,255,0,0);
56
57 fail_unless(netif_default == NULL);
58 netif_add(&test_netif, &test_ipaddr, &test_netmask, &test_gw,
59 NULL, test_netif_init, NULL);
60 netif_set_default(&test_netif);
61 netif_set_up(&test_netif);
62 }
63
64 static void
test_netif_remove(void)65 test_netif_remove(void)
66 {
67 if (netif_default == &test_netif) {
68 netif_remove(&test_netif);
69 }
70 }
71
72 /* Helper functions */
73 static void
create_ip4_input_fragment(u16_t ip_id,u16_t start,u16_t len,int last)74 create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last)
75 {
76 struct pbuf *p;
77 struct netif *input_netif = netif_list; /* just use any netif */
78 fail_unless((start & 7) == 0);
79 fail_unless(((len & 7) == 0) || last);
80 fail_unless(input_netif != NULL);
81
82 p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM);
83 fail_unless(p != NULL);
84 if (p != NULL) {
85 err_t err;
86 struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
87 IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4);
88 IPH_TOS_SET(iphdr, 0);
89 IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
90 IPH_ID_SET(iphdr, lwip_htons(ip_id));
91 if (last) {
92 IPH_OFFSET_SET(iphdr, lwip_htons(start / 8));
93 } else {
94 IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF));
95 }
96 IPH_TTL_SET(iphdr, 5);
97 IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
98 IPH_CHKSUM_SET(iphdr, 0);
99 ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif));
100 iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1);
101 ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif));
102 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr)));
103
104 err = ip4_input(p, input_netif);
105 if (err != ERR_OK) {
106 pbuf_free(p);
107 }
108 fail_unless(err == ERR_OK);
109 }
110 }
111
arpless_output(struct netif * netif,struct pbuf * p,const ip4_addr_t * ipaddr)112 static err_t arpless_output(struct netif *netif, struct pbuf *p,
113 const ip4_addr_t *ipaddr) {
114 LWIP_UNUSED_ARG(ipaddr);
115 return netif->linkoutput(netif, p);
116 }
117
118 /* Setups/teardown functions */
119
120 static void
ip4_setup(void)121 ip4_setup(void)
122 {
123 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
124 }
125
126 static void
ip4_teardown(void)127 ip4_teardown(void)
128 {
129 if (netif_list->loop_first != NULL) {
130 pbuf_free(netif_list->loop_first);
131 netif_list->loop_first = NULL;
132 }
133 netif_list->loop_last = NULL;
134 /* poll until all memory is released... */
135 tcpip_thread_poll_one();
136 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
137 test_netif_remove();
138 netif_set_up(netif_get_loopif());
139 }
140
141 /* Test functions */
START_TEST(test_ip4_frag)142 START_TEST(test_ip4_frag)
143 {
144 struct pbuf *data = pbuf_alloc(PBUF_IP, 8000, PBUF_RAM);
145 ip_addr_t peer_ip = IPADDR4_INIT_BYTES(192,168,0,5);
146 err_t err;
147 LWIP_UNUSED_ARG(_i);
148
149 linkoutput_ctr = 0;
150
151 /* Verify that 8000 byte payload is split into six packets */
152 fail_unless(data != NULL);
153 test_netif_add();
154 test_netif.output = arpless_output;
155 err = ip4_output_if_src(data, &test_ipaddr, ip_2_ip4(&peer_ip),
156 16, 0, IP_PROTO_UDP, &test_netif);
157 fail_unless(err == ERR_OK);
158 fail_unless(linkoutput_ctr == 6);
159 fail_unless(linkoutput_byte_ctr == (8000 + (6 * IP_HLEN)));
160 pbuf_free(data);
161 test_netif_remove();
162 }
163 END_TEST
164
START_TEST(test_ip4_reass)165 START_TEST(test_ip4_reass)
166 {
167 const u16_t ip_id = 128;
168 LWIP_UNUSED_ARG(_i);
169
170 memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
171
172 create_ip4_input_fragment(ip_id, 8*200, 200, 1);
173 fail_unless(lwip_stats.ip_frag.recv == 1);
174 fail_unless(lwip_stats.ip_frag.err == 0);
175 fail_unless(lwip_stats.ip_frag.memerr == 0);
176 fail_unless(lwip_stats.ip_frag.drop == 0);
177 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
178
179 create_ip4_input_fragment(ip_id, 0*200, 200, 0);
180 fail_unless(lwip_stats.ip_frag.recv == 2);
181 fail_unless(lwip_stats.ip_frag.err == 0);
182 fail_unless(lwip_stats.ip_frag.memerr == 0);
183 fail_unless(lwip_stats.ip_frag.drop == 0);
184 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
185
186 create_ip4_input_fragment(ip_id, 1*200, 200, 0);
187 fail_unless(lwip_stats.ip_frag.recv == 3);
188 fail_unless(lwip_stats.ip_frag.err == 0);
189 fail_unless(lwip_stats.ip_frag.memerr == 0);
190 fail_unless(lwip_stats.ip_frag.drop == 0);
191 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
192
193 create_ip4_input_fragment(ip_id, 2*200, 200, 0);
194 fail_unless(lwip_stats.ip_frag.recv == 4);
195 fail_unless(lwip_stats.ip_frag.err == 0);
196 fail_unless(lwip_stats.ip_frag.memerr == 0);
197 fail_unless(lwip_stats.ip_frag.drop == 0);
198 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
199
200 create_ip4_input_fragment(ip_id, 3*200, 200, 0);
201 fail_unless(lwip_stats.ip_frag.recv == 5);
202 fail_unless(lwip_stats.ip_frag.err == 0);
203 fail_unless(lwip_stats.ip_frag.memerr == 0);
204 fail_unless(lwip_stats.ip_frag.drop == 0);
205 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
206
207 create_ip4_input_fragment(ip_id, 4*200, 200, 0);
208 fail_unless(lwip_stats.ip_frag.recv == 6);
209 fail_unless(lwip_stats.ip_frag.err == 0);
210 fail_unless(lwip_stats.ip_frag.memerr == 0);
211 fail_unless(lwip_stats.ip_frag.drop == 0);
212 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
213
214 create_ip4_input_fragment(ip_id, 7*200, 200, 0);
215 fail_unless(lwip_stats.ip_frag.recv == 7);
216 fail_unless(lwip_stats.ip_frag.err == 0);
217 fail_unless(lwip_stats.ip_frag.memerr == 0);
218 fail_unless(lwip_stats.ip_frag.drop == 0);
219 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
220
221 create_ip4_input_fragment(ip_id, 6*200, 200, 0);
222 fail_unless(lwip_stats.ip_frag.recv == 8);
223 fail_unless(lwip_stats.ip_frag.err == 0);
224 fail_unless(lwip_stats.ip_frag.memerr == 0);
225 fail_unless(lwip_stats.ip_frag.drop == 0);
226 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
227
228 create_ip4_input_fragment(ip_id, 5*200, 200, 0);
229 fail_unless(lwip_stats.ip_frag.recv == 9);
230 fail_unless(lwip_stats.ip_frag.err == 0);
231 fail_unless(lwip_stats.ip_frag.memerr == 0);
232 fail_unless(lwip_stats.ip_frag.drop == 0);
233 fail_unless(lwip_stats.mib2.ipreasmoks == 1);
234 }
235 END_TEST
236
237 /* packets to 127.0.0.1 shall not be sent out to netif_default */
START_TEST(test_127_0_0_1)238 START_TEST(test_127_0_0_1)
239 {
240 ip4_addr_t localhost;
241 struct pbuf* p;
242 LWIP_UNUSED_ARG(_i);
243
244 linkoutput_ctr = 0;
245
246 test_netif_add();
247 netif_set_down(netif_get_loopif());
248
249 IP4_ADDR(&localhost, 127, 0, 0, 1);
250 p = pbuf_alloc(PBUF_IP, 10, PBUF_POOL);
251
252 if(ip4_output(p, netif_ip4_addr(netif_default), &localhost, 0, 0, IP_PROTO_UDP) != ERR_OK) {
253 pbuf_free(p);
254 }
255 fail_unless(linkoutput_ctr == 0);
256 }
257 END_TEST
258
START_TEST(test_ip4addr_aton)259 START_TEST(test_ip4addr_aton)
260 {
261 ip4_addr_t ip_addr;
262
263 LWIP_UNUSED_ARG(_i);
264
265 fail_unless(ip4addr_aton("192.168.0.1", &ip_addr) == 1);
266 fail_unless(ip4addr_aton("192.168.0.0001", &ip_addr) == 1);
267 fail_unless(ip4addr_aton("192.168.0.zzz", &ip_addr) == 0);
268 fail_unless(ip4addr_aton("192.168.1", &ip_addr) == 1);
269 fail_unless(ip4addr_aton("192.168.0xd3", &ip_addr) == 1);
270 fail_unless(ip4addr_aton("192.168.0xz5", &ip_addr) == 0);
271 fail_unless(ip4addr_aton("192.168.095", &ip_addr) == 0);
272 }
273 END_TEST
274
275 /* Test for bug #59364 */
START_TEST(test_ip4_icmp_replylen_short)276 START_TEST(test_ip4_icmp_replylen_short)
277 {
278 /* IP packet to 192.168.0.1 using proto 0x22 and 1 byte payload */
279 const u8_t unknown_proto[] = {
280 0x45, 0x00, 0x00, 0x15, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
281 0x66, 0x41, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
282 0xaa };
283 struct pbuf *p;
284 const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
285 LWIP_UNUSED_ARG(_i);
286
287 linkoutput_ctr = 0;
288
289 test_netif_add();
290 test_netif.output = arpless_output;
291 p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
292 pbuf_take(p, unknown_proto, sizeof(unknown_proto));
293 fail_unless(ip4_input(p, &test_netif) == ERR_OK);
294
295 fail_unless(linkoutput_ctr == 1);
296 /* Verify outgoing ICMP packet has no extra data */
297 fail_unless(linkoutput_pkt_len == icmp_len + sizeof(unknown_proto));
298 fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, sizeof(unknown_proto)));
299 }
300 END_TEST
301
START_TEST(test_ip4_icmp_replylen_first_8)302 START_TEST(test_ip4_icmp_replylen_first_8)
303 {
304 /* IP packet to 192.168.0.1 using proto 0x22 and 11 bytes payload */
305 const u8_t unknown_proto[] = {
306 0x45, 0x00, 0x00, 0x1f, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
307 0x66, 0x37, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
308 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
309 0xaa };
310 struct pbuf *p;
311 const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
312 const int unreach_len = IP_HLEN + 8;
313 LWIP_UNUSED_ARG(_i);
314
315 linkoutput_ctr = 0;
316
317 test_netif_add();
318 test_netif.output = arpless_output;
319 p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
320 pbuf_take(p, unknown_proto, sizeof(unknown_proto));
321 fail_unless(ip4_input(p, &test_netif) == ERR_OK);
322
323 fail_unless(linkoutput_ctr == 1);
324 fail_unless(linkoutput_pkt_len == icmp_len + unreach_len);
325 fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, unreach_len));
326 }
327 END_TEST
328
329 /** Create the suite including all tests for this module */
330 Suite *
ip4_suite(void)331 ip4_suite(void)
332 {
333 testfunc tests[] = {
334 TESTFUNC(test_ip4_frag),
335 TESTFUNC(test_ip4_reass),
336 TESTFUNC(test_127_0_0_1),
337 TESTFUNC(test_ip4addr_aton),
338 TESTFUNC(test_ip4_icmp_replylen_short),
339 TESTFUNC(test_ip4_icmp_replylen_first_8),
340 };
341 return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
342 }
343