1 /* This NetX test concentrates on the ICMPv4 Error Message. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #include "nx_ip.h"
6 #include "nx_icmp.h"
7
8 #if defined (__PRODUCT_NETXDUO__) && !defined (NX_DISABLE_ICMPV4_ERROR_MESSAGE) && !defined(NX_DISABLE_IPV4)
9
10 #define DEMO_STACK_SIZE 2048
11
12
13 /* Define the ThreadX and NetX object control blocks... */
14
15 static TX_THREAD ntest_0;
16
17 static NX_PACKET_POOL pool_0;
18 static NX_IP ip_0;
19 static NX_IP ip_1;
20
21
22
23 /* Define the counters used in the test application... */
24
25 static ULONG error_counter;
26 static ULONG ip_0_icmp_counter;
27 static ULONG ip_1_icmp_counter;
28 static ULONG ip_1_icmp_error_message_counter;
29
30
31 /* Define thread prototypes. */
32
33 static void ntest_0_entry(ULONG thread_input);
34 extern void test_control_return(UINT status);
35 extern void _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
36 extern UINT (*packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
37 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
38 static VOID my_ipv4_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
39
40
41 /* Define what the initial system looks like. */
42
43 #ifdef CTEST
test_application_define(void * first_unused_memory)44 VOID test_application_define(void *first_unused_memory)
45 #else
46 void netx_icmp_send_error_message_test_application_define(void *first_unused_memory)
47 #endif
48 {
49
50 CHAR *pointer;
51 UINT status;
52
53
54 /* Setup the working pointer. */
55 pointer = (CHAR *) first_unused_memory;
56
57 /* Initialize the value. */
58 error_counter = 0;
59 ip_0_icmp_counter = 0;
60 ip_1_icmp_counter = 0;
61 ip_1_icmp_error_message_counter = 0;
62
63 /* Create the main thread. */
64 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
65 pointer, DEMO_STACK_SIZE,
66 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
67 pointer = pointer + DEMO_STACK_SIZE;
68
69 /* Initialize the NetX system. */
70 nx_system_initialize();
71
72 /* Create a packet pool. */
73 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 2048);
74 pointer = pointer + 2048;
75
76 if (status)
77 error_counter++;
78
79 /* Create an IP instance. */
80 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
81 pointer, 2048, 1);
82 pointer = pointer + 2048;
83
84 /* Create another IP instance. */
85 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
86 pointer, 2048, 2);
87 pointer = pointer + 2048;
88 if (status)
89 error_counter++;
90
91 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
92 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
93 pointer = pointer + 1024;
94 if (status)
95 error_counter++;
96
97 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
98 status = nx_arp_enable(&ip_1, (void *) pointer, 1024);
99 pointer = pointer + 1024;
100 if (status)
101 error_counter++;
102
103 /* Enable ICMP processing for IP 0 instances. */
104 status = nx_icmp_enable(&ip_0);
105
106 /* Check TCP enable status. */
107 if (status)
108 error_counter++;
109 }
110
111
112
113 /* Define the test threads. */
114
ntest_0_entry(ULONG thread_input)115 static void ntest_0_entry(ULONG thread_input)
116 {
117
118 UINT status;
119 NX_PACKET *my_packet;
120
121
122 /* Print out test information banner. */
123 printf("NetX Test: ICMP Send Error Message Test..............................");
124
125 /* Check for earlier error. */
126 if (error_counter)
127 {
128
129 printf("ERROR!\n");
130 test_control_return(1);
131 }
132
133 packet_process_callback = my_packet_process;
134
135 /* Test illegal length of NX_IP_OPTION_INTERNET_TIMESTAMP option by ping. */
136 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
137
138 /* Check the status. */
139 if ((status != NX_NO_RESPONSE) || (my_packet))
140 {
141
142 printf("ERROR!\n");
143 test_control_return(1);
144 }
145
146 /* Check the value. */
147 if ((ip_0_icmp_counter != 1) && (ip_1_icmp_counter != 0))
148 {
149
150 printf("ERROR!\n");
151 test_control_return(1);
152 }
153
154 /* Enable ICMP processing for IP 1 instances. */
155 status = nx_icmp_enable(&ip_1);
156
157 /* Check TCP enable status. */
158 if (status)
159 error_counter++;
160
161 /* Test illegal length of NX_IP_OPTION_INTERNET_TIMESTAMP option and destination address (255, 255, 255, 255) by ping. */
162 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
163
164 /* Check the status. */
165 if ((status != NX_NO_RESPONSE) || (my_packet))
166 {
167
168 printf("ERROR!\n");
169 test_control_return(1);
170 }
171
172 /* Check the value. */
173 if ((ip_0_icmp_counter != 2) && (ip_1_icmp_counter != 0))
174 {
175
176 printf("ERROR!\n");
177 test_control_return(1);
178 }
179
180 /* Test illegal length of NX_IP_OPTION_INTERNET_TIMESTAMP option and non-initial fragment by ping. */
181 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
182
183 /* Check the status. */
184 if ((status != NX_NO_RESPONSE) || (my_packet))
185 {
186
187 printf("ERROR!\n");
188 test_control_return(1);
189 }
190
191 /* Check the value. */
192 if ((ip_0_icmp_counter != 3) && (ip_1_icmp_counter != 0))
193 {
194
195 printf("ERROR!\n");
196 test_control_return(1);
197 }
198
199 /* Set my function. */
200 ip_1.nx_ipv4_packet_receive = my_ipv4_packet_receive;
201
202 /* Test illegal length of NX_IP_OPTION_INTERNET_TIMESTAMP option by ping. */
203 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
204
205 /* Check the status. */
206 if ((status != NX_NO_RESPONSE) || (my_packet))
207 {
208
209 printf("ERROR!\n");
210 test_control_return(1);
211 }
212
213 /* Check the value. */
214 if ((ip_0_icmp_counter != 4) && (ip_1_icmp_counter != 0))
215 {
216
217 printf("ERROR!\n");
218 test_control_return(1);
219 }
220
221 #ifndef NX_ENABLE_SOURCE_ADDRESS_CHECK
222 /* Test illegal length of NX_IP_OPTION_INTERNET_TIMESTAMP option and multicast address by ping. */
223 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
224
225 /* Check the status. */
226 if ((status != NX_NO_RESPONSE) || (my_packet))
227 {
228
229 printf("ERROR!\n");
230 test_control_return(1);
231 }
232
233 /* Check the value. */
234 if ((ip_0_icmp_counter != 5) && (ip_1_icmp_counter != 0))
235 {
236
237 printf("ERROR!\n");
238 test_control_return(1);
239 }
240 #endif
241
242 /* Test unknown protocol. */
243 status = nx_icmp_ping(&ip_0, IP_ADDRESS(1, 2, 3, 5), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, 1 * NX_IP_PERIODIC_RATE);
244
245 /* Check the status. */
246 if ((status != NX_NO_RESPONSE) || (my_packet))
247 {
248
249 printf("ERROR!\n");
250 test_control_return(1);
251 }
252
253 #ifndef NX_ENABLE_SOURCE_ADDRESS_CHECK
254 /* Check the value. */
255 if ((ip_0_icmp_counter != 6) && (ip_1_icmp_counter != 1))
256 #else
257 /* Check the value. */
258 if ((ip_0_icmp_counter != 5) && (ip_1_icmp_counter != 1))
259 #endif
260 {
261
262 printf("ERROR!\n");
263 test_control_return(1);
264 }
265
266 printf("SUCCESS!\n");
267 test_control_return(0);
268 }
269
my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)270 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
271 {
272
273 NX_IPV4_HEADER *ip_header_ptr;
274 NX_ICMP_HEADER *icmp_header_ptr;
275 ULONG ip_header_length;
276 ULONG protocol;
277 ULONG checksum;
278 ULONG val;
279 ULONG offset = 0;
280 ULONG shift;
281 ULONG message_word;
282
283 /* Get the IP header pointer. */
284 ip_header_ptr = (NX_IPV4_HEADER*)(packet_ptr -> nx_packet_prepend_ptr);
285
286 /* Get IP header. */
287 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
288 protocol = (ip_header_ptr -> nx_ip_header_word_2 >> 16) & 0xFF;
289 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
290
291 /* Only process ICMP message. */
292 if (protocol != NX_PROTOCOL_ICMP)
293 return (NX_TRUE);
294
295 /* Modify the ICMP packet from ip_0 instance. */
296 if(ip_ptr == &ip_0)
297 {
298
299 /* Update the icmp_counter. */
300 ip_0_icmp_counter++;
301
302 /* Get the IP header pointer. */
303 ip_header_ptr = (NX_IPV4_HEADER*)(packet_ptr -> nx_packet_prepend_ptr);
304
305 /* Calculate the IPv4 option length. */
306 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_0);
307 ip_header_length = ((ip_header_ptr -> nx_ip_header_word_0 & NX_IP_LENGTH_MASK) >> 24) * sizeof(ULONG);
308
309 /* Get ICMP header. */
310 icmp_header_ptr = (NX_ICMP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr + ip_header_length);
311
312 /* Add the illegal length 7 for NX_IP_OPTION_INTERNET_TIMESTAMP option. */
313 if ((ip_0_icmp_counter == 1) || (ip_0_icmp_counter == 2) ||
314 #ifndef NX_ENABLE_SOURCE_ADDRESS_CHECK
315 (ip_0_icmp_counter == 3) || (ip_0_icmp_counter == 4) || (ip_0_icmp_counter == 5))
316 #else
317 (ip_0_icmp_counter == 3) || (ip_0_icmp_counter == 4))
318 #endif
319 {
320
321 /* Move the data to add the option. */
322 offset = 12;
323 shift = packet_ptr -> nx_packet_length - ip_header_length;
324 memmove(((UCHAR *)(icmp_header_ptr)) + offset, icmp_header_ptr, shift);
325
326 /* Clear memory. */
327 memset(&message_word, 0, sizeof(ULONG));
328
329 /* Add type, length, offset, overflw and flags. */
330 message_word = (ULONG)((NX_IP_OPTION_INTERNET_TIMESTAMP << 24) | (7 << 16) | (5 << 8) );
331
332 /* Adjust for endianness. */
333 NX_CHANGE_ULONG_ENDIAN(message_word);
334
335 /* Add type, length, offset, overflw and flags. */
336 memcpy(icmp_header_ptr, &message_word, sizeof(ULONG));
337
338 /* Clear the time stamp value. */
339 memset(((UCHAR *)(icmp_header_ptr)) + sizeof(ULONG), 0 , offset - sizeof(ULONG));
340 }
341
342 /* Modified the destination address to 255.255.255.255. */
343 if (ip_0_icmp_counter == 2)
344 {
345
346 /* Modified the destination address to 255.255.255.255. */
347 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
348 ip_header_ptr -> nx_ip_header_destination_ip = IP_ADDRESS(255, 255, 255, 255);
349 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip);
350 }
351
352 /* Modified the fragment offset. */
353 if (ip_0_icmp_counter == 3)
354 {
355
356 /* Modified the destination address to 255.255.255.255. */
357 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
358 ip_header_ptr -> nx_ip_header_word_1 |= 10;
359 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_1);
360 }
361
362 #ifndef NX_ENABLE_SOURCE_ADDRESS_CHECK
363 /* Modified the destination address to 255.255.255.255. */
364 if (ip_0_icmp_counter == 5)
365 {
366
367 /* Modified the source address to 224.0.0.251. */
368 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
369 ip_header_ptr -> nx_ip_header_source_ip = IP_ADDRESS(224,0,0,251);
370 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip);
371 }
372 #endif
373
374 /* Modified the protocol as unknown. */
375 #ifndef NX_ENABLE_SOURCE_ADDRESS_CHECK
376 if (ip_0_icmp_counter == 6)
377 #else
378 if (ip_0_icmp_counter == 5)
379 #endif
380 {
381
382 /* Set the protocol as unkown protocol, ip_1 should send the icmp unreachable meesage. */;
383 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
384 ip_header_ptr -> nx_ip_header_word_2 |= 0x00FF0000;
385 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2);
386 }
387
388 /* Update the header IP length and total length. */
389 ip_header_length += offset;
390 packet_ptr -> nx_packet_append_ptr += offset;
391 packet_ptr -> nx_packet_length += offset;
392
393 /* Rebuild the first 32-bit word of the IP header. */
394 ip_header_ptr -> nx_ip_header_word_0 = (ULONG)((NX_IP_VERSION_V4 << 28) |
395 ((ip_header_length/sizeof(ULONG)) << 24) |
396 NX_IP_NORMAL |
397 (0xFFFF & packet_ptr -> nx_packet_length));
398
399 /* Endian swapping logic. */
400 NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_0);
401
402 /* Clear the checksum . */
403 ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 & 0x0000FFFF;
404
405 /* Calculate the checksum. */
406 checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4,
407 /* Length is the size of IP header, including options */
408 (UINT)(ip_header_length),
409 /* IPv4 header checksum does not use src/dest addresses */
410 NULL, NULL);
411
412 val = (ULONG)(~checksum);
413 val = val & NX_LOWER_16_MASK;
414
415 /* Convert to network byte order. */
416 NX_CHANGE_ULONG_ENDIAN(val);
417
418 /* Now store the checksum in the IP header. */
419 ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 | val;
420 }
421
422 /* Check the ICMP packet from ip_1 instance. */
423 if(ip_ptr == &ip_1)
424 {
425
426 /* Update the icmp_counter. */
427 ip_1_icmp_counter++;
428 }
429
430 return NX_TRUE;
431 }
432
my_ipv4_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)433 VOID my_ipv4_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
434 {
435 NX_PACKET *my_packet[20];
436 UINT packet_counter;
437 UINT i;
438
439 /* Record the counter. */
440 packet_counter = ip_ptr -> nx_ip_default_packet_pool -> nx_packet_pool_available;
441
442 /* Loop to allocate the packet. */
443 for (i = 0; i < packet_counter; i ++)
444 nx_packet_allocate(ip_ptr -> nx_ip_default_packet_pool, &my_packet[i], 0, NX_NO_WAIT);
445
446 /* Receive the packet. */
447 _nx_ipv4_packet_receive(ip_ptr, packet_ptr);
448
449 /* Loop to release the packet. */
450 for (i = packet_counter; i > 0; i --)
451 nx_packet_release(my_packet[i - 1]);
452
453 /* Reset the function. */
454 ip_1.nx_ipv4_packet_receive = _nx_ipv4_packet_receive;
455 }
456
457 #else
458
459 extern void test_control_return(UINT status);
460
461 #ifdef CTEST
test_application_define(void * first_unused_memory)462 VOID test_application_define(void *first_unused_memory)
463 #else
464 void netx_icmp_send_error_message_test_application_define(void *first_unused_memory)
465 #endif
466 {
467 printf("NetX Test: ICMP Send Error Message Test..............................N/A\n");
468 test_control_return(3);
469 }
470 #endif
471