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 #include "nxd_dhcpv6_client.h"
8 #include "nxd_dhcpv6_server.h"
9
10 #define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
11
12 #ifdef FEATURE_NX_IPV6
13
14 #define DEMO_STACK_SIZE 2048
15 #define NX_DHCPV6_THREAD_STACK_SIZE 2048
16
17 /* Define the ThreadX and NetX object control blocks... */
18
19 NX_PACKET_POOL pool_0;
20 TX_THREAD thread_client;
21 NX_IP client_ip;
22 TX_THREAD thread_server;
23 NX_IP server_ip;
24
25 /* Define the Client and Server instances. */
26
27 NX_DHCPV6 dhcp_client;
28 NX_DHCPV6_SERVER dhcp_server;
29
30 /* Define the variables. */
31
32 CHAR *pointer;
33 NXD_ADDRESS server_address;
34 NXD_ADDRESS dns_ipv6_address;
35 NXD_ADDRESS start_ipv6_address;
36 NXD_ADDRESS end_ipv6_address;
37
38
39 /* Define thread prototypes. */
40
41 void thread_client_entry(ULONG thread_input);
42 void thread_server_entry(ULONG thread_input);
43
44 /***** Substitute your ethernet driver entry function here *********/
45 VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
46
47
48 /* Define some DHCPv6 parameters. */
49
50 #define DHCPV6_IANA_ID 0xABCDEFAB
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 main entry point. */
58
main()59 int main()
60 {
61
62 /* Enter the ThreadX kernel. */
63 tx_kernel_enter();
64 }
65
66
67 /* Define what the initial system looks like. */
68
tx_application_define(void * first_unused_memory)69 void tx_application_define(void *first_unused_memory)
70 {
71
72 UINT status;
73
74 /* Setup the working pointer. */
75 pointer = (CHAR *) first_unused_memory;
76
77 /* Initialize the NetX system. */
78 nx_system_initialize();
79
80 /* Create the Client thread. */
81 status = tx_thread_create(&thread_client, "Client thread", thread_client_entry, 0,
82 pointer, DEMO_STACK_SIZE,
83 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
84 pointer = pointer + DEMO_STACK_SIZE;
85
86 /* Check for thread create errors. */
87 if (status)
88 return;
89
90 /* Create the Server thread. */
91 status = tx_thread_create(&thread_server, "Server thread", thread_server_entry, 0,
92 pointer, DEMO_STACK_SIZE,
93 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
94 pointer = pointer + DEMO_STACK_SIZE;
95
96 /* Check for thread create errors. */
97 if (status)
98 return;
99
100 /* Create a packet pool. */
101 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1024, pointer, NX_DHCPV6_PACKET_POOL_SIZE);
102 pointer = pointer + NX_DHCPV6_PACKET_POOL_SIZE;
103
104 /* Check for pool creation error. */
105 if (status)
106 return;
107
108 /* Create a Client IP instance. */
109 status = nx_ip_create(&client_ip, "Client IP", IP_ADDRESS(0, 0, 0, 0),
110 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
111 pointer, 2048, 1);
112 pointer = pointer + 2048;
113
114 /* Check for IP create errors. */
115 if (status)
116 return;
117
118 /* Create a Server IP instance. */
119 status = nx_ip_create(&server_ip, "Server IP", IP_ADDRESS(1, 2, 3, 4),
120 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
121 pointer, 2048, 1);
122 pointer = pointer + 2048;
123
124 /* Check for IP create errors. */
125 if (status)
126 return;
127
128 /* Enable UDP traffic for sending DHCPv6 messages. */
129 status = nx_udp_enable(&client_ip);
130 status += nx_udp_enable(&server_ip);
131
132 /* Check for UDP enable errors. */
133 if (status)
134 return;
135
136 /* Enable the IPv6 services. */
137 status = nxd_ipv6_enable(&client_ip);
138 status += nxd_ipv6_enable(&server_ip);
139
140 /* Check for IPv6 enable errors. */
141 if (status)
142 return;
143
144 /* Enable the ICMPv6 services. */
145 status = nxd_icmp_enable(&client_ip);
146 status += nxd_icmp_enable(&server_ip);
147
148 /* Check for ICMPv6 enable errors. */
149 if (status)
150 return;
151 }
152
153 /* Define the Client host application thread. */
154
thread_client_entry(ULONG thread_input)155 void thread_client_entry(ULONG thread_input)
156 {
157
158 UINT status;
159
160 #ifdef GET_ONE_SPECIFIC_ADDRESS
161 NXD_ADDRESS ia_ipv6_address;
162 #endif
163
164 NXD_ADDRESS ipv6_address;
165 NXD_ADDRESS dns_address;
166 ULONG T1, T2, preferred_lifetime, valid_lifetime;
167 UINT address_count;
168 UINT address_index;
169 UINT dns_index;
170 NX_PACKET *my_packet;
171
172 NX_PARAMETER_NOT_USED(thread_input);
173
174 /* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
175 status = nx_ip_interface_mtu_set(&server_ip, 0, 1500);
176
177 /* Check for MTU set errors. */
178 if (status)
179 return;
180
181 /* Establish the link local address for the host. The RAM driver creates
182 a virtual MAC address of 0x1122334456. */
183 status = nxd_ipv6_address_set(&client_ip, 0, NX_NULL, 10, NULL);
184
185 /* Let NetX Duo and the network driver get initialized. Also give the server time to get set up. */
186 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
187
188 /* Create the DHCPv6 Client. */
189 status = nx_dhcpv6_client_create(&dhcp_client, &client_ip, "DHCPv6 Client", &pool_0, pointer, NX_DHCPV6_THREAD_STACK_SIZE,
190 NX_NULL, NX_NULL);
191 pointer = pointer + NX_DHCPV6_THREAD_STACK_SIZE;
192
193 /* Check for errors. */
194 if (status)
195 return;
196
197 /* Create a Link Layer Plus Time DUID for the DHCPv6 Client. Set time ID field
198 to NULL; the DHCPv6 Client API will supply one. */
199 status = nx_dhcpv6_create_client_duid(&dhcp_client, NX_DHCPV6_DUID_TYPE_LINK_TIME,
200 NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET, 0);
201
202 /* Check for errors. */
203 if (status)
204 return;
205
206 /* Create the DHCPv6 client's Identity Association (IA-NA) now.
207
208 Note that if this host had already been assigned in IPv6 lease, it
209 would have to use the assigned T1 and T2 values in loading the DHCPv6
210 client with an IANA block.
211 */
212 status = nx_dhcpv6_create_client_iana(&dhcp_client, DHCPV6_IANA_ID, DHCPV6_T1, DHCPV6_T2);
213
214 /* Check for errors. */
215 if (status)
216 return;
217
218 /* Starting up the NetX DHCPv6 Client. */
219 status = nx_dhcpv6_start(&dhcp_client);
220
221 /* Check for errors. */
222 if (status)
223 return;
224
225 /* Let DHCPv6 Server start. */
226 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
227
228 #ifdef GET_ONE_SPECIFIC_ADDRESS
229
230 /* Create an IA address option.
231 The client includs IA options for any IAs to which it wants the server to assign addresses.
232 */
233 ia_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
234 ia_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
235 ia_ipv6_address.nxd_ip_address.v6[1] = 0x00000f101;
236 ia_ipv6_address.nxd_ip_address.v6[2] = 0x0;
237 ia_ipv6_address.nxd_ip_address.v6[3] = 0x00000115;
238 status = nx_dhcpv6_create_client_ia(&dhcp_client, &ia_ipv6_address, NX_DHCPV6_REFERRED_LIFETIME,
239 NX_DHCPV6_VALID_LIFETIME);
240
241 /* Check for errors. */
242 if (status != NX_SUCCESS)
243 return;
244 #endif
245
246 /* If the host also want to get the option message, set the list of desired options to enabled. */
247 nx_dhcpv6_request_option_timezone(&dhcp_client, NX_TRUE);
248 nx_dhcpv6_request_option_DNS_server(&dhcp_client, NX_TRUE);
249 nx_dhcpv6_request_option_time_server(&dhcp_client, NX_TRUE);
250 nx_dhcpv6_request_option_domain_name(&dhcp_client, NX_TRUE);
251
252 /* Now, the host send the solicit message to get the IPv6 address and other options from the DHCPv6 server. */
253 status = nx_dhcpv6_request_solicit(&dhcp_client);
254
255 /* Check status. */
256 if (status)
257 return;
258
259 /* Waiting for get the IPv6 address and do the duplicate address detection. */
260 /*
261 Note, if the host detect another host withe the same address, the DHCPv6 Client can automatically
262 declient the address. At time T1 for an IPv6 address, the DHCPv6 Client can automatically renew the address.
263 At time T2 for an IPv6 address, the DHCPv6 Client can automatically rebind the address.
264 At time valid lifetime for an IPv6 address, the DHCPv6 Client can automatically delete the IPv6 address.
265 */
266 tx_thread_sleep(6 * NX_IP_PERIODIC_RATE);
267
268 /* Get the T1 and T2 value of IANA option. */
269 status = nx_dhcpv6_get_iana_lease_time(&dhcp_client, &T1, &T2);
270
271 /* Check status. */
272 if (status)
273 return;
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 status. */
279 if (status)
280 return;
281
282 /* Get the IPv6 address, preferred lifetime and valid lifetime according to the address index. */
283 address_index = 0;
284 status = nx_dhcpv6_get_valid_ip_address_lease_time(&dhcp_client, address_index, &ipv6_address, &preferred_lifetime, &valid_lifetime);
285
286 /* Check status. */
287 if (status)
288 return;
289
290 /* Get the IPv6 address.
291 Note, This API only applies to one IA. */
292 status = nx_dhcpv6_get_IP_address(&dhcp_client, &ipv6_address);
293
294 /* Check status. */
295 if (status)
296 return;
297
298 /* Get IP address lease time.
299 Note, This API only applies to one IA. */
300 status = nx_dhcpv6_get_lease_time_data(&dhcp_client, &T1, &T2, &preferred_lifetime, &valid_lifetime);
301
302 /* Check status. */
303 if (status)
304 return;
305
306 /* Get the DNS Server address lease time. */
307 dns_index = 0;
308 status = nx_dhcpv6_get_DNS_server_address(&dhcp_client, dns_index, &dns_address);
309
310 /* Check status. */
311 if (status)
312 return;
313
314 /**************************************************/
315 /* Ping the DHCPv6 Server, Test the IPv6 address. */
316 /**************************************************/
317
318 /* Ping the IPv6 address of DHCPv6 Server. */
319 status = nxd_icmp_ping(&client_ip, &server_address, DEMO_DATA, sizeof(DEMO_DATA), &my_packet, NX_IP_PERIODIC_RATE);
320
321 /* Check status. */
322 if (status)
323 return;
324
325 /* If we want to release the address, we can send release message to
326 the server we are releasing the assigned address. */
327 status = nx_dhcpv6_request_release(&dhcp_client);
328
329 /* Check status. */
330 if (status)
331 return;
332
333 /* Stop the Client task. */
334 status = nx_dhcpv6_stop(&dhcp_client);
335
336 /* Check status. */
337 if (status)
338 return;
339
340 /* Now delete the DHCPv6 client. */
341 status = nx_dhcpv6_client_delete(&dhcp_client);
342
343 /* Check status. */
344 if (status)
345 return;
346 }
347
348 /* Define the test server thread. */
349
thread_server_entry(ULONG thread_input)350 void thread_server_entry(ULONG thread_input)
351 {
352
353 UINT status;
354 ULONG duid_time;
355 UINT addresses_added;
356
357 NX_PARAMETER_NOT_USED(thread_input);
358
359 /* Modified the mtu size to avoid fragmenting the DHCP packet since the default mtu size is 128 in _nx_ram_network_driver. */
360 status = nx_ip_interface_mtu_set(&client_ip, 0, 1500);
361
362 /* Check for MTU set errors. */
363 if (status)
364 return;
365
366 /* Set the IPv6 address of DHCPv6 Server. */
367 server_address.nxd_ip_version = NX_IP_VERSION_V6 ;
368 server_address.nxd_ip_address.v6[0] = 0x20010db8;
369 server_address.nxd_ip_address.v6[1] = 0xf101;
370 server_address.nxd_ip_address.v6[2] = 0x00000000;
371 server_address.nxd_ip_address.v6[3] = 0x00000101;
372
373 /* Set the link local and global addresses. */
374 status = nxd_ipv6_address_set(&server_ip, 0, NX_NULL, 10, NULL);
375 status += nxd_ipv6_address_set(&server_ip, 0, &server_address, 64, NULL);
376
377 /* Check for errors. */
378 if (status)
379 return;
380
381 /* Create the DHCPv6 Server. */
382 status = nx_dhcpv6_server_create(&dhcp_server, &server_ip, "DHCPv6 Server", &pool_0, pointer, NX_DHCPV6_SERVER_THREAD_STACK_SIZE, NX_NULL, NX_NULL);
383 pointer = pointer + NX_DHCPV6_SERVER_THREAD_STACK_SIZE;
384
385 /* Check for errors. */
386 if (status)
387 return;
388
389 /* Note this example assumes a single global IP address on the primary interface. If otherwise
390 the host should call the service to set the network interface and global IP address index.
391
392 UINT _nx_dhcpv6_server_interface_set(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT interface_index, UINT address_index)
393 */
394
395 /* Validate the link local and global addresses. */
396 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
397
398 /* Set up the DNS IPv6 server address. */
399 dns_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
400 dns_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
401 dns_ipv6_address.nxd_ip_address.v6[1] = 0x0000f101;
402 dns_ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
403 dns_ipv6_address.nxd_ip_address.v6[3] = 0x00000107;
404
405 status = nx_dhcpv6_create_dns_address(&dhcp_server, &dns_ipv6_address);
406
407 /* Check for errors. */
408 if (status)
409 return;
410
411 /* Note: For DUID types that do not require time, the 'duid_time' input can be left at zero.
412 The DUID_TYPE and HW_TYPE are configurable options that are user defined in nx_dhcpv6_server.h. */
413
414 /* Set the DUID time as the start of the millenium. */
415 duid_time = SECONDS_SINCE_JAN_1_2000_MOD_32;
416 status = nx_dhcpv6_set_server_duid(&dhcp_server,
417 NX_DHCPV6_SERVER_DUID_TYPE, NX_DHCPV6_SERVER_HW_TYPE,
418 dhcp_server.nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_msw,
419 dhcp_server.nx_dhcpv6_ip_ptr -> nx_ip_arp_physical_address_lsw,
420 duid_time);
421
422 /* Check for errors. */
423 if (status)
424 return;
425
426 /* Set the IPv6 start address. */
427 start_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
428 start_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
429 start_ipv6_address.nxd_ip_address.v6[1] = 0x00000f101;
430 start_ipv6_address.nxd_ip_address.v6[2] = 0x0;
431 start_ipv6_address.nxd_ip_address.v6[3] = 0x00000110;
432
433 /* Set the IPv6 end address. */
434 end_ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
435 end_ipv6_address.nxd_ip_address.v6[0] = 0x20010db8;
436 end_ipv6_address.nxd_ip_address.v6[1] = 0x0000f101;
437 end_ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
438 end_ipv6_address.nxd_ip_address.v6[3] = 0x00000120;
439
440 /* Set the IPv6 address range. */
441 status = nx_dhcpv6_create_ip_address_range(&dhcp_server, &start_ipv6_address, &end_ipv6_address, &addresses_added);
442
443 /* Check for errors. */
444 if (status)
445 return;
446
447 /* Start the NetX DHCPv6 server! */
448 status = nx_dhcpv6_server_start(&dhcp_server);
449
450 /* Check for errors. */
451 if (status)
452 return;
453 }
454 #endif /* FEATURE_NX_IPV6 */
455