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 linkoutput_byte_ctr = 0;
151
152 /* Verify that 8000 byte payload is split into six packets */
153 fail_unless(data != NULL);
154 test_netif_add();
155 test_netif.output = arpless_output;
156 err = ip4_output_if_src(data, &test_ipaddr, ip_2_ip4(&peer_ip),
157 16, 0, IP_PROTO_UDP, &test_netif);
158 fail_unless(err == ERR_OK);
159 fail_unless(linkoutput_ctr == 6);
160 fail_unless(linkoutput_byte_ctr == (8000 + (6 * IP_HLEN)));
161 pbuf_free(data);
162 test_netif_remove();
163 }
164 END_TEST
165
START_TEST(test_ip4_reass)166 START_TEST(test_ip4_reass)
167 {
168 const u16_t ip_id = 128;
169 LWIP_UNUSED_ARG(_i);
170
171 memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
172
173 create_ip4_input_fragment(ip_id, 8*200, 200, 1);
174 fail_unless(lwip_stats.ip_frag.recv == 1);
175 fail_unless(lwip_stats.ip_frag.err == 0);
176 fail_unless(lwip_stats.ip_frag.memerr == 0);
177 fail_unless(lwip_stats.ip_frag.drop == 0);
178 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
179
180 create_ip4_input_fragment(ip_id, 0*200, 200, 0);
181 fail_unless(lwip_stats.ip_frag.recv == 2);
182 fail_unless(lwip_stats.ip_frag.err == 0);
183 fail_unless(lwip_stats.ip_frag.memerr == 0);
184 fail_unless(lwip_stats.ip_frag.drop == 0);
185 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
186
187 create_ip4_input_fragment(ip_id, 1*200, 200, 0);
188 fail_unless(lwip_stats.ip_frag.recv == 3);
189 fail_unless(lwip_stats.ip_frag.err == 0);
190 fail_unless(lwip_stats.ip_frag.memerr == 0);
191 fail_unless(lwip_stats.ip_frag.drop == 0);
192 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
193
194 create_ip4_input_fragment(ip_id, 2*200, 200, 0);
195 fail_unless(lwip_stats.ip_frag.recv == 4);
196 fail_unless(lwip_stats.ip_frag.err == 0);
197 fail_unless(lwip_stats.ip_frag.memerr == 0);
198 fail_unless(lwip_stats.ip_frag.drop == 0);
199 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
200
201 create_ip4_input_fragment(ip_id, 3*200, 200, 0);
202 fail_unless(lwip_stats.ip_frag.recv == 5);
203 fail_unless(lwip_stats.ip_frag.err == 0);
204 fail_unless(lwip_stats.ip_frag.memerr == 0);
205 fail_unless(lwip_stats.ip_frag.drop == 0);
206 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
207
208 create_ip4_input_fragment(ip_id, 4*200, 200, 0);
209 fail_unless(lwip_stats.ip_frag.recv == 6);
210 fail_unless(lwip_stats.ip_frag.err == 0);
211 fail_unless(lwip_stats.ip_frag.memerr == 0);
212 fail_unless(lwip_stats.ip_frag.drop == 0);
213 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
214
215 create_ip4_input_fragment(ip_id, 7*200, 200, 0);
216 fail_unless(lwip_stats.ip_frag.recv == 7);
217 fail_unless(lwip_stats.ip_frag.err == 0);
218 fail_unless(lwip_stats.ip_frag.memerr == 0);
219 fail_unless(lwip_stats.ip_frag.drop == 0);
220 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
221
222 create_ip4_input_fragment(ip_id, 6*200, 200, 0);
223 fail_unless(lwip_stats.ip_frag.recv == 8);
224 fail_unless(lwip_stats.ip_frag.err == 0);
225 fail_unless(lwip_stats.ip_frag.memerr == 0);
226 fail_unless(lwip_stats.ip_frag.drop == 0);
227 fail_unless(lwip_stats.mib2.ipreasmoks == 0);
228
229 create_ip4_input_fragment(ip_id, 5*200, 200, 0);
230 fail_unless(lwip_stats.ip_frag.recv == 9);
231 fail_unless(lwip_stats.ip_frag.err == 0);
232 fail_unless(lwip_stats.ip_frag.memerr == 0);
233 fail_unless(lwip_stats.ip_frag.drop == 0);
234 fail_unless(lwip_stats.mib2.ipreasmoks == 1);
235 }
236 END_TEST
237
238 /* packets to 127.0.0.1 shall not be sent out to netif_default */
START_TEST(test_127_0_0_1)239 START_TEST(test_127_0_0_1)
240 {
241 ip4_addr_t localhost;
242 struct pbuf* p;
243 LWIP_UNUSED_ARG(_i);
244
245 linkoutput_ctr = 0;
246
247 test_netif_add();
248 netif_set_down(netif_get_loopif());
249
250 IP4_ADDR(&localhost, 127, 0, 0, 1);
251 p = pbuf_alloc(PBUF_IP, 10, PBUF_POOL);
252
253 if(ip4_output(p, netif_ip4_addr(netif_default), &localhost, 0, 0, IP_PROTO_UDP) != ERR_OK) {
254 pbuf_free(p);
255 }
256 fail_unless(linkoutput_ctr == 0);
257 }
258 END_TEST
259
START_TEST(test_ip4addr_aton)260 START_TEST(test_ip4addr_aton)
261 {
262 ip4_addr_t ip_addr;
263
264 LWIP_UNUSED_ARG(_i);
265
266 fail_unless(ip4addr_aton("192.168.0.1", &ip_addr) == 1);
267 fail_unless(ip4addr_aton("192.168.0.0001", &ip_addr) == 1);
268 fail_unless(ip4addr_aton("192.168.0.zzz", &ip_addr) == 0);
269 fail_unless(ip4addr_aton("192.168.1", &ip_addr) == 1);
270 fail_unless(ip4addr_aton("192.168.0xd3", &ip_addr) == 1);
271 fail_unless(ip4addr_aton("192.168.0xz5", &ip_addr) == 0);
272 fail_unless(ip4addr_aton("192.168.095", &ip_addr) == 0);
273 }
274 END_TEST
275
276 /* Test for bug #59364 */
START_TEST(test_ip4_icmp_replylen_short)277 START_TEST(test_ip4_icmp_replylen_short)
278 {
279 /* IP packet to 192.168.0.1 using proto 0x22 and 1 byte payload */
280 const u8_t unknown_proto[] = {
281 0x45, 0x00, 0x00, 0x15, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
282 0x66, 0x41, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
283 0xaa };
284 struct pbuf *p;
285 const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
286 LWIP_UNUSED_ARG(_i);
287
288 linkoutput_ctr = 0;
289
290 test_netif_add();
291 test_netif.output = arpless_output;
292 p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
293 pbuf_take(p, unknown_proto, sizeof(unknown_proto));
294 fail_unless(ip4_input(p, &test_netif) == ERR_OK);
295
296 fail_unless(linkoutput_ctr == 1);
297 /* Verify outgoing ICMP packet has no extra data */
298 fail_unless(linkoutput_pkt_len == icmp_len + sizeof(unknown_proto));
299 fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, sizeof(unknown_proto)));
300 }
301 END_TEST
302
START_TEST(test_ip4_icmp_replylen_first_8)303 START_TEST(test_ip4_icmp_replylen_first_8)
304 {
305 /* IP packet to 192.168.0.1 using proto 0x22 and 11 bytes payload */
306 const u8_t unknown_proto[] = {
307 0x45, 0x00, 0x00, 0x1f, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
308 0x66, 0x37, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
309 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
310 0xaa };
311 struct pbuf *p;
312 const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
313 const int unreach_len = IP_HLEN + 8;
314 LWIP_UNUSED_ARG(_i);
315
316 linkoutput_ctr = 0;
317
318 test_netif_add();
319 test_netif.output = arpless_output;
320 p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
321 pbuf_take(p, unknown_proto, sizeof(unknown_proto));
322 fail_unless(ip4_input(p, &test_netif) == ERR_OK);
323
324 fail_unless(linkoutput_ctr == 1);
325 fail_unless(linkoutput_pkt_len == icmp_len + unreach_len);
326 fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, unreach_len));
327 }
328 END_TEST
329
330 /** Create the suite including all tests for this module */
331 Suite *
ip4_suite(void)332 ip4_suite(void)
333 {
334 testfunc tests[] = {
335 TESTFUNC(test_ip4_frag),
336 TESTFUNC(test_ip4_reass),
337 TESTFUNC(test_127_0_0_1),
338 TESTFUNC(test_ip4addr_aton),
339 TESTFUNC(test_ip4_icmp_replylen_short),
340 TESTFUNC(test_ip4_icmp_replylen_first_8),
341 };
342 return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
343 }
344