1 /* The DHCPREQUEST message MUST use the same value in the DHCP message header's 'secs' field and be sent to the same IP
2 * broadcast address as the original DHCPDISCOVER message.
3 * rfc 2131, page 16, 3.1 Client-server interaction - allocating a network address
4 */
5 #include "tx_api.h"
6 #include "nx_api.h"
7 #include "netx_dhcp_clone_function.h"
8 #include "nx_ipv4.h"
9 #include "nxd_dhcp_client.h"
10
11 extern void test_control_return(UINT status);
12
13 #if !defined(NX_DISABLE_IPV4)
14
15 #define DEMO_STACK_SIZE 4096
16 #define NX_PACKET_SIZE 1536
17 #define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8
18
19 #define NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(10,0,0,1)
20 #define START_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,10)
21 #define END_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,19)
22
23 #define NX_DHCP_SUBNET_MASK_0 IP_ADDRESS(255,255,255,0)
24 #define NX_DHCP_DEFAULT_GATEWAY_0 IP_ADDRESS(10,0,0,1)
25 #define NX_DHCP_DNS_SERVER_0 IP_ADDRESS(10,0,0,1)
26
27
28 /* Define the ThreadX and NetX object control blocks... */
29 static TX_THREAD client_thread;
30 static NX_PACKET_POOL client_pool;
31 static NX_IP client_ip;
32 static NX_DHCP dhcp_client;
33
34 static TX_THREAD server_thread;
35 static NX_PACKET_POOL server_pool;
36 static NX_IP server_ip;
37 static NX_UDP_SOCKET server_socket;
38
39 /* Define the counters used in the demo application... */
40
41 static ULONG error_counter;
42 static CHAR *pointer;
43 static UINT test_done = NX_FALSE;
44
45 /* Define thread prototypes. */
46
47 static void server_thread_entry(ULONG thread_input);
48 static void client_thread_entry(ULONG thread_input);
49
50 /******** Optionally substitute your Ethernet driver here. ***********/
51 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
52
53
54 /* Define what the initial system looks like. */
55
56 #ifdef CTEST
test_application_define(void * first_unused_memory)57 VOID test_application_define(void *first_unused_memory)
58 #else
59 void netx_dhcp_client_parameter_request_test_application_define(void *first_unused_memory)
60 #endif
61 {
62
63 UINT status;
64
65 /* Setup the working pointer. */
66 pointer = (CHAR *) first_unused_memory;
67
68 /* Create the client thread. */
69 tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
70 pointer, DEMO_STACK_SIZE,
71 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
72 pointer = pointer + DEMO_STACK_SIZE;
73
74 /* Create the server thread. */
75 tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,
76 pointer, DEMO_STACK_SIZE,
77 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
78 pointer = pointer + DEMO_STACK_SIZE;
79
80 /* Initialize the NetX system. */
81 nx_system_initialize();
82
83 /* Create the client packet pool. */
84 status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
85 pointer = pointer + NX_PACKET_POOL_SIZE;
86
87 /* Check for pool creation error. */
88 if (status)
89 error_counter++;
90
91 /* Create the server packet pool. */
92 status = nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
93 pointer = pointer + NX_PACKET_POOL_SIZE;
94
95 /* Check for pool creation error. */
96 if (status)
97 error_counter++;
98
99 /* Create an IP instance for the DHCP Client. */
100 status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1500, pointer, 2048, 1);
101
102 pointer = pointer + 2048;
103
104 /* Check for IP create errors. */
105 if (status)
106 error_counter++;
107
108 /* Create an IP instance for the DHCP Server. */
109 status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1500, pointer, 2048, 1);
110
111 pointer = pointer + 2048;
112
113 /* Check for IP create errors. */
114 if (status)
115 error_counter++;
116
117 /* Enable ARP and supply ARP cache memory for DHCP Client IP. */
118 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
119 pointer = pointer + 1024;
120
121 /* Check for ARP enable errors. */
122 if (status)
123 error_counter++;
124
125 /* Enable ARP and supply ARP cache memory for DHCP Server IP. */
126 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
127 pointer = pointer + 1024;
128
129 /* Check for ARP enable errors. */
130 if (status)
131 error_counter++;
132
133 /* Enable UDP traffic. */
134 status = nx_udp_enable(&client_ip);
135
136 /* Check for UDP enable errors. */
137 if (status)
138 error_counter++;
139
140 /* Enable UDP traffic. */
141 status = nx_udp_enable(&server_ip);
142
143 /* Check for UDP enable errors. */
144 if (status)
145 error_counter++;
146
147 /* Enable ICMP. */
148 status = nx_icmp_enable(&client_ip);
149
150 /* Check for errors. */
151 if (status)
152 error_counter++;
153
154 /* Enable ICMP. */
155 status = nx_icmp_enable(&server_ip);
156
157 /* Check for errors. */
158 if (status)
159 error_counter++;
160
161 return;
162 }
163
164 /* Define the test threads. */
165
server_thread_entry(ULONG thread_input)166 void server_thread_entry(ULONG thread_input)
167 {
168
169 UINT status;
170 UINT i = 0;
171 UINT index;
172 NX_PACKET *my_packet;
173 UCHAR *option_ptr;
174 UINT option_size;
175
176 printf("NetX Test: DHCP Client Parameter Request Test........................");
177
178 /* Create a socket as the server. */
179 status = nx_udp_socket_create(&server_ip, &server_socket, "Socket Server", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 5);
180
181 /* Check status. */
182 if (status)
183 {
184 printf("ERROR!\n");
185 test_control_return(1);
186 }
187
188 status = nx_udp_socket_bind(&server_socket, NX_DHCP_SERVER_UDP_PORT, TX_WAIT_FOREVER);
189
190 /* Check status. */
191 if (status)
192 {
193 printf("ERROR!\n");
194 test_control_return(1);
195 }
196
197 /* Receive DHCP message. */
198 status = nx_udp_socket_receive(&server_socket, &my_packet, 5 * NX_IP_PERIODIC_RATE);
199
200 /* Check status. */
201 if (status)
202 {
203 printf("ERROR!\n");
204 test_control_return(1);
205 }
206 else
207 {
208
209 /* Check if there is NTP in parameter request list. */
210 option_ptr = dhcp_search_buffer(my_packet -> nx_packet_prepend_ptr, NX_DHCP_OPTION_DHCP_PARAMETERS, my_packet -> nx_packet_length);
211
212 /* Check if found the parameter request option. */
213 if (option_ptr == NX_NULL)
214 {
215 printf("ERROR!\n");
216 test_control_return(1);
217 }
218 else
219 {
220 option_size = (UINT)*option_ptr;
221 option_ptr++;
222
223 /* Check if option size is correct. */
224 if (option_size != 3 + NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER)
225 {
226 printf("ERROR!\n");
227 test_control_return(1);
228 }
229
230 /* Check the default option. */
231 if ((*(option_ptr) != NX_DHCP_OPTION_SUBNET_MASK) ||
232 (*(option_ptr + 1) != NX_DHCP_OPTION_GATEWAYS) ||
233 (*(option_ptr + 2) != NX_DHCP_OPTION_DNS_SVR))
234 {
235 printf("ERROR!\n");
236 test_control_return(1);
237 }
238 option_ptr += 3;
239
240 /* Check the user option. */
241 for (index = 0; index < NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER; index ++)
242 {
243 if (*(option_ptr + index) != NX_DHCP_OPTION_NTP_SVR + index)
244 {
245 printf("ERROR!\n");
246 test_control_return(1);
247 }
248 }
249 }
250
251 /* Release the packet. */
252 nx_packet_release(my_packet);
253 }
254
255 /* Wait for test done. */
256 while(test_done == NX_FALSE)
257 {
258 tx_thread_sleep(NX_IP_PERIODIC_RATE);
259 }
260
261 if (error_counter)
262 {
263 printf("ERROR!\n");
264 test_control_return(1);
265 }
266 else
267 {
268 printf("SUCCESS!\n");
269 test_control_return(0);
270 }
271
272 return;
273 }
274
275 /* Define the test threads. */
276
client_thread_entry(ULONG thread_input)277 void client_thread_entry(ULONG thread_input)
278 {
279
280 UINT status;
281 UINT i;
282
283 /* Create the DHCP instance. */
284 status = nx_dhcp_create(&dhcp_client, &client_ip, "dhcp_client");
285 if (status)
286 {
287 error_counter++;
288 }
289
290 #ifdef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
291 status = nx_dhcp_packet_pool_set(&dhcp_client, &client_pool);
292 if (status)
293 error_counter++;
294 #endif /* NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL */
295
296 /* Add default option: subnet mask. */
297 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_SUBNET_MASK);
298 if (status != NX_DUPLICATED_ENTRY)
299 {
300 error_counter++;
301 }
302
303 /* Add default option: gateway. */
304 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_GATEWAYS);
305 if (status != NX_DUPLICATED_ENTRY)
306 {
307 error_counter++;
308 }
309
310 /* Add default option: dns. */
311 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_DNS_SVR);
312 if (status != NX_DUPLICATED_ENTRY)
313 {
314 error_counter++;
315 }
316
317 /* Try to add NTP server option. */
318 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_NTP_SVR);
319 if (status)
320 {
321 error_counter++;
322 }
323
324 /* Try to add NTP server option again. */
325 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_NTP_SVR);
326 if (status != NX_DUPLICATED_ENTRY)
327 {
328 error_counter++;
329 }
330
331 /* Loop to fill in the array. */
332 for (i = 0; i < NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER - 1; i++)
333 {
334 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_NTP_SVR + i + 1);
335 if (status)
336 {
337 error_counter++;
338 }
339 }
340
341 /* Try to add one more. */
342 status = nx_dhcp_user_option_request(&dhcp_client, NX_DHCP_OPTION_NTP_SVR + i + 1);
343 if (status != NX_NO_MORE_ENTRIES)
344 {
345 error_counter++;
346 }
347
348 /* Start the DHCP Client. */
349 status = nx_dhcp_start(&dhcp_client);
350 if (status)
351 {
352 error_counter++;
353 }
354
355 /* Let client sends out at least one message. */
356 while(dhcp_client.nx_dhcp_interface_record[0].nx_dhcp_discoveries_sent == 0)
357 {
358 tx_thread_sleep(NX_IP_PERIODIC_RATE);
359 }
360
361 /* Stopping the DHCP client. */
362 nx_dhcp_stop(&dhcp_client);
363
364 /* All done. Return resources to NetX and ThreadX. */
365 nx_dhcp_delete(&dhcp_client);
366
367 test_done = NX_TRUE;
368
369 return;
370 }
371 #else
372
373 #ifdef CTEST
test_application_define(void * first_unused_memory)374 VOID test_application_define(void *first_unused_memory)
375 #else
376 void netx_dhcp_client_parameter_request_test_application_define(void *first_unused_memory)
377 #endif
378 {
379
380 /* Print out test information banner. */
381 printf("NetX Test: DHCP Client Parameter Request Test........................N/A\n");
382
383 test_control_return(3);
384 }
385 #endif