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