1 /* This NetX test concentrates on the basic BSD RAW blocking operation.  */
2 
3 #include   "tx_api.h"
4 #include   "nx_api.h"
5 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
6 #ifdef NX_BSD_ENABLE
7 #include   "nxd_bsd.h"
8 #include   "nx_icmpv6.h"
9 #define     DEMO_STACK_SIZE         8192
10 
11 
12 /* Define the ThreadX and NetX object control blocks...  */
13 
14 static TX_THREAD               ntest_0;
15 static TX_THREAD               ntest_1;
16 
17 static NX_PACKET_POOL          pool_0;
18 static NX_IP                   ip_0;
19 static NX_IP                   ip_1;
20 static ULONG                   bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
21 #define BSD_THREAD_PRIORITY    2
22 #define NUM_CLIENTS            20
23 /* Define the counters used in the test application...  */
24 
25 static ULONG                   error_counter;
26 
27 
28 /* Define thread prototypes.  */
29 
30 static void    ntest_0_entry(ULONG thread_input);
31 static void    ntest_1_entry(ULONG thread_input);
32 extern void    test_control_return(UINT status);
33 extern void    _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
34 static void    validate_bsd_structure(void);
35 #ifdef FEATURE_NX_IPV6
36 static NXD_ADDRESS ipv6_address_ip0;
37 static NXD_ADDRESS ipv6_address_ip1;
38 #endif /* FEATURE_NX_IPV6 */
39 static char *requests[4] = {"Request1", "Request2", "Request3", "Request4"};
40 static char *response[4] = {"Response1", "Response2", "Response3", "Response4"};
41 extern UINT    _nxd_ip_raw_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr,  NXD_ADDRESS *destination_ip, ULONG protocol, UINT ttl, ULONG tos);
42 /* Define what the initial system looks like.  */
43 
44 #ifdef CTEST
test_application_define(void * first_unused_memory)45 VOID test_application_define(void *first_unused_memory)
46 #else
47 void    netx_bsd_raw_basic_blocking_test_application_define(void *first_unused_memory)
48 #endif
49 {
50 
51 CHAR    *pointer;
52 UINT    status;
53 
54 
55     /* Setup the working pointer.  */
56     pointer =  (CHAR *) first_unused_memory;
57 
58     error_counter =  0;
59 
60     /* Create the main thread.  */
61     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
62                      pointer, DEMO_STACK_SIZE,
63                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
64 
65     pointer =  pointer + DEMO_STACK_SIZE;
66 
67     /* Create the main thread.  */
68     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
69                      pointer, DEMO_STACK_SIZE,
70                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
71 
72     pointer =  pointer + DEMO_STACK_SIZE;
73 
74 
75     /* Initialize the NetX system.  */
76     nx_system_initialize();
77 
78     /* Create a packet pool.  */
79     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2);
80     pointer = pointer + (256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 2;
81 
82     if (status)
83         error_counter++;
84 
85     /* Create an IP instance.  */
86     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
87                     pointer, 2048, 1);
88     pointer =  pointer + 2048;
89 
90     /* Create another IP instance.  */
91     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
92                     pointer, 2048, 2);
93     pointer =  pointer + 2048;
94     if (status)
95         error_counter++;
96 
97     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
98     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
99     pointer = pointer + 1024;
100     if (status)
101         error_counter++;
102 
103     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
104     status  =  nx_arp_enable(&ip_1, (void *) pointer, 1024);
105     pointer = pointer + 1024;
106     if (status)
107         error_counter++;
108 
109     /* Enable raw processing for both IP instances.  */
110     status += nx_ip_raw_packet_enable(&ip_0);
111     status += nx_ip_raw_packet_enable(&ip_1);
112 
113     /* Enable BSD */
114     status += bsd_initialize(&ip_0, &pool_0, (CHAR*)&bsd_thread_area[0], sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
115 
116     /* Check RAW enable and BSD init status.  */
117     if (status)
118         error_counter++;
119 }
120 
test_raw_server_ipv4(void)121 static void test_raw_server_ipv4(void)
122 {
123 int                sockfd;
124 struct sockaddr_in remote_addr;
125 struct sockaddr_ll sock_addr;
126 int                ret;
127 char               buf[30];
128 int                addrlen;
129 
130 
131     sockfd = socket(AF_INET, SOCK_RAW, 100);
132     if(sockfd < 0)
133         error_counter++;
134 
135     /* Receive data from the client. */
136     addrlen = sizeof(remote_addr);
137     ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&remote_addr, &addrlen);
138     if(ret <= 0)
139         error_counter++;
140 
141     if(addrlen != sizeof(struct sockaddr_in))
142         error_counter++;
143 
144     if((remote_addr.sin_family != AF_INET) ||
145        (remote_addr.sin_addr.s_addr != htonl(IP_ADDRESS(1,2,3,5))))
146         error_counter++;
147 
148     /* Validate the data. */
149     if((ret != (int)(strlen(requests[0]) + 20)) || strncmp((buf + 20), requests[0], (ret - 20)))
150         error_counter++;
151 
152     /* Send a response back. */
153     ret = sendto(sockfd, response[0], strlen(response[0]), 0, (struct sockaddr*)&remote_addr, addrlen);
154     if(ret != (int)strlen(response[0]))
155         error_counter++;
156 
157 
158     /* Close downt he socket. */
159     ret = soc_close(sockfd);
160     if(ret < 0)
161         error_counter++;
162 
163 #ifdef NX_BSD_RAW_SUPPORT
164     /* Test raw packet type. */
165     sockfd = socket(AF_PACKET, SOCK_RAW, 200);
166     if(sockfd < 0)
167         error_counter++;
168 
169     sock_addr.sll_family = AF_PACKET;
170     sock_addr.sll_ifindex = 0;
171     ret = sendto(sockfd, response[0], strlen(response[0]), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
172     if(ret != (int)strlen(response[0]))
173         error_counter++;
174 
175     /* Close downt he socket. */
176     ret = soc_close(sockfd);
177     if(ret < 0)
178         error_counter++;
179 #endif
180 
181 
182     /* Give the reciever a chance to receive the raw data. */
183     tx_thread_sleep(2);
184 
185 }
186 
187 #ifdef FEATURE_NX_IPV6
test_raw_server_ipv6(void)188 static void test_raw_server_ipv6(void)
189 {
190 int                 sockfd;
191 struct sockaddr_in6 remote_addr;
192 int                 ret;
193 char                buf[50];
194 int                 addrlen;
195 
196 
197     sockfd = socket(AF_INET6, SOCK_RAW, 100);
198     if(sockfd < 0)
199         error_counter++;
200 
201     /* Receive data from the client. */
202     addrlen = sizeof(remote_addr);
203     ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&remote_addr, &addrlen);
204     if(ret <= 0)
205         error_counter++;
206 
207     if(addrlen != sizeof(struct sockaddr_in6))
208         error_counter++;
209 
210     if((remote_addr.sin6_family != AF_INET6) ||
211        (remote_addr.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip1.nxd_ip_address.v6[0])) ||
212        (remote_addr.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip1.nxd_ip_address.v6[1])) ||
213        (remote_addr.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip1.nxd_ip_address.v6[2])) ||
214        (remote_addr.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip1.nxd_ip_address.v6[3])))
215         error_counter++;
216 
217 
218     /* Validate the data. */
219     if((ret != (INT)(strlen(requests[0]) )) || strncmp((buf ), requests[0], ret ))
220         error_counter++;
221 
222     /* Send a response back. */
223     ret = sendto(sockfd, response[0], strlen(response[0]), 0, (struct sockaddr*)&remote_addr, addrlen);
224     if(ret != (INT)strlen(response[0]))
225         error_counter++;
226 
227 
228     /* Close downt he socket. */
229     ret = soc_close(sockfd);
230     if(ret < 0)
231         error_counter++;
232 
233     /* Give the reciever a chance to receive the raw data. */
234     tx_thread_sleep(2);
235 
236 }
237 
238 #endif
239 
240 
241 /* Define the test threads.  */
ntest_0_entry(ULONG thread_input)242 static void    ntest_0_entry(ULONG thread_input)
243 {
244 #ifdef FEATURE_NX_IPV6
245 UINT status;
246 char mac_ip0[6];
247 char mac_ip1[6];
248 #endif
249     printf("NetX Test:   Basic BSD Raw Blocking Test...................");
250 
251     /* Check for earlier error.  */
252     if (error_counter)
253     {
254 
255         printf("ERROR!\n");
256         test_control_return(1);
257     }
258 #ifdef FEATURE_NX_IPV6
259     /* First set up IPv6 addresses. */
260     ipv6_address_ip0.nxd_ip_version = NX_IP_VERSION_V6;
261     ipv6_address_ip0.nxd_ip_address.v6[0] = 0xfe800000;
262     ipv6_address_ip0.nxd_ip_address.v6[1] = 0x00000000;
263     ipv6_address_ip0.nxd_ip_address.v6[2] = 0x021122ff;
264     ipv6_address_ip0.nxd_ip_address.v6[3] = 0xfe334456;
265 
266     ipv6_address_ip1.nxd_ip_version = NX_IP_VERSION_V6;
267     ipv6_address_ip1.nxd_ip_address.v6[0] = 0xfe800000;
268     ipv6_address_ip1.nxd_ip_address.v6[1] = 0x00000000;
269     ipv6_address_ip1.nxd_ip_address.v6[2] = 0x021122ff;
270     ipv6_address_ip1.nxd_ip_address.v6[3] = 0xfe334457;
271 
272     status = nxd_ipv6_address_set(&ip_0, 0, &ipv6_address_ip0, 64, NX_NULL);
273     status += nxd_ipv6_address_set(&ip_1, 0, &ipv6_address_ip1, 64, NX_NULL);
274 
275     status += nxd_ipv6_enable(&ip_0);
276     status += nxd_ipv6_enable(&ip_1);
277 
278     mac_ip0[0] = ip_0.nx_ip_interface[0].nx_interface_physical_address_msw >> 8;
279     mac_ip0[1] = ip_0.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
280     mac_ip0[2] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
281     mac_ip0[3] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
282     mac_ip0[4] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
283     mac_ip0[5] = ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
284 
285     mac_ip1[0] = ip_1.nx_ip_interface[0].nx_interface_physical_address_msw >> 8;
286     mac_ip1[1] = ip_1.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
287     mac_ip1[2] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
288     mac_ip1[3] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
289     mac_ip1[4] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
290     mac_ip1[5] = ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
291 
292     status += nxd_nd_cache_entry_set(&ip_0, ipv6_address_ip1.nxd_ip_address.v6, 0,  mac_ip1);
293     status += nxd_nd_cache_entry_set(&ip_1, ipv6_address_ip0.nxd_ip_address.v6, 0,  mac_ip0);
294 
295     if(status)
296         error_counter++;
297 #endif
298     test_raw_server_ipv4();
299 
300     /* Now open another socket and attempt to connect to the correct remote
301        host but an unexpected port so we expect an unsuccessful connections. */
302 #if 0
303     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
304     if(sockfd < 0)
305         error_counter++;
306 #endif
307 
308     /* Allow the stateless autoaddress configuration/DAD to finish */
309     tx_thread_sleep(3);
310 
311 #ifdef FEATURE_NX_IPV6
312     test_raw_server_ipv6();
313 #endif
314 
315     validate_bsd_structure();
316     tx_thread_sleep(2);
317     if(error_counter)
318         printf("ERROR!\n");
319     else
320         printf("SUCCESS!\n");
321 
322     if(error_counter)
323         test_control_return(1);
324 
325     test_control_return(0);
326 }
327 
ntest_1_entry(ULONG thread_input)328 static void    ntest_1_entry(ULONG thread_input)
329 {
330 
331 UINT            status;
332 NX_PACKET       *packet_ptr;
333 ULONG           actual_status;
334 NXD_ADDRESS     dest_addr;
335 
336 
337 
338     /* Ensure the IP instance has been initialized.  */
339     status =  nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, 1 * NX_IP_PERIODIC_RATE);
340 
341     /* Check status...  */
342     if (status != NX_SUCCESS)
343     {
344 
345         printf("ERROR!\n");
346         test_control_return(3);
347     }
348 
349     /* Allocate a packet. */
350     status = nx_packet_allocate(&pool_0, &packet_ptr, NX_IP_PACKET, NX_WAIT_FOREVER);
351     if (status)
352         error_counter++;
353 
354     /* Fill in the packet with data */
355     memcpy(packet_ptr -> nx_packet_prepend_ptr, requests[0], strlen(requests[0]));
356 
357     packet_ptr -> nx_packet_length = strlen(requests[0]);
358     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
359 
360     /* Send a RAW packet */
361     dest_addr.nxd_ip_version = NX_IP_VERSION_V4;
362     dest_addr.nxd_ip_address.v4 = IP_ADDRESS(1,2,3,4);
363     status =  _nxd_ip_raw_packet_send(&ip_1, packet_ptr, &dest_addr, 100, 128, 0);
364     if(status)
365         error_counter++;
366 
367     error_counter++;
368     tx_thread_sleep(1);
369     /* Ready to reaceive a message */
370     status = nx_ip_raw_packet_receive(&ip_1, &packet_ptr, NX_IP_PERIODIC_RATE);
371     if(status)
372         error_counter++;
373 
374 
375     /* Validate the content. */
376     if(packet_ptr -> nx_packet_length != strlen(response[0]))
377         error_counter++;
378     else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[0], strlen(response[0])))
379         error_counter++;
380     else
381         error_counter--;
382 
383 #ifdef FEATURE_NX_IPV6
384     /* Test IPv6 */
385     tx_thread_sleep(5);
386     /* Allocate a packet. */
387     status = nx_packet_allocate(&pool_0, &packet_ptr, NX_IP_PACKET, NX_WAIT_FOREVER);
388     if (status)
389         error_counter++;
390 
391     /* Fill in the packet with data */
392     memcpy(packet_ptr -> nx_packet_prepend_ptr, requests[0], strlen(requests[0]));
393 
394     packet_ptr -> nx_packet_length = strlen(requests[0]);
395     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length;
396 
397     status =  _nxd_ip_raw_packet_send(&ip_1, packet_ptr, &ipv6_address_ip0, 100, 128, 0);
398     if(status)
399         error_counter++;
400 
401     error_counter++;
402     tx_thread_sleep(1);
403     /* Ready to reaceive a message */
404     status = nx_ip_raw_packet_receive(&ip_1, &packet_ptr, NX_IP_PERIODIC_RATE);
405     if(status)
406         error_counter++;
407 
408     /* Validate the content. */
409     if(packet_ptr -> nx_packet_length != strlen(response[0]))
410         error_counter++;
411     else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[0], strlen(response[0])))
412         error_counter++;
413     else
414         error_counter--;
415 
416 #endif
417 }
418 
419 extern NX_BSD_SOCKET  nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
420 extern TX_BLOCK_POOL nx_bsd_socket_block_pool;
validate_bsd_structure(void)421 static void validate_bsd_structure(void)
422 {
423 int i;
424     /* Make sure every BSD socket should be free by now. */
425 
426     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
427     {
428         if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)
429         {
430             error_counter++;
431         }
432 
433         if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket ||
434            nx_bsd_socket_array[i].nx_bsd_socket_udp_socket)
435         {
436             error_counter++;
437         }
438     }
439 
440     /* Make sure all the NX SOCKET control blocks are released. */
441     if(nx_bsd_socket_block_pool.tx_block_pool_available !=
442        nx_bsd_socket_block_pool.tx_block_pool_total)
443     {
444         error_counter++;
445     }
446 
447     /* Make sure all the sockets are released */
448     if(ip_0.nx_ip_tcp_created_sockets_ptr ||
449        ip_0.nx_ip_udp_created_sockets_ptr)
450     {
451         error_counter++;
452         return;
453     }
454 
455 }
456 
457 #endif /* NX_BSD_ENABLE */
458 
459 #else /* __PRODUCT_NETXDUO__ */
460 
461 extern void    test_control_return(UINT status);
462 #ifdef CTEST
test_application_define(void * first_unused_memory)463 VOID test_application_define(void *first_unused_memory)
464 #else
465 void    netx_bsd_raw_basic_blocking_test_application_define(void *first_unused_memory)
466 #endif
467 {
468     printf("NetX Test:   Basic BSD Raw Blocking Test...................N/A\n");
469     test_control_return(3);
470 }
471 #endif /* __PRODUCT_NETXDUO__ */
472 
473