• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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