1 #include "tx_api.h"
2 #include "nx_api.h"
3
4 extern void test_control_return(UINT status);
5 #ifdef FEATURE_NX_IPV6
6 #include "nx_udp.h"
7 #include "nx_ip.h"
8 #include "nx_ipv6.h"
9 #include "nxd_dhcpv6_client.h"
10
11 #define DEMO_STACK_SIZE 2048
12 #define DHCPV6_IANA_ID 0xc0dedbad
13
14 static TX_THREAD dhcpv6_client_thread;
15 static NX_PACKET_POOL pool_0;
16 static NX_IP ip_0;
17 static NX_DHCPV6 dhcp_client;
18
19 static CHAR *pointer;
20 static ULONG error_counter;
21
22 static UCHAR solicit = NX_FALSE;
23 static UCHAR request = NX_FALSE;
24 static ULONG server_identifier;
25 static ULONG server_identifier_length;
26 static ULONG server_duid_type;
27 static ULONG server_hardware_type;
28 static ULONG server_msw;
29 static ULONG server_lsw;
30
31 /* Define thread prototypes. */
32
33 static void dhcpv6_client_thread_entry(ULONG thread_input);
34 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
35 extern UINT (*packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
36 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
37 extern UINT _nx_dhcpv6_utility_get_block_option_length(UCHAR *buffer_ptr, ULONG *option, ULONG *length);
38
39 /* Frame (118 bytes) Solicit */
40 static unsigned char pkt1[118] = {
41 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, 0x00, 0x80, /* 33...... */
42 0xa3, 0xc7, 0x1c, 0xf6, 0x86, 0xdd, 0x60, 0x00, /* ......`. */
43 0x00, 0x00, 0x00, 0x40, 0x11, 0x40, 0xfe, 0x80, /* ...@.@.. */
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, /* ........ */
45 0xa3, 0xff, 0xfe, 0xc7, 0x1c, 0xf6, 0xff, 0x02, /* ........ */
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
47 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x22, /* ......." */
48 0x02, 0x23, 0x00, 0x40, 0xc2, 0x19, 0x01, 0xdc, /* .#.@.... */
49 0x5d, 0x45, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, /* ]E...... */
50 0x00, 0x01, 0x5a, 0xcd, 0x54, 0xc7, 0x00, 0x80, /* ..Z.T... */
51 0xa3, 0xc7, 0x1c, 0xf6, 0x00, 0x03, 0x00, 0x0c, /* ........ */
52 0xc0, 0xde, 0xdb, 0xad, 0x00, 0x00, 0x00, 0x00, /* ........ */
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, /* ........ */
54 0x0c, 0x1c, 0x00, 0x06, 0x00, 0x08, 0x00, 0x17, /* ........ */
55 0x00, 0x1f, 0x00, 0x29, 0x00, 0x18 /* ...).. */
56 };
57
58 /* Frame (178 bytes) Advertise */
59 static unsigned char pkt2[178] = {
60 0x00, 0x80, 0xa3, 0xc7, 0x1c, 0xf6, 0xec, 0x08, /* ........ */
61 0x6b, 0x93, 0x70, 0xde, 0x86, 0xdd, 0x60, 0x00, /* k.p...`. */
62 0x00, 0x00, 0x00, 0x7c, 0x11, 0x40, 0xfe, 0x80, /* ...|.@.. */
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x08, /* ........ */
64 0x6b, 0xff, 0xfe, 0x93, 0x70, 0xde, 0xfe, 0x80, /* k...p... */
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, /* ........ */
66 0xa3, 0xff, 0xfe, 0xc7, 0x1c, 0xf6, 0xd3, 0x98, /* ........ */
67 0x02, 0x22, 0x00, 0x7c, 0xd9, 0x80, 0x02, 0xdc, /* .".|.... */
68 0x5d, 0x45, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, /* ]E...... */
69 0x00, 0x01, 0x5a, 0xcd, 0x54, 0xc7, 0x00, 0x80, /* ..Z.T... */
70 0xa3, 0xc7, 0x1c, 0xf6, 0x00, 0x02, 0x00, 0x0a, /* ........ */
71 0x00, 0x03, 0x00, 0x01, 0xec, 0x08, 0x6b, 0x93, /* ......k. */
72 0x70, 0xde, 0x00, 0x03, 0x00, 0x28, 0xc0, 0xde, /* p....(.. */
73 0xdb, 0xad, 0x00, 0x00, 0xa8, 0xc0, 0x00, 0x01, /* ........ */
74 0x0e, 0x00, 0x00, 0x05, 0x00, 0x18, 0x12, 0x34, /* .......4 */
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, /* ........ */
77 0x51, 0x80, 0x00, 0x01, 0x51, 0x80, 0x00, 0x17, /* Q...Q... */
78 0x00, 0x20, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, /* . .4.... */
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
80 0x00, 0x01, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, /* ...4.... */
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
82 0x00, 0x02 /* .. */
83 };
84
85
86 #ifdef CTEST
test_application_define(void * first_unused_memory)87 VOID test_application_define(void *first_unused_memory)
88 #else
89 void netx_dhcpv6_client_process_server_duid_test_application_define(void * first_unused_memory)
90 #endif
91 {
92 UINT status;
93
94 /* Setup the working pointer. */
95 pointer = (CHAR *) first_unused_memory;
96
97 error_counter = 0;
98
99 /* Initialize the NetX system. */
100 nx_system_initialize();
101
102 /* Create a packet pool. */
103 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, pointer, 1536*16);
104 pointer = pointer + 1536*16;
105 if(status)
106 error_counter++;
107
108 /* Create an IP instance. */
109 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1,2,3,4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
110 pointer, 2048, 1);
111 pointer = pointer + 2048;
112
113 /* Enable IPv6 */
114 status = nxd_ipv6_enable(&ip_0);
115 if(status)
116 error_counter++;
117
118 /* Enable ICMP for IP Instance 0 and 1. */
119 status = nxd_icmp_enable(&ip_0);
120 if(status)
121 error_counter++;
122
123 status = nx_udp_enable(&ip_0);
124 if(status)
125 error_counter++;
126
127 /* Create the main thread. */
128 tx_thread_create(&dhcpv6_client_thread, "dhcpv6 client thread", dhcpv6_client_thread_entry, 0,
129 pointer, DEMO_STACK_SIZE,
130 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
131
132 pointer = pointer + DEMO_STACK_SIZE;
133 }
134
dhcpv6_client_thread_entry(ULONG thread_input)135 void dhcpv6_client_thread_entry(ULONG thread_input)
136 {
137 UINT status;
138
139
140 /* Print out test information banner. */
141 printf("NetX Test: DHCPv6 Client Process Server Duid Test....................");
142
143 /* Check for earlier error. */
144 if(error_counter)
145 {
146 printf("ERROR!\n");
147 test_control_return(1);
148 }
149
150 /* Set the new physical address. */
151 status = nx_ip_interface_physical_address_set(&ip_0, 0, 0x00000080, 0xa3c71cf6, NX_TRUE);
152
153 /* Check the status. */
154 if(status)
155 {
156 printf("ERROR!\n");
157 test_control_return(1);
158 }
159
160 /* Set the linklocal address. */
161 status = nxd_ipv6_address_set(&ip_0, 0, NX_NULL, 10, NX_NULL);
162
163 /* Check the status. */
164 if(status)
165 {
166 printf("ERROR!\n");
167 test_control_return(1);
168 }
169
170 /* Wait to finish the DAD. */
171 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
172
173 /* Create a DHCPv6 Client. */
174 status = nx_dhcpv6_client_create(&dhcp_client, &ip_0, "DHCPv6 Client", &pool_0, pointer, 2048, NX_NULL, NX_NULL);
175 pointer += 2048;
176
177 /* Check the status. */
178 if(status)
179 {
180 printf("ERROR!\n");
181 test_control_return(1);
182 }
183
184 /* Create a Link Layer Plus Time DUID for the DHCPv6 Client. Set time ID field
185 to NULL; the DHCPv6 Client API will supply one. */
186 status = nx_dhcpv6_create_client_duid(&dhcp_client, NX_DHCPV6_DUID_TYPE_LINK_TIME, NX_DHCPV6_HW_TYPE_IEEE_802, 0x5acd54c7);
187
188 /* Check the status. */
189 if(status)
190 {
191 printf("ERROR!\n");
192 test_control_return(1);
193 }
194
195 /* Create the DHCPv6 client's Identity Association (IA-NA) now. */
196 status = nx_dhcpv6_create_client_iana(&dhcp_client, DHCPV6_IANA_ID, 0xFFFFFFFF, 0xFFFFFFFF);
197
198 /* Check the status. */
199 if(status)
200 {
201 printf("ERROR!\n");
202 test_control_return(1);
203 }
204
205 /* Set the DNS Server option. */
206 status = nx_dhcpv6_request_option_DNS_server(&dhcp_client, NX_TRUE);
207
208 /* Check the status. */
209 if(status)
210 {
211 printf("ERROR!\n");
212 test_control_return(1);
213 }
214
215 /* Set the SNTP Server option. */
216 status = nx_dhcpv6_request_option_time_server(&dhcp_client, NX_TRUE);
217
218 /* Check the status. */
219 if(status)
220 {
221 printf("ERROR!\n");
222 test_control_return(1);
223 }
224
225 /* Set the Time Zone option. */
226 status = nx_dhcpv6_request_option_timezone(&dhcp_client, NX_TRUE);
227
228 /* Check the status. */
229 if(status)
230 {
231 printf("ERROR!\n");
232 test_control_return(1);
233 }
234
235 /* Set the Domain Search List option. */
236 status = nx_dhcpv6_request_option_domain_name(&dhcp_client, NX_TRUE);
237
238 /* Check the status. */
239 if(status)
240 {
241 printf("ERROR!\n");
242 test_control_return(1);
243 }
244
245 /* Set the call back function. */
246 packet_process_callback = my_packet_process;
247
248 /* Start the NetX DHCPv6 Client. */
249 status = nx_dhcpv6_start(&dhcp_client);
250
251 /* Check the status. */
252 if(status)
253 {
254 printf("ERROR!\n");
255 test_control_return(1);
256 }
257
258 /* Request the IPv6 address. */
259 status = nx_dhcpv6_request_solicit(&dhcp_client);
260
261 /* Check the status. */
262 if(status)
263 {
264 printf("ERROR!\n");
265 test_control_return(1);
266 }
267
268 /* Wait for Advertise. */
269 tx_thread_sleep(2 * NX_IP_PERIODIC_RATE);
270
271 /* Check the error counter. */
272 if ((error_counter) || (solicit != NX_TRUE) || (request != NX_TRUE))
273 {
274 printf("ERROR!\n");
275 test_control_return(1);
276 }
277 else
278 {
279 printf("SUCCESS!\n");
280 test_control_return(0);
281 }
282
283 }
my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr)284 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
285 {
286
287 ULONG received_message_type;
288 NX_PACKET *response_packet;
289 UINT status;
290 NX_IPV6_HEADER *ip_header;
291
292 /* Update the prepend to point DHCPv6 message, IPv6 header, UDP header. */
293 packet_ptr -> nx_packet_prepend_ptr += (40 + 8);
294
295 /* Extract the message type which should be the first byte. */
296 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr, 1, &received_message_type);
297
298 /* Check for an illegal message type. */
299 if ((received_message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT) && (solicit == NX_FALSE))
300 {
301
302 solicit = NX_TRUE;
303
304 /* Send DHCPv6 Server Advertise response. */
305
306 /* Allocate a response packet. */
307 status = nx_packet_allocate(&pool_0, &response_packet, NX_RECEIVE_PACKET, TX_WAIT_FOREVER);
308
309 /* Check status. */
310 if (status)
311 {
312 error_counter++;
313
314 /* Relase the packet. */
315 nx_packet_release(packet_ptr);
316 return(NX_FALSE);
317 }
318
319 response_packet -> nx_packet_prepend_ptr += 2;
320 response_packet -> nx_packet_append_ptr += 2;
321
322 /* Write the DHCPv6 Server response messages into the packet payload! */
323 status = nx_packet_data_append(response_packet, pkt2, sizeof(pkt2), &pool_0, NX_NO_WAIT);
324
325 /* Check status. */
326 if (status)
327 {
328 error_counter++;
329 nx_packet_release(packet_ptr);
330 nx_packet_release(response_packet);
331 return(NX_FALSE);
332 }
333
334 /* Set the packet version. */
335 response_packet -> nx_packet_ip_version = NX_IP_VERSION_V6;
336
337 /* Set the IP header pointer. */
338 response_packet -> nx_packet_ip_header = response_packet -> nx_packet_prepend_ptr + 14;
339 ip_header = (NX_IPV6_HEADER *)(response_packet -> nx_packet_ip_header);
340 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_source_ip);
341 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_destination_ip);
342
343 /* Update the data pointer UDP + DHCPv6 message. */
344 response_packet -> nx_packet_prepend_ptr += 54;
345 response_packet -> nx_packet_length -= 54;
346
347 /* Set the packet interface. */
348 response_packet -> nx_packet_address.nx_packet_ipv6_address_ptr = &ip_0.nx_ipv6_address[0];
349
350 dhcp_client.nx_dhcpv6_message_hdr.nx_message_xid = 0xdc5d45;
351
352 /* Receive the DHCPv6 Server response. */
353 _nx_udp_packet_receive(ip_ptr, response_packet);
354
355 }
356 else if((received_message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST) && (request == NX_FALSE))
357 {
358
359 /* Skip the DHCPv6 header. Type and Transaction ID. */
360 packet_ptr -> nx_packet_prepend_ptr += 4;
361
362 /* Skip the Client Identifier. */
363 packet_ptr -> nx_packet_prepend_ptr += 18;
364
365 /* Skip the Elapsed time. */
366 packet_ptr -> nx_packet_prepend_ptr += 6;
367
368 /* Extract the server identifier. */
369 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr, 2, &server_identifier);
370 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 2, 2, &server_identifier_length);
371 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 4, 2, &server_duid_type);
372 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 6, 2, &server_hardware_type);
373 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 8, 2, &server_msw);
374 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 10, 4, &server_lsw);
375
376 /* Check the server identifier. */
377 if ((server_identifier == 2) && (server_identifier_length == 10) &&
378 (server_duid_type == 3) && (server_hardware_type == 1) &&
379 (server_msw == 0x0000ec08) && (server_lsw == 0x6b9370de))
380 request = NX_TRUE;
381 }
382
383 /* Relase the packet. */
384 nx_packet_release(packet_ptr);
385
386 return(NX_FALSE);
387 }
388
389 #else
390 #ifdef CTEST
test_application_define(void * first_unused_memory)391 VOID test_application_define(void *first_unused_memory)
392 #else
393 void netx_dhcpv6_client_process_server_duid_test_application_define(void * first_unused_memory)
394 #endif
395 {
396 printf("NetX Test: DHCPv6 Client Process Server Duid Test....................N/A\n");
397 test_control_return(3);
398 }
399 #endif
400