/***************************************************************************/ /* Copyright (c) 2024 Microsoft Corporation */ /* Copyright (c) 2026 Eclipse ThreadX contributors */ /* */ /* This program and the accompanying materials are made available under */ /* the terms of the MIT License which is available at */ /* https://opensource.org/licenses/MIT. */ /* */ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ /* Test the DHCP CLient with 2 physical interfaces, set NX_DHCP_CLIENT_MAX_INTERFACES = 2 and run the demo. Note because of limitations of the ram driver there is some code in nx_dhcp_received_data_process in the nxd_dhcp_client.c to switch packets that should be stamped for the secondary interface. Note to that DHCP Client is modified in nx_dhcp_start() to set the XID arbitrarily. This simply facilitates using the server responses (using "C arrays" from a real packet trace).*/ #include "tx_api.h" #include "nx_api.h" #include "nxd_dhcp_client.h" #include "nx_ram_network_driver_test_1500.h" #define DEMO_STACK_SIZE 4096 #define PACKET_PAYLOAD 1518 extern NX_PACKET *packet_copy; /* Define the ThreadX, NetX object control blocks... */ NX_UDP_SOCKET server_socket0; TX_THREAD server_thread0; TX_THREAD client_thread0; NX_PACKET_POOL client_pool; NX_PACKET_POOL server_pool; NX_IP client_ip; NX_IP server_ip0; /* Define the NetX FTP object control block. */ NX_DHCP dhcp_client; typedef struct DHCP_RESPONSE_STRUCT { char *dhcp_response_pkt_data; int dhcp_response_pkt_size; } DHCP_RESPONSE; #define NUM_RESPONSES 7 // offer, ack, ack for renew for both interfaces // set to 7 to include an additional ack for rebind request on interface 0 static DHCP_RESPONSE dhcp_response[NUM_RESPONSES]; /* Define the counters used in the demo application... */ static UINT error_counter = 0; static UINT client_running = NX_FALSE; static UINT state_changes[2] = {0,0}; static UINT renews[2] = {0,0}; static UINT rebinds[2] = {0,0}; static UINT bounds[2] = {0,0}; #define SERVER_PORT 67 /* Replace the 'ram' driver with your Ethernet driver. */ extern VOID nx_driver_ram_driver(NX_IP_DRIVER*); void server0_thread_entry(ULONG thread_input); void client0_thread_entry(ULONG thread_input); static UINT nx_dhcp_response_packet_send(NX_UDP_SOCKET *socket_ptr, UINT port, INT packet_number, UINT iface_index); static void dhcp_test_initialize(); static void dhcp_interface_state_change0(NX_DHCP *dhcp_ptr, UCHAR new_state); static void dhcp_interface_state_change1(NX_DHCP *dhcp_ptr, UCHAR new_state); extern void test_control_return(UINT); extern void _nx_ram_network_driver_1024(NX_IP_DRIVER *driver_req_ptr); char offer_response[300] = { 0x02, 0x01, 0x06, 0x00, 0x31, 0x9D, /* {.....T. */ 0x58, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x02, 0x02, 0xf7, 0xc0, 0x02, /* ........ */ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x02, 0x01, 0x04, 0xff, /* Sc5..... */ 0xff, 0xff, 0x00, 0x3a, 0x04, 0x00, 0x06, 0xac, /* ...:.... */ 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, 0x0a, 0x33, /* .;.....3 */ 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, 0x04, 0xc0, /* ...Y06.. */ 0x02, 0x02, 0x01, 0x03, 0x04, 0xc0, 0x02, 0x02, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x02, 0x02, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int offer_response_size = 300; /* Frame (342 bytes) */ char ack_response[300] = { 0x02, 0x01, 0x06, 0x00, 0x31, 0x9D, /* {.....T. */ 0x58, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x02, 0x02, 0xf7, 0xc0, 0x02, /* ........ */ 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a, 0x04, 0x00, /* Sc5..:.. */ 0x06, 0xac, 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, /* ...;.... */ 0x0a, 0x33, 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, /* .3...Y06 */ 0x04, 0xc0, 0x02, 0x02, 0x01, 0x01, 0x04, 0xff, /* ........ */ 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0x02, 0x02, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x02, 0x02, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int ack_response_size = 300; /* Frame (342 bytes) */ static char renew_response[300] = { 0x02, 0x01, 0x06, 0x00, 0x31, 0x9D, /* :.....T. */ 0x58, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x02, 0x02, 0xf8, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a, 0x04, 0x00, /* Sc5..:.. */ 0x05, 0xac, 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, /* ...;.... */ 0x0a, 0x33, 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, /* .3...Y06 */ 0x04, 0xc0, 0x02, 0x02, 0x01, 0x01, 0x04, 0xff, /* ........ */ 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0x02, 0x02, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x02, 0x02, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int renew_response_size = 300; /* Frame (342 bytes) */ static char rebind_response[300] = { 0x02, 0x01, 0x06, 0x00, 0x31, 0x9D, /* g.....T. */ 0x58, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x02, 0x02, 0xf9, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x58, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a, 0x04, 0x00, /* Sc5..:.. */ 0x07, 0xac, 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, /* ...;.... */ 0x0a, 0x33, 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, /* .3...Y06 */ 0x04, 0xc0, 0x02, 0x02, 0x01, 0x01, 0x04, 0xff, /* ........ */ 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0x02, 0x02, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x02, 0x02, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int rebind_response_size = 300; /* Responses from server on interface 1 */ char offer_response1[300] = { 0x02, 0x01, 0x06, 0x00, 0x2a, 0x3e, /* {.....T. */ 0xf0, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x01, 0x01, 0xf7, 0xc0, 0x01, /* ........ */ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x59, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x02, 0x01, 0x04, 0xff, /* Sc5..... */ 0xff, 0xff, 0x00, 0x3a, 0x04, 0x00, 0x06, 0xac, /* ...:.... */ 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, 0x0a, 0x33, /* .;.....3 */ 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, 0x04, 0xc0, /* ...Y06.. */ 0x01, 0x01, 0x01, 0x03, 0x04, 0xc0, 0x01, 0x01, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x01, 0x01, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int offer_response1_size = 300; /* Frame (342 bytes) */ char ack_response1[300] = { 0x02, 0x01, 0x06, 0x00, 0x2a, 0x3e, /* {.....T. */ 0xf0, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x01, 0x01, 0xf7, 0xc0, 0x01, /* ........ */ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x59, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a, 0x04, 0x00, /* Sc5..:.. */ 0x06, 0xac, 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, /* ...;.... */ 0x0a, 0x33, 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, /* .3...Y06 */ 0x04, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x04, 0xff, /* ........ */ 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0x01, 0x01, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x01, 0x01, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int ack_response1_size = 300; /* Frame (342 bytes) */ static char renew_response1[300] = { 0x02, 0x01, 0x06, 0x00, 0x2a, 0x3e, /* :.....T. */ 0xf0, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0xc0, 0x01, 0x01, 0xf8, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, /* ........ */ 0x22, 0x33, 0x44, 0x59, 0x00, 0x00, 0x00, 0x00, /* T....... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, /* ......c. */ 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a, 0x04, 0x00, /* Sc5..:.. */ 0x05, 0xac, 0x98, 0x3b, 0x04, 0x00, 0x0b, 0xae, /* ...;.... */ 0x0a, 0x33, 0x04, 0x00, 0x0d, 0x59, 0x30, 0x36, /* .3...Y06 */ 0x04, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x04, 0xff, /* ........ */ 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, 0x01, 0x01, /* ........ */ 0x01, 0x06, 0x04, 0xc0, 0x01, 0x01, 0x01, 0xff, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static int renew_response1_size = 300; /* Define what the initial system looks like. */ #ifdef CTEST VOID test_application_define(void *first_unused_memory) #else void netx_dhcp_cilent_two_interface_test_application_define(void *first_unused_memory) #endif { UINT status; UCHAR *pointer; /* Setup the working pointer. */ pointer = (UCHAR *) first_unused_memory; /* Initialize NetX. */ nx_system_initialize(); /* Set up the FTP Server. */ /* Create the main server thread. */ status = tx_thread_create(&server_thread0, "Server0 thread ", server0_thread_entry, 0, pointer, DEMO_STACK_SIZE, 6, 6, TX_NO_TIME_SLICE, TX_AUTO_START); pointer = pointer + DEMO_STACK_SIZE ; /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } /* Create the server packet pool. */ status = nx_packet_pool_create(&server_pool, "Server Packet Pool", 700, pointer , 700*10); pointer = pointer + 700*10; if (status) error_counter++; /* Create an IP instance. */ status = nx_ip_create(&server_ip0, "Server IP", IP_ADDRESS(192,2,2,1), 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024, pointer, DEMO_STACK_SIZE, 1); pointer = pointer + DEMO_STACK_SIZE; if (status) error_counter++; status = nx_ip_interface_attach(&server_ip0, "Server1 interface", IP_ADDRESS(192,1,1,1), 0xFFFFFF00UL, _nx_ram_network_driver_1024); /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } /* Enable ARP and supply ARP cache memory for the server IP instance. */ status = nx_arp_enable(&server_ip0, (void *) pointer, 1024); pointer = pointer + 1024; if (status) error_counter++; /* Enable UDP traffic. */ status = nx_udp_enable(&server_ip0); if (status) error_counter++; /* Set up the Client. */ /* Create the main client thread. */ status = tx_thread_create(&client_thread0, "Client thread ", client0_thread_entry, 0, pointer, DEMO_STACK_SIZE, 6, 6, TX_NO_TIME_SLICE, TX_AUTO_START); pointer = pointer + DEMO_STACK_SIZE ; /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } /* Create a packet pool for the client. */ status = nx_packet_pool_create(&client_pool, "Client Packet Pool", PACKET_PAYLOAD, pointer, 25*PACKET_PAYLOAD); /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } pointer = pointer + 25*PACKET_PAYLOAD; /* Create an IP instance for the client. */ status = nx_ip_create(&client_ip, "Client0 IP", IP_ADDRESS(0,0,0,0), 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024, pointer, 2048, 1); /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } pointer = pointer + 2048; status = nx_ip_interface_attach(&client_ip, "Client1 IP", IP_ADDRESS(0,0,0,0), 0xFFFFFF00UL, _nx_ram_network_driver_1024); /* Check status. */ if (status != NX_SUCCESS) { error_counter++; return; } /* Enable ARP and supply ARP cache memory for the Client IP. */ nx_arp_enable(&client_ip, (void *) pointer, 1024); pointer = pointer + 1024; /* Enable UDP for client IP instance. */ nx_udp_enable(&client_ip); nx_icmp_enable(&client_ip); return; } /* Define the main DHCP client thread. */ void client0_thread_entry(ULONG thread_input) { UINT status; tx_thread_sleep(20); /* Create the DHCP instance. */ status = nx_dhcp_create(&dhcp_client, &client_ip, "dhcp0"); if (status) error_counter++; status = nx_dhcp_packet_pool_set(&dhcp_client, &client_pool); if (status) error_counter++; /* Register state change variable. */ status = nx_dhcp_interface_state_change_notify(&dhcp_client, 0, dhcp_interface_state_change0); if (status) error_counter++; /* Register state change variable. */ status = nx_dhcp_interface_state_change_notify(&dhcp_client, 1, dhcp_interface_state_change1); if (status) error_counter++; printf("Start the client\n\n"); /* Start the DHCP Client. */ status = nx_dhcp_start(&dhcp_client); if (status) error_counter++; while(client_running == NX_FALSE) { tx_thread_sleep(100); } } /* Define the helper DHCP server thread on interface 0. */ void server0_thread_entry(ULONG thread_input) { UINT status; NX_PACKET *my_packet; UINT i, j, k; /* Print out test information banner. */ printf("NetX Test: DHCP Client Two Interface Test............................\n"); /* Check for earlier error. */ if(error_counter) { printf("ERROR!\n"); test_control_return(1); } /* Create a socket as the server. */ status = nx_udp_socket_create(&server_ip0, &server_socket0, "Server0 socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 5); /* Check status. */ if (status) { error_counter++; } status = nx_udp_socket_bind(&server_socket0, NX_DHCP_SERVER_UDP_PORT, TX_WAIT_FOREVER); /* Check status. */ if (status) { error_counter++; } /* Load up the server 'responses'. */ dhcp_test_initialize(); i = 0; j = 4; // index into array of responses to send from interface server 1 k = 0; // count of packets received on interface 1 /* Wait for Client requests */ //while (i < 3) // Reduce this to see client packet retransmissions while (i < NUM_RESPONSES) { status = nx_udp_socket_receive(&server_socket0, &my_packet, 10 * NX_IP_PERIODIC_RATE); /* Check status. */ if (status) { printf("ERRO7R on 0!\n"); error_counter++; } else { ULONG source_ip_address; UINT protocol; UINT source_port; UINT iface_index; UCHAR *work_ptr = my_packet -> nx_packet_prepend_ptr + 4; ULONG *id = (ULONG *)work_ptr; NX_CHANGE_ULONG_ENDIAN(*id); status = nx_udp_packet_info_extract(my_packet, &source_ip_address, &protocol, &source_port, &iface_index); if ((iface_index == 1) && (*id != 0x2a3ef01d)) { /* This packet is really intended for the server on the primary interface. */ my_packet -> nx_packet_ip_interface = &(server_ip0.nx_ip_interface[0]); iface_index = 0; } else if ((iface_index == 0) && (*id != 0x319d58a2)) { /* This packet is really intended for server on secondary interface. */ my_packet -> nx_packet_ip_interface = &(server_ip0.nx_ip_interface[1]); iface_index = 1; } /* Is this packet from the client on interface 1? */ if (*id == 0x2a3ef01d) { // do this silliness to drop server packets if (i != 1) { ////////// /* Yes, make sure to send it out on interface 1. */ printf("Server 1 got %dth packet. Send %d packet back\n", k, j-4); status = nx_dhcp_response_packet_send(&server_socket0, 68, j, 1); } j++; k++; } else { if (i != 1) { printf("Server 0 got %dth packet\n", i); status = nx_dhcp_response_packet_send(&server_socket0, 68, i, 0); } i++; } nx_packet_release(my_packet); } } printf("0: All done, waiting for client 0 to go away\n"); /* Wait for the client to terminate the connection. */ while(client_running != NX_TRUE) tx_thread_sleep(20); /* Delete the UDP socket. */ nx_udp_socket_delete(&server_socket0); if(error_counter) { printf("ERROR!\n"); test_control_return(1); } else { printf("SUCCESS!\n"); test_control_return(0); }; } static void dhcp_test_initialize() { /* Download data responses */ dhcp_response[0].dhcp_response_pkt_data = &offer_response[0]; dhcp_response[0].dhcp_response_pkt_size = offer_response_size ; dhcp_response[1].dhcp_response_pkt_data = &ack_response[0]; dhcp_response[1].dhcp_response_pkt_size = ack_response_size ; dhcp_response[2].dhcp_response_pkt_data = &renew_response[0]; dhcp_response[2].dhcp_response_pkt_size = renew_response_size ; dhcp_response[3].dhcp_response_pkt_data = &rebind_response[0]; dhcp_response[3].dhcp_response_pkt_size = rebind_response_size ; /* Server on second interface */ dhcp_response[4].dhcp_response_pkt_data = &offer_response1[0]; dhcp_response[4].dhcp_response_pkt_size = offer_response1_size ; dhcp_response[5].dhcp_response_pkt_data = &ack_response1[0]; dhcp_response[5].dhcp_response_pkt_size = ack_response1_size ; dhcp_response[6].dhcp_response_pkt_data = &renew_response1[0]; dhcp_response[6].dhcp_response_pkt_size = renew_response1_size ; } static UINT nx_dhcp_response_packet_send(NX_UDP_SOCKET *server_socket0, UINT port, INT packet_number, UINT iface_index) { UINT status; NX_PACKET *response_packet; UINT local_index; local_index = packet_number; if (iface_index == 1) { local_index = packet_number - 4; } printf("Server %d sends %dth response\n", iface_index, local_index); /* Allocate a response packet. */ status = nx_packet_allocate(&server_pool, &response_packet, NX_TCP_PACKET, TX_WAIT_FOREVER); /* Check status. */ if (status) { error_counter++; } /* Write the response messages into the packet payload! */ memcpy(response_packet -> nx_packet_prepend_ptr, dhcp_response[packet_number].dhcp_response_pkt_data, dhcp_response[packet_number].dhcp_response_pkt_size); /* Adjust the write pointer. */ response_packet -> nx_packet_length = dhcp_response[packet_number].dhcp_response_pkt_size; response_packet -> nx_packet_append_ptr = response_packet -> nx_packet_prepend_ptr + response_packet -> nx_packet_length; if (iface_index == 0) { /* Set driver callback function. */ //advanced_packet_process_callback = advanced_packet_process; /* Send the packet with the correct port. */ status = nx_udp_socket_send(server_socket0, response_packet, 0xFFFFFFFF, 68); } else { /* Send the packet with the correct port. */ //status = nx_udp_socket_send(&server_socket1, response_packet, 0xFFFFFFFF, 68); NXD_ADDRESS temp; temp.nxd_ip_version = NX_IP_VERSION_V4; temp.nxd_ip_address.v4 = 0xFFFFFFFF; status = nxd_udp_socket_source_send(server_socket0, response_packet, &temp, 68, 1); } /* Check the status. */ if (status) nx_packet_release(response_packet); return status; } void dhcp_interface_state_change0(NX_DHCP *dhcp_ptr, UCHAR new_state) { UINT dhcp_state; dhcp_state = (UINT)new_state; /* Increment state changes counter. */ state_changes[0]++; if (dhcp_state == NX_DHCP_STATE_RENEWING) { renews[0]++; } else if (dhcp_state == NX_DHCP_STATE_REBINDING) { rebinds[0]++; } else if (dhcp_state == NX_DHCP_STATE_BOUND) { bounds[0]++; } return; } void dhcp_interface_state_change1(NX_DHCP *dhcp_ptr, UCHAR new_state) { UINT dhcp_state; dhcp_state = (UINT)new_state; /* Increment state changes counter. */ state_changes[1]++; if (dhcp_state == NX_DHCP_STATE_RENEWING) { renews[1]++; } else if (dhcp_state == NX_DHCP_STATE_REBINDING) { rebinds[1]++; } else if (dhcp_state == NX_DHCP_STATE_BOUND) { bounds[1]++; } return; }