1 #include "tx_api.h"
2 #include "nx_api.h"
3 #include "netx_tahi.h"
4 #if defined(FEATURE_NX_IPV6) && defined(NX_TAHI_ENABLE)
5 #include "nx_udp.h"
6 #include "nx_ip.h"
7 #include "nx_ipv6.h"
8 #include "nxd_dhcpv6_client.h"
9
10
11 #define DEMO_STACK_SIZE 2048
12 #define TEST_INTERFACE 0
13 #define DHCPV6_IANA_ID 0xC0DEDBAD
14
15 static TX_THREAD dhcpv6_client_thread;
16 static NX_PACKET_POOL pool_0;
17 static NX_IP ip_0;
18 static NX_DHCPV6 dhcp_client;
19
20 static ULONG error_counter;
21
22 static void dhcpv6_client_thread_entry(ULONG thread_input);
23 extern void test_control_return(UINT status);
24 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
25 extern UINT (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
26 static UINT my_dhcpv6_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
27 static void my_dhcpv6_udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
28
29 static ULONG original_xid;
30 static UCHAR original_cid[18];
31 static UINT renew_count;
32
33 extern TAHI_TEST_SEQ tahi_dhcpv6_01_068[];
34 extern int tahi_dhcpv6_01_068_size;
35
36 #ifdef CTEST
test_application_define(void * first_unused_memory)37 VOID test_application_define(void *first_unused_memory)
38 #else
39 void netx_tahi_dhcpv6_test_01_068_define(void * first_unused_memory)
40 #endif
41 {
42 CHAR *pointer;
43 UINT status;
44
45 /* Setup the working pointer. */
46 pointer = (CHAR *) first_unused_memory;
47
48 error_counter = 0;
49 renew_count = 0;
50
51 /* Initialize the NetX system. */
52 nx_system_initialize();
53
54 /* Create a packet pool. */
55 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, pointer, 1536*16);
56 pointer = pointer + 1536*16;
57 if(status)
58 error_counter++;
59
60 /* Create an IP instance. */
61 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1,2,3,4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
62 pointer, 2048, 1);
63 pointer = pointer + 2048;
64
65 /* Enable IPv6 */
66 status = nxd_ipv6_enable(&ip_0);
67 if(status)
68 error_counter++;
69
70 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
71 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
72 pointer = pointer + 1024;
73 if(status)
74 error_counter++;
75
76 /* Enable ICMP for IP Instance 0 and 1. */
77 status = nxd_icmp_enable(&ip_0);
78 if(status)
79 error_counter++;
80
81 status = nx_udp_enable(&ip_0);
82 if(status)
83 error_counter++;
84
85 /* Enable fragment processing for IP Instance 0. */
86 status = nx_ip_fragment_enable(&ip_0);
87 if(status)
88 error_counter++;
89
90 /* Create a DHCPv6 Client. */
91 status = nx_dhcpv6_client_create(&dhcp_client, &ip_0, "DHCPv6 Client", &pool_0, pointer, 2048, NX_NULL, NX_NULL);
92 pointer += 2048;
93 if(status)
94 error_counter++;
95
96 /* Create the main thread. */
97 tx_thread_create(&dhcpv6_client_thread, "dhcpv6 client thread", dhcpv6_client_thread_entry, 0,
98 pointer, DEMO_STACK_SIZE,
99 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
100
101 pointer = pointer + DEMO_STACK_SIZE;
102
103 }
104
dhcpv6_client_thread_entry(ULONG thread_input)105 void dhcpv6_client_thread_entry(ULONG thread_input)
106 {
107 NXD_ADDRESS ipv6_address;
108 UINT status;
109
110 status = nxd_ipv6_address_set(&ip_0, 0, NX_NULL, 10, NX_NULL);
111 if(status)
112 error_counter++;
113
114 /* Create a Link Layer Plus Time DUID for the DHCPv6 Client. Set time ID field
115 to NULL; the DHCPv6 Client API will supply one. */
116 status = nx_dhcpv6_create_client_duid(&dhcp_client, NX_DHCPV6_DUID_TYPE_LINK_TIME,
117 NX_DHCPV6_HW_TYPE_IEEE_802, 0);
118 if(status)
119 error_counter++;
120
121 /* Create the DHCPv6 client's Identity Association (IA-NA) now. */
122 status = nx_dhcpv6_create_client_iana(&dhcp_client, DHCPV6_IANA_ID, 0xFFFFFFFF, 0xFFFFFFFF);
123 if(status)
124 error_counter++;
125
126 memset(&ipv6_address,0x0, sizeof(NXD_ADDRESS));
127 ipv6_address.nxd_ip_version = NX_IP_VERSION_V6 ;
128
129 /* Create an IA address option. */
130 if((ipv6_address.nxd_ip_address.v6[0] != 0) ||
131 (ipv6_address.nxd_ip_address.v6[1] != 0) ||
132 (ipv6_address.nxd_ip_address.v6[2] != 0) ||
133 (ipv6_address.nxd_ip_address.v6[3] != 0))
134 {
135
136 status = nx_dhcpv6_create_client_ia(&dhcp_client, &ipv6_address, 0xFFFFFFFF,
137 0xFFFFFFFF);
138
139 if (status != NX_SUCCESS)
140 {
141 return;
142 }
143 }
144
145 /* Set the list of desired options to enabled. */
146 nx_dhcpv6_request_option_timezone(&dhcp_client, NX_TRUE);
147 nx_dhcpv6_request_option_DNS_server(&dhcp_client, NX_TRUE);
148 nx_dhcpv6_request_option_time_server(&dhcp_client, NX_TRUE);
149 nx_dhcpv6_request_option_domain_name(&dhcp_client, NX_TRUE);
150
151 /* Wait to finish the DAD. */
152 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
153
154 /* Start the NetX DHCPv6 Client. */
155 status = nx_dhcpv6_start(&dhcp_client);
156
157 advanced_packet_process_callback = my_dhcpv6_packet_process;
158 ip_0.nx_ip_udp_packet_receive = my_dhcpv6_udp_packet_receive;
159
160 status = nx_dhcpv6_request_solicit(&dhcp_client);
161
162 netx_tahi_run_test_case(&ip_0, &tahi_dhcpv6_01_068[0], tahi_dhcpv6_01_068_size);
163
164 nx_dhcpv6_client_delete(&dhcp_client);
165
166 test_control_return(0xdeadbeef);
167 }
168
169
my_dhcpv6_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)170 UINT my_dhcpv6_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
171 {
172 NX_UDP_HEADER *udp_header_ptr;
173 ULONG src_dst_port;
174 ULONG message_type;
175 NX_IPV6_HEADER *ip_header;
176 ULONG checksum;
177 ULONG *ip_src_addr, *ip_dest_addr;
178 UCHAR cid[18] = {0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01,
179 0xac, 0x7d, 0x87, 0x3a, 0x00, 0x11, 0x22, 0x33,
180 0x44, 0x56};
181
182
183 udp_header_ptr = (NX_UDP_HEADER*)(packet_ptr -> nx_packet_prepend_ptr + 40);
184 src_dst_port = udp_header_ptr -> nx_udp_header_word_0;
185 NX_CHANGE_ULONG_ENDIAN(src_dst_port);
186
187
188 /* From port 546(client) to 547(server). Check if this is a DHCPv6 packet sent from client to server*/
189 if(src_dst_port == 0x02220223)
190 {
191 packet_ptr -> nx_packet_prepend_ptr += 40;
192 packet_ptr -> nx_packet_length -= 40;
193
194 /* Get IP address for checksum computing. */
195 ip_header = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_ip_header);
196 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_source_ip);
197 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_destination_ip);
198 ip_src_addr = &(ip_header -> nx_ip_header_source_ip[0]);
199 ip_dest_addr = &(ip_header -> nx_ip_header_destination_ip[0]);
200
201 /* Get message type. */
202 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 8, 1, &message_type);
203
204 if(message_type == NX_DHCPV6_MESSAGE_TYPE_SOLICIT)
205 {
206 /* Record original xid, modify the xid to be the same with Tahi test packet. */
207 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 9, 3, &original_xid);
208 *(ULONG *)(packet_ptr -> nx_packet_prepend_ptr + 8) = 0x12f03e01;
209 }
210 else if(message_type == NX_DHCPV6_MESSAGE_TYPE_REQUEST)
211 {
212 /* Record original xid, modify the xid to be the same with Tahi test packet. */
213 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 9, 3, &original_xid);
214 *(ULONG *)(packet_ptr -> nx_packet_prepend_ptr + 8) = 0x900e0803;
215 }
216 else if((message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) && (renew_count == 0))
217 {
218 /* Record original xid, modify the xid to be the same with Tahi test packet. */
219 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 9, 3, &original_xid);
220 *(ULONG *)(packet_ptr -> nx_packet_prepend_ptr + 8) = 0x66915200 + message_type;
221 renew_count++;
222 }
223 else if((message_type == NX_DHCPV6_MESSAGE_TYPE_RENEW) ||
224 (message_type == NX_DHCPV6_MESSAGE_TYPE_REBIND))
225 {
226
227 /* Record original xid, modify the xid to be the same with Tahi test packet. */
228 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 9, 3, &original_xid);
229 *(ULONG *)(packet_ptr -> nx_packet_prepend_ptr + 8) = 0xa4e49600 + message_type;
230 }
231
232 /* Record original cid, modify the cid to be the same with Tahi test packet. */
233 memcpy(original_cid, (packet_ptr -> nx_packet_prepend_ptr + 12), 18);
234 memcpy(packet_ptr -> nx_packet_prepend_ptr + 12, cid, 18);
235
236
237 /* Compute the checksum. */
238 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
239
240 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & 0xFFFF0000;
241
242 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
243
244 /* Yes, we need to compute the UDP checksum. */
245 checksum = _nx_ip_checksum_compute(packet_ptr,
246 NX_PROTOCOL_UDP,
247 packet_ptr -> nx_packet_length,
248 ip_src_addr,
249 ip_dest_addr);
250 checksum = ~checksum & NX_LOWER_16_MASK;
251
252 /* If the computed checksum is zero, it is transmitted as all ones. */
253 /* RFC 768, page 2. */
254 if(checksum == 0)
255 checksum = 0xFFFF;
256
257 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
258
259 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & 0xFFFF0000;
260
261 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
262
263 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
264
265 packet_ptr -> nx_packet_prepend_ptr -= 40;
266 packet_ptr -> nx_packet_length += 40;
267
268 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_source_ip);
269 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header -> nx_ip_header_destination_ip);
270 }
271
272 return NX_TRUE;
273
274 }
275
my_dhcpv6_udp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)276 void my_dhcpv6_udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
277 {
278
279 ULONG *ip_src_addr, *ip_dest_addr;
280 ULONG dst_port;
281 NX_UDP_HEADER *udp_header_ptr;
282 ULONG checksum;
283 NX_IPV6_HEADER *ip_header;
284 ULONG message_type;
285
286 udp_header_ptr = (NX_UDP_HEADER*)(packet_ptr -> nx_packet_prepend_ptr);
287 dst_port = udp_header_ptr -> nx_udp_header_word_0;
288 NX_CHANGE_ULONG_ENDIAN(dst_port);
289
290 /* Check if this is a DHCPv6 packet sent to client. */
291 if((dst_port & 0x0000FFFF) == 0x00000222)
292 {
293
294 /* Get IP address for checksum computing. */
295 ip_header = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_ip_header);
296 ip_src_addr = &(ip_header -> nx_ip_header_source_ip[0]);
297 ip_dest_addr= &(ip_header -> nx_ip_header_destination_ip[0]);
298
299
300 /* Modify the xid and cid. */
301 _nx_dhcpv6_utility_get_data(packet_ptr -> nx_packet_prepend_ptr + 8, 1, &message_type);
302 NX_CHANGE_ULONG_ENDIAN(original_xid);
303 *(ULONG *)(packet_ptr -> nx_packet_prepend_ptr + 8) = original_xid + message_type;
304 memcpy(packet_ptr -> nx_packet_prepend_ptr + 12, original_cid, 18);
305
306
307 /* Compute the checksum. */
308 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
309
310 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & 0xFFFF0000;
311
312 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
313
314 /* Yes, we need to compute the UDP checksum. */
315 checksum = _nx_ip_checksum_compute(packet_ptr,
316 NX_PROTOCOL_UDP,
317 packet_ptr -> nx_packet_length,
318 ip_src_addr,
319 ip_dest_addr);
320 checksum = ~checksum & NX_LOWER_16_MASK;
321
322 /* If the computed checksum is zero, it is transmitted as all ones. */
323 /* RFC 768, page 2. */
324 if(checksum == 0)
325 checksum = 0xFFFF;
326
327 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
328
329 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 & 0xFFFF0000;
330
331 udp_header_ptr -> nx_udp_header_word_1 = udp_header_ptr -> nx_udp_header_word_1 | checksum;
332
333 NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1);
334 }
335
336 _nx_udp_packet_receive(ip_ptr, packet_ptr);
337
338 }
339 #endif
340