1 /* This is a small demo of the NetX Duo DHCPv6 Client and Server for the high-performance
2 NetX Duo stack. */
3
4 #include <stdio.h>
5 #include "tx_api.h"
6 #include "nx_api.h"
7 extern void test_control_return(UINT status);
8
9 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_FRAGMENTATION)
10 #include "nxd_dhcpv6_client.h"
11 #include "nxd_dhcpv6_server.h"
12
13 #define DEMO_STACK_SIZE 2048
14 #define NX_DHCPV6_THREAD_STACK_SIZE 2048
15 #define NX_PACKET_SIZE 1536
16 #define NX_PACKET_POOL_SIZE (NX_PACKET_SIZE * 8)
17
18 /* Define the ThreadX and NetX object control blocks... */
19
20 static NX_PACKET_POOL pool_0;
21 static TX_THREAD thread_client;
22 static TX_THREAD thread_server;
23 static NX_IP client_ip;
24 static NX_IP server_ip;
25
26 /* Define the Client and Server instances. */
27
28 static NX_DHCPV6 dhcp_client;
29 static NX_DHCPV6_SERVER dhcp_server;
30
31 /* Define the error counter used in the demo application... */
32 static ULONG error_counter;
33 static CHAR *pointer;
34
35 static NXD_ADDRESS server_address;
36 static NXD_ADDRESS dns_ipv6_address;
37 static NXD_ADDRESS start_ipv6_address;
38 static NXD_ADDRESS end_ipv6_address;
39
40
41 /* Define thread prototypes. */
42
43 static void thread_client_entry(ULONG thread_input);
44 static void thread_server_entry(ULONG thread_input);
45 extern void _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
46
47
48 /* Define some DHCPv6 parameters. */
49
50 #define DHCPV6_IANA_ID 0xC0DEDBAD
51 #define DHCPV6_T1 NX_DHCPV6_INFINITE_LEASE
52 #define DHCPV6_T2 NX_DHCPV6_INFINITE_LEASE
53 #define NX_DHCPV6_REFERRED_LIFETIME NX_DHCPV6_INFINITE_LEASE
54 #define NX_DHCPV6_VALID_LIFETIME NX_DHCPV6_INFINITE_LEASE
55
56
57 /* Define what the initial system looks like. */
58
59 #ifdef CTEST
test_application_define(void * first_unused_memory)60 VOID test_application_define(void *first_unused_memory)
61 #else
62 void netx_dhcpv6_basic_test_application_define(void *first_unused_memory)
63 #endif
64 {
65
66 UINT status;
67
68 /* Setup the working pointer. */
69 pointer = (CHAR *) first_unused_memory;
70
71 /* Initialize the NetX system. */
72 nx_system_initialize();
73
74 /* Create the Client thread. */
75 status = tx_thread_create(&thread_client, "Client thread", thread_client_entry, 0,
76 pointer, DEMO_STACK_SIZE,
77 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
78
79 pointer = pointer + DEMO_STACK_SIZE;
80
81 /* Check for IP create errors. */
82 if (status)
83 {
84 error_counter++;
85 }
86
87 /* Create the Server thread. */
88 status = tx_thread_create(&thread_server, "Server thread", thread_server_entry, 0,
89 pointer, DEMO_STACK_SIZE,
90 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
91 pointer = pointer + DEMO_STACK_SIZE;
92
93 /* Check for IP create errors. */
94 if (status)
95 {
96 error_counter++;
97 }
98
99 /* Create a packet pool. */
100 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
101 pointer = pointer + NX_PACKET_POOL_SIZE;
102
103 /* Check for pool creation error. */
104 if (status)
105 error_counter++;
106
107 /* Create a Client IP instance. */
108 status = nx_ip_create(&client_ip, "Client IP", IP_ADDRESS(0, 0, 0, 0),
109 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
110 pointer, 2048, 1);
111
112 pointer = pointer + 2048;
113
114 /* Check for IP create errors. */
115 if (status)
116 {
117 error_counter++;
118 }
119
120 /* Create a Server IP instance. */
121 status = nx_ip_create(&server_ip, "Server IP", IP_ADDRESS(1, 2, 3, 4),
122 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
123 pointer, 2048, 1);
124
125 pointer = pointer + 2048;
126
127 /* Check for IP create errors. */
128 if (status)
129 {
130 error_counter++;
131 }
132
133 /* Enable UDP traffic for sending DHCPv6 messages. */
134 status = nx_udp_enable(&client_ip);
135 status += nx_udp_enable(&server_ip);
136
137 /* Check for UDP enable errors. */
138 if (status)
139 {
140 error_counter++;
141 }
142
143 /* Enable the IPv6 services. */
144 status = nxd_ipv6_enable(&client_ip);
145 status += nxd_ipv6_enable(&server_ip);
146
147 /* Check for IPv6 enable errors. */
148 if (status)
149 {
150 error_counter++;
151 }
152
153 /* Enable the ICMPv6 services. */
154 status = nxd_icmp_enable(&client_ip);
155 status += nxd_icmp_enable(&server_ip);
156
157 /* Check for ICMP enable errors. */
158 if (status)
159 {
160 error_counter++;
161 }
162
163 /* Enable the fragment feature. */
164 status = nx_ip_fragment_enable(&client_ip);
165 status += nx_ip_fragment_enable(&server_ip);
166
167 /* Check for ICMP enable errors. */
168 if (status)
169 {
170 error_counter++;
171 }
172 }
173
174 /* Define the Client host application thread. */
175
thread_client_entry(ULONG thread_input)176 void thread_client_entry(ULONG thread_input)
177 {
178
179 UINT status;
180 NXD_ADDRESS ipv6_address;
181 NXD_ADDRESS dns_address;
182 ULONG prefix_length;
183 UINT interface_index;
184 ULONG T1, T2, preferred_lifetime, valid_lifetime;
185 UINT address_count;
186 UINT address_index;
187 NX_PACKET *my_packet;
188
189
190 /* Print out test information banner. */
191 printf("NetX Test: DHCPv6 Basic Test.........................................");
192
193 /* Check for earlier error. */
194 if(error_counter)
195 {
196 printf("ERROR!\n");
197 test_control_return(1);
198 }
199
200 /* Establish the link local address for the host. The RAM driver creates
201 a virtual MAC address of 0x1122334456. */
202 status = nxd_ipv6_address_set(&client_ip, 0, NX_NULL, 10, NULL);
203
204 /* Let NetX Duo and the network driver get initialized. Also give the server time to get set up. */
205 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
206
207 /* Create the DHCPv6 Client. */
208 status = nx_dhcpv6_client_create(&dhcp_client, &client_ip, "DHCPv6 Client", &pool_0, pointer, NX_DHCPV6_THREAD_STACK_SIZE,
209 NX_NULL, NX_NULL);
210 pointer = pointer + NX_DHCPV6_THREAD_STACK_SIZE;
211
212 /* Check for errors. */
213 if(status)
214 {
215 printf("ERROR!\n");
216 test_control_return(1);
217 }
218
219 /* Create a Link Layer Plus Time DUID for the DHCPv6 Client. Set time ID field
220 to NULL; the DHCPv6 Client API will supply one. */
221 status = nx_dhcpv6_create_client_duid(&dhcp_client, NX_DHCPV6_DUID_TYPE_LINK_TIME,
222 NX_DHCPV6_HW_TYPE_IEEE_802, 0);
223
224 /* Check for errors. */
225 if(status)
226 {
227 printf("ERROR!\n");
228 test_control_return(1);
229 }
230
231 /* Create the DHCPv6 client's Identity Association (IA-NA) now.
232
233 Note that if this host had already been assigned in IPv6 lease, it
234 would have to use the assigned T1 and T2 values in loading the DHCPv6
235 client with an IANA block.
236 */
237 status = nx_dhcpv6_create_client_iana(&dhcp_client, DHCPV6_IANA_ID, DHCPV6_T1, DHCPV6_T2);
238
239 /* Check for errors. */
240 if(status)
241 {
242 printf("ERROR!\n");
243 test_control_return(1);
244 }
245
246 /* Starting up the NetX DHCPv6 Client. */
247 status = nx_dhcpv6_start(&dhcp_client);
248
249 /* Check for errors. */
250 if(status)
251 {
252 printf("ERROR!\n");
253 test_control_return(1);
254 }
255
256 /* If the host also want to get the option message, set the list of desired options to enabled. */
257 nx_dhcpv6_request_option_timezone(&dhcp_client, NX_TRUE);
258 nx_dhcpv6_request_option_DNS_server(&dhcp_client, NX_TRUE);
259 nx_dhcpv6_request_option_time_server(&dhcp_client, NX_TRUE);
260 nx_dhcpv6_request_option_domain_name(&dhcp_client, NX_TRUE);
261
262 /* Now, the host send the solicit message to get the IPv6 address and other options from the DHCPv6 server. */
263 status = nx_dhcpv6_request_solicit(&dhcp_client);
264
265 /* Check for errors. */
266 if(status)
267 {
268 printf("ERROR!\n");
269 test_control_return(1);
270 }
271
272 /* Waiting for get the IPv6 address and do the duplicate address detection. */
273 tx_thread_sleep(6 * NX_IP_PERIODIC_RATE);
274
275 /* Get the valid IPv6 address count which the DHCPv6 server assigned . */
276 status = nx_dhcpv6_get_valid_ip_address_count(&dhcp_client, &address_count);
277
278 /* Check for errors. */
279 if ((status) || (address_count != 1))
280 {
281 printf("ERROR!\n");
282 test_control_return(1);
283 }
284
285 /* Get the IPv6 address, preferred lifetime and valid lifetime according to the address index. */
286 address_index = 0;
287 status = nx_dhcpv6_get_valid_ip_address_lease_time(&dhcp_client, address_index, &ipv6_address, &preferred_lifetime, &valid_lifetime);
288
289 /* Check for errors. */
290 if ((status) || (address_count != 1))
291 {
292 printf("ERROR!\n");
293 test_control_return(1);
294 }
295
296 /* Get the IPv6 address by DHCPv6 API. */
297 status = nx_dhcpv6_get_IP_address(&dhcp_client, &ipv6_address);
298
299 /* Check status. */
300 if (status != NX_SUCCESS)
301 {
302 printf("ERROR!\n");
303 test_control_return(1);
304 }
305
306 /* Check the address. */
307 if ((ipv6_address.nxd_ip_version != start_ipv6_address.nxd_ip_version) ||
308 (ipv6_address.nxd_ip_address.v6[0] != start_ipv6_address.nxd_ip_address.v6[0]) ||
309 (ipv6_address.nxd_ip_address.v6[1] != start_ipv6_address.nxd_ip_address.v6[1]) ||
310 (ipv6_address.nxd_ip_address.v6[2] != start_ipv6_address.nxd_ip_address.v6[2]) ||
311 (ipv6_address.nxd_ip_address.v6[3] != start_ipv6_address.nxd_ip_address.v6[3]))
312 {
313 printf("ERROR!\n");
314 test_control_return(1);
315 }
316
317 /* Get the IPv6 address by NetX Duo API. */
318 status = nxd_ipv6_address_get(&client_ip, 1, &ipv6_address, &prefix_length, &interface_index);
319
320 /* Check status. */
321 if (status != NX_SUCCESS)
322 {
323 printf("ERROR!\n");
324 test_control_return(1);
325 }
326
327 /* Check the IPv6 address. */
328 if ((prefix_length != 64) || (interface_index != 0) ||
329 (ipv6_address.nxd_ip_version != start_ipv6_address.nxd_ip_version) ||
330 (ipv6_address.nxd_ip_address.v6[0] != start_ipv6_address.nxd_ip_address.v6[0]) ||
331 (ipv6_address.nxd_ip_address.v6[1] != start_ipv6_address.nxd_ip_address.v6[1]) ||
332 (ipv6_address.nxd_ip_address.v6[2] != start_ipv6_address.nxd_ip_address.v6[2]) ||
333 (ipv6_address.nxd_ip_address.v6[3] != start_ipv6_address.nxd_ip_address.v6[3]))
334 {
335 printf("ERROR!\n");
336 test_control_return(1);
337 }
338
339 /* Get IP address lease time.
340 Note, This API only applies to one IA. */
341 status = nx_dhcpv6_get_lease_time_data(&dhcp_client, &T1, &T2, &preferred_lifetime, &valid_lifetime);
342
343 /* Check status. */
344 if (status != NX_SUCCESS)
345 {
346 printf("ERROR!\n");
347 test_control_return(1);
348 }
349
350 /* Check the value. */
351 if ((T1 != NX_DHCPV6_DEFAULT_T1_TIME) ||
352 (T2 != NX_DHCPV6_DEFAULT_T2_TIME) ||
353 (preferred_lifetime != NX_DHCPV6_DEFAULT_PREFERRED_TIME) ||
354 (valid_lifetime != NX_DHCPV6_DEFAULT_VALID_TIME))
355 {
356 printf("ERROR!\n");
357 test_control_return(1);
358 }
359
360 /* Get the DNS Server address. */
361 status = nx_dhcpv6_get_DNS_server_address(&dhcp_client, 0, &dns_address);
362
363 /* Check status. */
364 if (status != NX_SUCCESS)
365 {
366 printf("ERROR!\n");
367 test_control_return(1);
368 }
369
370 /* Check the IPv6 DNS address. */
371 if ((dns_address.nxd_ip_version != dns_ipv6_address.nxd_ip_version) ||
372 (dns_address.nxd_ip_address.v6[0] != dns_ipv6_address.nxd_ip_address.v6[0]) ||
373 (dns_address.nxd_ip_address.v6[1] != dns_ipv6_address.nxd_ip_address.v6[1]) ||
374 (dns_address.nxd_ip_address.v6[2] != dns_ipv6_address.nxd_ip_address.v6[2]) ||
375 (dns_address.nxd_ip_address.v6[3] != dns_ipv6_address.nxd_ip_address.v6[3]))
376 {
377 printf("ERROR!\n");
378 test_control_return(1);
379 }
380
381 /* Ping the DHCPv6 Server. */
382 status = nxd_icmp_ping(&client_ip, &server_address, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 28, &my_packet, NX_IP_PERIODIC_RATE);
383
384 /* Check for errors. */
385 if (status)
386 {
387 printf("ERROR!\n");
388 test_control_return(1);
389 }
390
391 /* Release the address. */
392 status = nx_dhcpv6_request_release(&dhcp_client);
393
394 /* Check status. */
395 if (status)
396 {
397 printf("ERROR!\n");
398 test_control_return(1);
399 }
400
401 /* Waiting for release the IPv6 address. */
402 tx_thread_sleep(NX_IP_PERIODIC_RATE);
403
404 /* Get the IPv6 address by DHCPv6 API. */
405 status = nx_dhcpv6_get_IP_address(&dhcp_client, &ipv6_address);
406
407 /* Check status. */
408 if (status == NX_SUCCESS)
409 {
410 printf("ERROR!\n");
411 test_control_return(1);
412 }
413
414 /* Get the IPv6 address by NetX Duo API. */
415 status = nxd_ipv6_address_get(&client_ip, 1, &ipv6_address, &prefix_length, &interface_index);
416
417 /* Check status. */
418 if (status == NX_SUCCESS)
419 {
420 printf("ERROR!\n");
421 test_control_return(1);
422 }
423
424 /* Stop the Client task. */
425 status = nx_dhcpv6_stop(&dhcp_client);
426
427 /* Check status. */
428 if (status)
429 {
430 printf("ERROR!\n");
431 test_control_return(1);
432 }
433
434 /* Delete the DHCPv6 client. */
435 status = nx_dhcpv6_client_delete(&dhcp_client);
436
437 /* Check status. */
438 if (status)
439 {
440 printf("ERROR!\n");
441 test_control_return(1);
442 }
443
444 /* Output successfully. */
445 printf("SUCCESS!\n");
446 test_control_return(0);
447 }
448
449 /* Define the test server thread. */
thread_server_entry(ULONG thread_input)450 void thread_server_entry(ULONG thread_input)
451 {
452
453 UINT status;
454 ULONG duid_time;
455 UINT addresses_added;
456
457 /* Set the IPv6 address of DHCPv6 Server. */
458 server_address.nxd_ip_version = NX_IP_VERSION_V6 ;
459 server_address.nxd_ip_address.v6[0] = 0x20010db8;
460 server_address.nxd_ip_address.v6[1] = 0xf101;
461 server_address.nxd_ip_address.v6[2] = 0x00000000;
462 server_address.nxd_ip_address.v6[3] = 0x00000101;
463
464 /* Set the link local and global addresses. */
465 status = nxd_ipv6_address_set(&server_ip, 0, NX_NULL, 10, NULL);
466 status += nxd_ipv6_address_set(&server_ip, 0, &server_address, 64, NULL);
467
468 /* Check for errors. */
469 if(status)
470 {
471 printf("ERROR!\n");
472 test_control_return(1);
473 }
474
475 /* Validate the link local and global addresses. */
476 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
477
478 /* Create the DHCPv6 Server. */
479 status = nx_dhcpv6_server_create(&dhcp_server, &server_ip, "DHCPv6 Server", &pool_0, pointer, NX_DHCPV6_SERVER_THREAD_STACK_SIZE, NX_NULL, NX_NULL);
480 pointer += NX_DHCPV6_SERVER_THREAD_STACK_SIZE;
481
482 /* Check for errors. */
483 if(status)
484 {
485 printf("ERROR!\n");
486 test_control_return(1);
487 }
488
489 /* Set up the DNS IPv6 server address. */
490 dns_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
491 dns_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
492 dns_ipv6_address.nxd_ip_address.v6[1] = 0x0000f101;
493 dns_ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
494 dns_ipv6_address.nxd_ip_address.v6[3] = 0x00000107;
495
496 status = nx_dhcpv6_create_dns_address(&dhcp_server, &dns_ipv6_address);
497
498 /* Check for errors. */
499 if(status)
500 {
501 printf("ERROR!\n");
502 test_control_return(1);
503 }
504
505 /* Note: For DUID types that do not require time, the 'duid_time' input can be left at zero.
506 The DUID_TYPE and HW_TYPE are configurable options that are user defined in nx_dhcpv6_server.h. */
507
508 /* Set the DUID time as the start of the millenium. */
509 duid_time = SECONDS_SINCE_JAN_1_2000_MOD_32;
510 status = nx_dhcpv6_set_server_duid(&dhcp_server,
511 NX_DHCPV6_SERVER_DUID_TYPE, NX_DHCPV6_SERVER_HW_TYPE,
512 dhcp_server.nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_msw,
513 dhcp_server.nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_lsw,
514 duid_time);
515
516 /* Check for errors. */
517 if(status)
518 {
519 printf("ERROR!\n");
520 test_control_return(1);
521 }
522
523 /* Set the IPv6 start address. */
524 start_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
525 start_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
526 start_ipv6_address.nxd_ip_address.v6[1] = 0x00000f101;
527 start_ipv6_address.nxd_ip_address.v6[2] = 0x0;
528 start_ipv6_address.nxd_ip_address.v6[3] = 0x00000110;
529
530 /* Set the IPv6 end address. */
531 end_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
532 end_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
533 end_ipv6_address.nxd_ip_address.v6[1] = 0x0000f101;
534 end_ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
535 end_ipv6_address.nxd_ip_address.v6[3] = 0x00000120;
536
537 /* Set the IPv6 address range. */
538 status = nx_dhcpv6_create_ip_address_range(&dhcp_server, &start_ipv6_address, &end_ipv6_address, &addresses_added);
539
540 /* Check for errors. */
541 if ((status) || (addresses_added != 16))
542 {
543 printf("ERROR!\n");
544 test_control_return(1);
545 }
546
547 /* Start the NetX DHCPv6 server! */
548 status = nx_dhcpv6_server_start(&dhcp_server);
549
550 /* Check for errors. */
551 if(status)
552 {
553 printf("ERROR!\n");
554 test_control_return(1);
555 }
556 }
557 #else
558 #ifdef CTEST
test_application_define(void * first_unused_memory)559 VOID test_application_define(void *first_unused_memory)
560 #else
561 void netx_dhcpv6_basic_test_application_define(void * first_unused_memory)
562 #endif
563 {
564 printf("NetX Test: DHCPv6 Basic Test.........................................N/A\n");
565 test_control_return(3);
566 }
567 #endif /* FEATURE_NX_IPV6 */
568