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