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