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