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