1 
2 #include   "tx_api.h"
3 #include   "nx_api.h"
4 #include   "nxd_dhcp_client.h"
5 #include   "nxd_dhcp_server.h"
6 
7 extern void    test_control_return(UINT status);
8 
9 #if !defined(NX_DISABLE_IPV4)
10 
11 #define     DEMO_STACK_SIZE             4096
12 #define     NX_PACKET_SIZE              1536
13 #define     NX_PACKET_POOL_SIZE         NX_PACKET_SIZE * 8
14 
15 #define     NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(10,0,0,1)
16 #define     START_IP_ADDRESS_LIST_0     IP_ADDRESS(10,0,0,2)
17 #define     END_IP_ADDRESS_LIST_0       IP_ADDRESS(10,0,0,5)
18 
19 
20 typedef struct DHCP_TEST_STRUCT
21 {
22     char          *dhcp_test_pkt_data;
23     int           dhcp_test_pkt_size;
24 } DHCP_TEST;
25 
26 #define CLIENT_MSG_COUNT    2
27 static  DHCP_TEST           dhcp_test[CLIENT_MSG_COUNT];
28 UINT    client_complete = NX_FALSE;
29 
30 /* Define the ThreadX and NetX object control blocks...  */
31 static TX_THREAD               client_thread;
32 static NX_PACKET_POOL          client_pool;
33 static NX_IP                   client_ip;
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 static NX_UDP_SOCKET           client_socket;
40 
41 /* Define the counters used in the demo application...  */
42 
43 static ULONG                   error_counter;
44 static CHAR                    *pointer;
45 
46 /* Define thread prototypes.  */
47 
48 static void    server_thread_entry(ULONG thread_input);
49 static void    client_thread_entry(ULONG thread_input);
50 
51 /******** Optionally substitute your Ethernet driver here. ***********/
52 extern void    _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req);
53 static UINT    nx_dhcp_response_packet_send(NX_UDP_SOCKET *client_socket, UINT packet_number);
54 static void    dhcp_test_initialize();
55 
56 /* Frame (366 bytes) */
57 static char discover[366] = {
58 0x01, 0x01,                                     /* .C.4.... */
59 0x06, 0x00, 0x42, 0x2a, 0x4c, 0xf5, 0x00, 0x00, /* ..B*L... */
60 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
62 0x00, 0x00, 0x80, 0x86, 0xf2, 0x83, 0x15, 0xd5, /* ........ */
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
88 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, /* ..c.Sc5. */
89 0x01, 0x3d, 0x07, 0x01, 0x80, 0x86, 0xf2, 0x83, /* .=...... */
90 0x15, 0xd5, 0x0c, 0x06, 0x57, 0x59, 0x2d, 0x50, /* ....WY-P */
91 0x53, 0x54, 0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, /* ST<.MSFT */
92 0x20, 0x35, 0x2e, 0x30, 0x37, 0x0c, 0x01, 0x0f, /*  5.07... */
93 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, 0x79, /* ..,./.!y */
94 0xf9, 0x2b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, /* .+...... */
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* ...... */
97 };
98 
99 static int discover_size = 304;
100 
101 /* Frame (385 bytes) */
102 static char request[385] = {
103 0x01, 0x01,                                     /* .C.GO... */
104 0x06, 0x00, 0x42, 0x2a, 0x4c, 0xf5, 0x04, 0x00, /* ..B*L... */
105 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
107 0x00, 0x00, 0x80, 0x86, 0xf2, 0x83, 0x15, 0xd5, /* ........ */
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
133 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, /* ..c.Sc5. */
134 0x03, 0x3d, 0x07, 0x01, 0x80, 0x86, 0xf2, 0x83, /* .=...... */
135 0x15, 0xd5, 0x32, 0x04, 0x0a, 0x00, 0x00, 0x02, /* ..2..... */
136 0x36, 0x04, 0x0a, 0x00, 0x00, 0x01, 0x0c, 0x06, /* 6....... */
137 0x57, 0x59, 0x2d, 0x50, 0x53, 0x54, 0x51, 0x14, /* WY-PSTQ. */
138 0x00, 0x00, 0x00, 0x57, 0x59, 0x2d, 0x50, 0x53, /* ...WY-PS */
139 0x54, 0x2e, 0x66, 0x63, 0x69, 0x2e, 0x73, 0x6d, /* T.fci.sm */
140 0x69, 0x2e, 0x61, 0x64, 0x3c, 0x08, 0x4d, 0x53, /* i.ad<.MS */
141 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, 0x37, 0x0c, /* FT 5.07. */
142 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, /* ....,./. */
143 0x21, 0x79, 0xf9, 0x2b, 0x00, 0x00, 0x00, 0x01, /* !y.+.... */
144 0x00                                            /* . */
145 };
146 
147 static int request_size = 323;
148 
149 
150 /* Define what the initial system looks like.  */
151 
152 #ifdef CTEST
test_application_define(void * first_unused_memory)153 VOID test_application_define(void *first_unused_memory)
154 #else
155 void    netx_dhcp_server_improper_term_test_application_define(void *first_unused_memory)
156 #endif
157 {
158 
159 UINT    status;
160 
161 
162     /* Setup the working pointer.  */
163     pointer =  (CHAR *) first_unused_memory;
164 
165     /* Create the client thread.  */
166     tx_thread_create(&client_thread, "thread client", client_thread_entry, 0,
167             pointer, DEMO_STACK_SIZE,
168             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
169     pointer =  pointer + DEMO_STACK_SIZE;
170 
171     /* Create the server thread.  */
172     tx_thread_create(&server_thread, "thread server", server_thread_entry, 0,
173             pointer, DEMO_STACK_SIZE,
174             3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
175     pointer =  pointer + DEMO_STACK_SIZE;
176 
177     /* Initialize the NetX system.  */
178     nx_system_initialize();
179 
180     /* Create the client packet pool.  */
181     status =  nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
182     pointer = pointer + NX_PACKET_POOL_SIZE;
183 
184     /* Check for pool creation error.  */
185     if (status)
186         error_counter++;
187 
188     /* Create the server packet pool.  */
189     status =  nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE);
190     pointer = pointer + NX_PACKET_POOL_SIZE;
191 
192     /* Check for pool creation error.  */
193     if (status)
194         error_counter++;
195 
196     /* Create an IP instance for the DHCP Client.  */
197     status = nx_ip_create(&client_ip, "DHCP Client", IP_ADDRESS(0, 0, 0, 0), 0xFFFFFF00UL, &client_pool,
198                           _nx_ram_network_driver_1024, pointer, 2048, 1);
199 
200     pointer =  pointer + 2048;
201 
202     /* Check for IP create errors.  */
203     if (status)
204         error_counter++;
205 
206     /* Create an IP instance for the DHCP Server.  */
207     status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool,
208                           _nx_ram_network_driver_1024, pointer, 2048, 1);
209 
210     pointer =  pointer + 2048;
211 
212     /* Check for IP create errors.  */
213     if (status)
214         error_counter++;
215 
216     /* Enable ARP and supply ARP cache memory for DHCP Client IP.  */
217     status =  nx_arp_enable(&client_ip, (void *) pointer, 1024);
218     pointer = pointer + 1024;
219 
220     /* Check for ARP enable errors.  */
221     if (status)
222         error_counter++;
223 
224     /* Enable ARP and supply ARP cache memory for DHCP Server IP.  */
225     status =  nx_arp_enable(&server_ip, (void *) pointer, 1024);
226     pointer = pointer + 1024;
227 
228     /* Check for ARP enable errors.  */
229     if (status)
230         error_counter++;
231 
232     /* Enable UDP traffic.  */
233     status =  nx_udp_enable(&client_ip);
234 
235     /* Check for UDP enable errors.  */
236     if (status)
237         error_counter++;
238 
239     /* Enable UDP traffic.  */
240     status =  nx_udp_enable(&server_ip);
241 
242     /* Check for UDP enable errors.  */
243     if (status)
244         error_counter++;
245 
246     /* Enable ICMP.  */
247     status =  nx_icmp_enable(&client_ip);
248 
249     /* Check for errors.  */
250     if (status)
251         error_counter++;
252 
253     /* Enable ICMP.  */
254     status =  nx_icmp_enable(&server_ip);
255 
256     /* Check for errors.  */
257     if (status)
258         error_counter++;
259 
260     return;
261 }
262 
263 /* Define the test threads.  */
264 
server_thread_entry(ULONG thread_input)265 void    server_thread_entry(ULONG thread_input)
266 {
267 
268 UINT        status;
269 UINT        iface_index;
270 UINT        addresses_added;
271 
272     printf("NetX Test:   DHCP Server Improper Termination Test.....................");
273 
274     /* Check for earlier errors.  */
275     if(error_counter)
276     {
277         printf("ERROR!\n");
278         test_control_return(1);
279     }
280 
281     /* Create the DHCP Server.  */
282     status =  nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE,  "DHCP Server", &server_pool);
283 
284     pointer = pointer + DEMO_STACK_SIZE;
285 
286     /* Check for errors creating the DHCP Server. */
287     if (status)
288         error_counter++;
289 
290     /* Load the assignable DHCP IP addresses for the first interface.  */
291     iface_index = 0;
292 
293     status = nx_dhcp_create_server_ip_address_list(&dhcp_server, iface_index, START_IP_ADDRESS_LIST_0,
294                                                    END_IP_ADDRESS_LIST_0, &addresses_added);
295 
296     /* Check for errors creating the list. */
297     if (status)
298     {
299         error_counter++;
300     }
301 
302     /* Verify all the addresses were added to the list. */
303     if (addresses_added != 4)
304     {
305         error_counter++;
306     }
307 
308     /* Start DHCP Server task.  */
309     status = nx_dhcp_server_start(&dhcp_server);
310 
311     /* Check for errors starting up the DHCP server.  */
312     if (status)
313     {
314         error_counter++;
315     }
316 
317     while(!client_complete)
318         tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
319 
320     /* Check that the server did not receive a valid request */
321     if (dhcp_server.nx_dhcp_requests_received > 0)
322     {
323         error_counter++;
324     }
325 
326     if (error_counter)
327     {
328         printf("ERROR!\n");
329         test_control_return(1);
330     }
331     else
332     {
333         printf("SUCCESS!\n");
334         test_control_return(0);
335     }
336 
337     return;
338 }
339 
340 
341 /* This thread task simulates DHCP Client sending requests. */
client_thread_entry(ULONG thread_input)342 void    client_thread_entry(ULONG thread_input)
343 {
344 
345 NX_PACKET   *my_packet;
346 UINT        i;
347 ULONG      actual_status;
348 UINT       status;
349 
350 
351     /* Check for earlier errors.  */
352     if(error_counter)
353     {
354         client_complete = NX_TRUE;
355         return;
356     }
357 
358 #ifdef FEATURE_NX_IPV6
359     /* Sleep 4 seconds to finish DAD.  */
360    tx_thread_sleep(4 * NX_IP_PERIODIC_RATE);
361 #endif /* FEATURE_NX_IPV6 */
362 
363     /* Ensure the IP instance has been initialized.  */
364     status = nx_ip_status_check(&server_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
365 
366     /* Check status...*/
367     if(status != NX_SUCCESS)
368     {
369         error_counter++;
370         return;
371     }
372 
373     /* Load up the Client messages. */
374     dhcp_test_initialize();
375 
376     status = nx_udp_socket_create(&client_ip, &client_socket, "Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
377 
378     /* Check status.  */
379     if (status)
380     {
381         error_counter++;
382     }
383 
384     /* Bind the UDP socket to the IP port.  */
385     status =  nx_udp_socket_bind(&client_socket, 68, TX_WAIT_FOREVER);
386 
387     /* Check status.  */
388     if (status)
389     {
390         error_counter++;
391         return;
392     }
393 
394     /* Act as the DHCP Client to send DHCP discover and request packets.  */
395     for (i = 0; i < CLIENT_MSG_COUNT; i++ )
396     {
397 
398         /* Send the DHCP client packet.  */
399         status = nx_dhcp_response_packet_send(&client_socket,  i);
400 
401         /* Check status.  */
402         if (status)
403         {
404             error_counter++;
405         }
406 
407         /* Receive a UDP packet.  */
408         status =  nx_udp_socket_receive(&client_socket, &my_packet, NX_IP_PERIODIC_RATE);
409 
410         /* Check status.  */
411         if (status)
412         {
413 
414             if (i == 1)
415             {
416 
417                 /* This is correct. The Client should not get a message because the server rejected the request packet. */
418             }
419             else /* i == 0*/
420             {
421                 /* There should be a response to the discovery message, so this is an error. */
422                 error_counter++;
423                 continue;
424             }
425 
426         }
427         else
428         {
429             nx_packet_release(my_packet);
430         }
431 
432     }
433 
434     status = nx_udp_socket_unbind(&client_socket);
435 
436     /* Delete the UDP socket.  */
437     status |=  nx_udp_socket_delete(&client_socket);
438 
439     /* Check status.  */
440     if (status)
441     {
442         error_counter++;
443     }
444 
445     client_complete = NX_TRUE;
446 }
447 
448 
nx_dhcp_response_packet_send(NX_UDP_SOCKET * client_socket,UINT packet_number)449 static UINT   nx_dhcp_response_packet_send(NX_UDP_SOCKET *client_socket, UINT packet_number)
450 {
451 
452 UINT        status;
453 NX_PACKET   *client_packet;
454 
455 
456 
457     /* Allocate a response packet.  */
458     status =  nx_packet_allocate(&client_pool, &client_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
459 
460     /* Check status.  */
461     if (status)
462     {
463         error_counter++;
464         return status;
465     }
466 
467     memset(client_packet -> nx_packet_prepend_ptr, 0, (client_packet -> nx_packet_data_end - client_packet -> nx_packet_prepend_ptr));
468 
469     /* Write the DHCP Client messages into the packet payload!  */
470     memcpy(client_packet -> nx_packet_prepend_ptr,
471            dhcp_test[packet_number].dhcp_test_pkt_data,
472            dhcp_test[packet_number].dhcp_test_pkt_size);
473 
474     /* Adjust the write pointer.  */
475     client_packet -> nx_packet_length =  dhcp_test[packet_number].dhcp_test_pkt_size;
476     client_packet -> nx_packet_append_ptr =  client_packet -> nx_packet_prepend_ptr + client_packet -> nx_packet_length;
477 
478     /* Send the UDP packet with the correct port.  */
479     status =  nx_udp_socket_send(client_socket, client_packet, IP_ADDRESS(255,255,255,255), 67);
480     /* Check the status.  */
481     if (status)
482     {
483         error_counter++;
484         nx_packet_release(client_packet);
485     }
486 
487     return status;
488 }
489 
dhcp_test_initialize()490 static void dhcp_test_initialize()
491 {
492     dhcp_test[0].dhcp_test_pkt_data = &discover[0];
493     dhcp_test[0].dhcp_test_pkt_size = discover_size;
494     dhcp_test[1].dhcp_test_pkt_data = &request[0];
495     dhcp_test[1].dhcp_test_pkt_size = request_size;
496 
497 
498 }
499 #else
500 
501 #ifdef CTEST
test_application_define(void * first_unused_memory)502 VOID test_application_define(void *first_unused_memory)
503 #else
504 void    netx_dhcp_server_improper_term_test_application_define(void *first_unused_memory)
505 #endif
506 {
507 
508     /* Print out test information banner.  */
509     printf("NetX Test:   NetX DHCP Server Improper Termination Test................N/A\n");
510 
511     test_control_return(3);
512 }
513 #endif
514