1 /* The server responds to a DHCPINFORM message by sending a DHCPACK
2 * message directly to the address given in the 'ciaddr' field of the
3 * DHCPINFORM message. The server MUST NOT send a lease expiration time
4 to the client and SHOULD NOT fill in 'yiaddr'.
5 * rfc 2131, page 33, 4.3.5 DHCPINFORM message
6 *
7 */
8
9 #include "tx_api.h"
10 #include "nx_api.h"
11 #include "nxd_dhcp_client.h"
12 #include "nxd_dhcp_server.h"
13 #include "netx_dhcp_clone_function.h"
14
15 extern void test_control_return(UINT status);
16
17 #if !defined(NX_DISABLE_IPV4)
18
19 #define DEMO_STACK_SIZE 4096
20 #define NX_PACKET_SIZE 1536
21 #define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8
22
23 #define NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(10,0,0,1)
24 #define START_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,10)
25 #define END_IP_ADDRESS_LIST_0 IP_ADDRESS(10,0,0,19)
26
27 #define NX_DHCP_SUBNET_MASK_0 IP_ADDRESS(255,255,255,0)
28 #define NX_DHCP_DEFAULT_GATEWAY_0 IP_ADDRESS(10,0,0,1)
29 #define NX_DHCP_DNS_SERVER_0 IP_ADDRESS(10,0,0,1)
30
31 /* Define the ThreadX and NetX object control blocks... */
32 static TX_THREAD client_thread;
33 static NX_PACKET_POOL client_pool;
34 static NX_IP client_ip;
35 static NX_DHCP dhcp_client;
36
37 static TX_THREAD server_thread;
38 static NX_PACKET_POOL server_pool;
39 static NX_IP server_ip;
40 static NX_DHCP_SERVER dhcp_server;
41
42 /* Define the counters used in the demo application... */
43
44 static ULONG error_counter;
45 static CHAR *pointer;
46
47 static UINT dhcp_ack_flag;
48 static UINT dhcp_inform_count;
49
50 /* Define thread prototypes. */
51
52 static void server_thread_entry(ULONG thread_input);
53 static void client_thread_entry(ULONG thread_input);
54
55 /******** Optionally substitute your Ethernet driver here. ***********/
56 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
57 extern UINT (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
58 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
59 static void my_udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
60
61 /* Define what the initial system looks like. */
62
63 #ifdef CTEST
test_application_define(void * first_unused_memory)64 VOID test_application_define(void *first_unused_memory)
65 #else
66 void netx_dhcp_04_03_05_01_test_application_define(void *first_unused_memory)
67 #endif
68 {
69
70 UINT status;
71
72 /* Setup the working pointer. */
73 pointer = (CHAR *) first_unused_memory;
74
75 /* Create the client thread. */
76 tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
77 pointer, DEMO_STACK_SIZE,
78 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
79 pointer = pointer + DEMO_STACK_SIZE;
80
81 /* Create the server thread. */
82 tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,
83 pointer, DEMO_STACK_SIZE,
84 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
85 pointer = pointer + DEMO_STACK_SIZE;
86
87 /* Initialize the NetX system. */
88 nx_system_initialize();
89
90 /* Create the client packet pool. */
91 status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
92 pointer = pointer + NX_PACKET_POOL_SIZE;
93
94 /* Check for pool creation error. */
95 if (status)
96 error_counter++;
97
98 /* Create the server packet pool. */
99 status = nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
100 pointer = pointer + NX_PACKET_POOL_SIZE;
101
102 /* Check for pool creation error. */
103 if (status)
104 error_counter++;
105
106 /* Create an IP instance for the DHCP Client. */
107 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);
108
109 pointer = pointer + 2048;
110
111 /* Check for IP create errors. */
112 if (status)
113 error_counter++;
114
115 /* Create an IP instance for the DHCP Server. */
116 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);
117
118 pointer = pointer + 2048;
119
120 /* Check for IP create errors. */
121 if (status)
122 error_counter++;
123
124 /* Enable ARP and supply ARP cache memory for DHCP Client IP. */
125 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
126 pointer = pointer + 1024;
127
128 /* Check for ARP enable errors. */
129 if (status)
130 error_counter++;
131
132 /* Enable ARP and supply ARP cache memory for DHCP Server IP. */
133 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
134 pointer = pointer + 1024;
135
136 /* Check for ARP enable errors. */
137 if (status)
138 error_counter++;
139
140 /* Enable UDP traffic. */
141 status = nx_udp_enable(&client_ip);
142
143 /* Check for UDP enable errors. */
144 if (status)
145 error_counter++;
146
147 /* Enable UDP traffic. */
148 status = nx_udp_enable(&server_ip);
149
150 /* Check for UDP enable errors. */
151 if (status)
152 error_counter++;
153
154 /* Enable ICMP. */
155 status = nx_icmp_enable(&client_ip);
156
157 /* Check for errors. */
158 if (status)
159 error_counter++;
160
161 /* Enable ICMP. */
162 status = nx_icmp_enable(&server_ip);
163
164 /* Check for errors. */
165 if (status)
166 error_counter++;
167
168 return;
169 }
170
171 /* Define the test threads. */
172
server_thread_entry(ULONG thread_input)173 void server_thread_entry(ULONG thread_input)
174 {
175
176 UINT status;
177 UINT iface_index;
178 UINT addresses_added;
179
180 printf("NetX Test: DHCP 04_03_05_01 Test.....................................");
181
182 /* Create the DHCP Server. */
183 status = nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE,
184 "DHCP Server", &server_pool);
185
186 pointer = pointer + DEMO_STACK_SIZE;
187
188 /* Check for errors creating the DHCP Server. */
189 if (status)
190 error_counter++;
191
192 /* Load the assignable DHCP IP addresses for the first interface. */
193 iface_index = 0;
194
195 status = nx_dhcp_create_server_ip_address_list(&dhcp_server, iface_index, START_IP_ADDRESS_LIST_0,
196 END_IP_ADDRESS_LIST_0, &addresses_added);
197
198 /* Check for errors creating the list. */
199 if (status)
200 error_counter++;
201
202 /* Verify all the addresses were added to the list. */
203 if (addresses_added != 10)
204 error_counter++;
205
206 status = nx_dhcp_set_interface_network_parameters(&dhcp_server, iface_index, NX_DHCP_SUBNET_MASK_0,
207 NX_DHCP_DEFAULT_GATEWAY_0, NX_DHCP_DNS_SERVER_0);
208
209 /* Check for errors setting network parameters. */
210 if (status)
211 error_counter++;
212
213 /* Start DHCP Server task. */
214 status = nx_dhcp_server_start(&dhcp_server);
215
216 /* Check for errors starting up the DHCP server. */
217 if (status)
218 error_counter++;
219
220 tx_thread_sleep(10 * NX_IP_PERIODIC_RATE);
221
222 if((error_counter) || (dhcp_inform_count != 1) || (dhcp_ack_flag == 0))
223 {
224 printf("ERROR!\n");
225 test_control_return(1);
226 }
227 else
228 {
229 printf("SUCCESS!\n");
230 test_control_return(0);
231 }
232
233 return;
234 }
235
236 /* Define the test threads. */
237
client_thread_entry(ULONG thread_input)238 void client_thread_entry(ULONG thread_input)
239 {
240
241 UINT status;
242
243 dhcp_ack_flag = 0;
244 dhcp_inform_count = 0;
245
246 /* Create the DHCP instance. */
247 status = nx_dhcp_create(&dhcp_client, &client_ip, "dhcp_client");
248 if(status)
249 error_counter++;
250
251 #ifdef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL
252 status = nx_dhcp_packet_pool_set(&dhcp_client, &client_pool);
253 if (status)
254 error_counter++;
255 #endif /* NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL */
256
257 /* Start the DHCP Client. */
258 status = nx_dhcp_start(&dhcp_client);
259 if(status)
260 error_counter++;
261
262 /* Check for address resolution. */
263 status = nx_ip_status_check(&client_ip, NX_IP_ADDRESS_RESOLVED, (ULONG *)&status, 10 * NX_IP_PERIODIC_RATE);
264 if(status)
265 error_counter++;
266
267 advanced_packet_process_callback = my_packet_process;
268 client_ip.nx_ip_udp_packet_receive = my_udp_packet_receive;
269
270 /* Send DHCP Information message. */
271 status = nx_dhcp_send_request(&dhcp_client, NX_DHCP_TYPE_DHCPINFORM);
272 if(status)
273 error_counter++;
274
275 /* Stopping the DHCP client. */
276 nx_dhcp_stop(&dhcp_client);
277
278 /* All done. Return resources to NetX and ThreadX. */
279 nx_dhcp_delete(&dhcp_client);
280
281 return;
282 }
283
284
my_packet_process(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)285 static UINT my_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
286 {
287
288 UINT status;
289 ULONG message_type;
290 NX_UDP_HEADER *udp_header;
291 ULONG src_dst_port;
292
293
294 udp_header = (NX_UDP_HEADER*)((packet_ptr -> nx_packet_prepend_ptr) + 20);
295 src_dst_port = udp_header -> nx_udp_header_word_0;
296 NX_CHANGE_ULONG_ENDIAN(src_dst_port);
297
298 /* client port 68(0x44), server port 67(0x43). packet sent to server from client*/
299 if(src_dst_port == 0x00440043)
300 {
301 /* Get the dhcp message type. */
302 status = dhcp_get_option_value((packet_ptr -> nx_packet_prepend_ptr + 20 + 8), NX_DHCP_SERVER_OPTION_DHCP_TYPE,
303 &message_type, (packet_ptr -> nx_packet_length - 20 - 8));
304 if(status)
305 error_counter++;
306
307 /* Check if the message is a DHCPREQUEST. */
308 if(message_type == NX_DHCP_TYPE_DHCPINFORM)
309 {
310 dhcp_inform_count = 1;
311
312 }
313 }
314 return NX_TRUE;
315
316 }
my_udp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)317 void my_udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
318 {
319
320 UINT status;
321 ULONG message_type;
322 ULONG lease_time;
323 ULONG yiaddr;
324
325
326 /* Get the dhcp message type. */
327 status = dhcp_get_option_value((packet_ptr -> nx_packet_prepend_ptr + 8), NX_DHCP_SERVER_OPTION_DHCP_TYPE,
328 &message_type, (packet_ptr -> nx_packet_length - 8));
329 if(status)
330 error_counter++;
331
332 /* Check if the message is a DHCPACK and INFORM has be sent. */
333 if((message_type == NX_DHCP_TYPE_DHCPACK) && (dhcp_inform_count == 1))
334 {
335
336 dhcp_ack_flag = 1;
337
338 /* Get the dhcp message type. */
339 status = dhcp_get_option_value((packet_ptr -> nx_packet_prepend_ptr + 8), NX_DHCP_SERVER_OPTION_DHCP_TYPE,
340 &message_type, (packet_ptr -> nx_packet_length - 8));
341 if(status)
342 error_counter++;
343
344
345 /* Get the dhcp lease time. */
346 status = dhcp_get_option_value((packet_ptr -> nx_packet_prepend_ptr + 8), NX_DHCP_OPTION_DHCP_LEASE,
347 &lease_time, (packet_ptr -> nx_packet_length - 8));
348 if((status != NX_OPTION_ERROR) ||
349 ((status == NX_SUCCESS) && (lease_time != 0)))
350 error_counter++;
351
352 /* Get yiaddr field value. */
353 yiaddr = dhcp_get_data((packet_ptr -> nx_packet_prepend_ptr + 20 + 8 + NX_BOOTP_OFFSET_YOUR_IP), 4);
354 if(yiaddr != 0)
355 error_counter++;
356
357 /* Restore the udp packet receiving function. */
358 client_ip.nx_ip_udp_packet_receive = _nx_udp_packet_receive;
359 }
360
361 /* Let server receives the packet. */
362 _nx_udp_packet_receive(ip_ptr, packet_ptr);
363 }
364 #else
365
366 #ifdef CTEST
test_application_define(void * first_unused_memory)367 VOID test_application_define(void *first_unused_memory)
368 #else
369 void netx_dhcp_04_03_05_01_test_application_define(void *first_unused_memory)
370 #endif
371 {
372
373 /* Print out test information banner. */
374 printf("NetX Test: NetX DHCP 04_03_05_01 Test................................N/A\n");
375
376 test_control_return(3);
377 }
378 #endif