/***************************************************************************/ /* 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 */ /***************************************************************************/ #include "tx_api.h" #include "nx_api.h" extern void test_control_return(UINT status); #if !defined(NX_DISABLE_IPV4) && defined(NX_DISABLE_UDP_RX_CHECKSUM) #include "nxd_dhcp_client.h" #include "nxd_dhcp_server.h" #define DEMO_STACK_SIZE 4096 #define NX_PACKET_SIZE 1536 #define NX_PACKET_POOL_SIZE NX_PACKET_SIZE * 8 #define NX_DHCP_SERVER_IP_ADDRESS_0 IP_ADDRESS(192, 168, 3, 8) #define START_IP_ADDRESS_LIST_0 IP_ADDRESS(192, 168, 3, 11) #define END_IP_ADDRESS_LIST_0 IP_ADDRESS(192, 168, 3,20) #define NX_DHCP_SUBNET_MASK_0 IP_ADDRESS(255,255,255,0) #define NX_DHCP_DEFAULT_GATEWAY_0 IP_ADDRESS(192, 168, 3, 8) #define NX_DHCP_DNS_SERVER_0 IP_ADDRESS(192, 168, 3, 8) /* Define the ThreadX and NetX object control blocks... */ static NX_PACKET_POOL client_pool; static TX_THREAD server_thread; static NX_PACKET_POOL server_pool; static NX_IP server_ip; static NX_DHCP_SERVER dhcp_server; /* Define the counters used in the demo application... */ static ULONG error_counter; static ULONG resposner_counter; static CHAR *pointer; /* Define thread prototypes. */ static void server_thread_entry(ULONG thread_input); /******** Optionally substitute your Ethernet driver here. ***********/ extern void _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req); /* Frame (342 bytes) DHCP DISCOVER Read overflow. */ static const unsigned char pkt1[342] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x08, 0x00, 0x45, 0x00, /* ...i..E. */ 0x01, 0x48, 0x00, 0x01, 0x00, 0x00, 0x80, 0x11, /* .H...... */ 0x39, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* 9....... */ 0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, /* ...D.C.4 */ 0x83, 0x9e, 0x01, 0x01, 0x06, 0x00, 0x00, 0xf6, /* ........ */ 0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x37, 0x3c, 0x00, 0x00, 0x00, 0x00, /* Sc5..=.. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* .P...i.. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CW-9WDPJ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* V1-GA1<. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MSFT 5.0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7.....,. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* /.!y.+.. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; /* Frame (342 bytes) DHCP DISCOVER Write overflow. */ static const unsigned char pkt2[342] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x08, 0x00, 0x45, 0x00, /* ...i..E. */ 0x01, 0x48, 0x00, 0x01, 0x00, 0x00, 0x80, 0x11, /* .H...... */ 0x39, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* 9....... */ 0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, /* ...D.C.4 */ 0x83, 0x9e, 0x01, 0x01, 0x06, 0x00, 0x00, 0xf6, /* ........ */ 0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x37, 0x14, 0x35, 0x35, 0x35, 0x35, /* Sc5..=.. */ 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, /* .P...i.. */ 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, /* CW-9WDPJ */ 0x56, 0x31, 0x2d, 0x47, 0x41, 0x31, 0x3c, 0x08, /* V1-GA1<. */ 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, /* MSFT 5.0 */ 0x37, 0x0c, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, /* 7.....,. */ 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xff, 0x00, /* /.!y.+.. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; /* Frame (342 bytes) DHCP DISCOVER Endless loop. */ static const unsigned char pkt3[342] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x08, 0x00, 0x45, 0x00, /* ...i..E. */ 0x01, 0x48, 0x00, 0x01, 0x00, 0x00, 0x80, 0x11, /* .H...... */ 0x39, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* 9....... */ 0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, /* ...D.C.4 */ 0x83, 0x9e, 0x01, 0x01, 0x06, 0x00, 0x00, 0xf6, /* ........ */ 0x16, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /* .......P */ 0xb6, 0x07, 0xa1, 0x69, 0x00, 0x00, 0x00, 0x00, /* ...i.... */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x37, 0x01, 0x37, 0x3d, 0x07, 0x01, /* Sc5..=.. */ 0x00, 0x50, 0xb6, 0x07, 0xa1, 0x69, 0x0c, 0x0e, /* .P...i.. */ 0x43, 0x57, 0x2d, 0x39, 0x57, 0x44, 0x50, 0x4a, /* CW-9WDPJ */ 0x56, 0x31, 0x2d, 0x47, 0x41, 0x31, 0x3c, 0x08, /* V1-GA1<. */ 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, /* MSFT 5.0 */ 0x37, 0x0c, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, /* 7.....,. */ 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xff, 0x00, /* /.!y.+.. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* ...... */ }; static const UCHAR *test_packet[] = {pkt1, pkt2, pkt3}; static UINT test_packet_size[] = {sizeof(pkt1), sizeof(pkt2), sizeof(pkt3)}; static UINT test_count = sizeof(test_packet_size) / sizeof(UINT); /* Define what the initial system looks like. */ #ifdef CTEST VOID test_application_define(void *first_unused_memory) #else void netx_dhcp_server_options_test_application_define(void *first_unused_memory) #endif { UINT status; /* Setup the working pointer. */ pointer = (CHAR *) first_unused_memory; /* Create the server thread. */ tx_thread_create(&server_thread, "thread server", server_thread_entry, 0, pointer, DEMO_STACK_SIZE, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); pointer = pointer + DEMO_STACK_SIZE; /* Initialize the NetX system. */ nx_system_initialize(); /* Create the client packet pool. */ status = nx_packet_pool_create(&client_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE); pointer = pointer + NX_PACKET_POOL_SIZE; /* Check for pool creation error. */ if (status) error_counter++; memset(pointer, 53, NX_PACKET_POOL_SIZE); /* Create the server packet pool. */ status = nx_packet_pool_create(&server_pool, "NetX Main Packet Pool", 1024, pointer, NX_PACKET_POOL_SIZE); pointer = pointer + NX_PACKET_POOL_SIZE; /* Check for pool creation error. */ if (status) error_counter++; /* Check for IP create errors. */ if (status) error_counter++; /* Create an IP instance for the DHCP Server. */ status = nx_ip_create(&server_ip, "DHCP Server", NX_DHCP_SERVER_IP_ADDRESS_0, 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024, pointer, 2048, 1); pointer = pointer + 2048; /* Check for IP create errors. */ if (status) error_counter++; /* Enable ARP and supply ARP cache memory for DHCP Server IP. */ status = nx_arp_enable(&server_ip, (void *) pointer, 1024); pointer = pointer + 1024; /* Check for ARP enable errors. */ if (status) error_counter++; /* Enable UDP traffic. */ status = nx_udp_enable(&server_ip); /* Check for UDP enable errors. */ if (status) error_counter++; /* Enable ICMP. */ status = nx_icmp_enable(&server_ip); /* Check for errors. */ if (status) error_counter++; return; } /* Define the test threads. */ void server_thread_entry(ULONG thread_input) { UINT status; UINT iface_index; UINT addresses_added; NX_PACKET *my_packet; UINT i; printf("NetX Test: DHCP Server Options Test.................................."); /* Create the DHCP Server. */ status = nx_dhcp_server_create(&dhcp_server, &server_ip, pointer, DEMO_STACK_SIZE, "DHCP Server", &server_pool); pointer = pointer + DEMO_STACK_SIZE; /* Check for errors creating the DHCP Server. */ if (status) error_counter++; /* Load the assignable DHCP IP addresses for the first interface. */ iface_index = 0; status = nx_dhcp_create_server_ip_address_list(&dhcp_server, iface_index, START_IP_ADDRESS_LIST_0, END_IP_ADDRESS_LIST_0, &addresses_added); /* Check for errors creating the list. */ if (status) { error_counter++; } /* Verify all the addresses were added to the list. */ if (addresses_added != 10) { error_counter++; } status = nx_dhcp_set_interface_network_parameters(&dhcp_server, iface_index, NX_DHCP_SUBNET_MASK_0, NX_DHCP_DEFAULT_GATEWAY_0, NX_DHCP_DNS_SERVER_0); /* Check for errors setting network parameters. */ if (status) { error_counter++; } /* Start DHCP Server task. */ status = nx_dhcp_server_start(&dhcp_server); /* Check for errors starting up the DHCP server. */ if (status) { error_counter++; } for (i = 0; i < test_count; i++) { /* Send the DHCP DISCOVER packet. */ status = nx_packet_allocate(&client_pool, &my_packet, NX_UDP_PACKET, NX_WAIT_FOREVER); /* Check status */ if (status) error_counter++; /* Fill in the packet with data. Skip the MAC header. */ memcpy(my_packet->nx_packet_prepend_ptr, &test_packet[i][14], test_packet_size[i] - 14); my_packet->nx_packet_length = test_packet_size[i] - 14; my_packet->nx_packet_append_ptr = my_packet->nx_packet_prepend_ptr + test_packet_size[i] - 14; /* Directly receive the DHCP DISCOVER packet. */ _nx_ip_packet_deferred_receive(&server_ip, my_packet); tx_thread_sleep(NX_IP_PERIODIC_RATE); if ((i == 0) && (dhcp_server.client_records[0].nx_dhcp_client_option_count)) { error_counter++; } if ((i == 1) && (dhcp_server.client_records[1].nx_dhcp_client_state == 53)) { error_counter++; } nx_dhcp_clear_client_record(&dhcp_server, &(dhcp_server.client_records[0])); } if (error_counter) { printf("ERROR!\n"); test_control_return(1); } else { printf("SUCCESS!\n"); test_control_return(0); } return; } #else #ifdef CTEST VOID test_application_define(void *first_unused_memory) #else void netx_dhcp_server_options_test_application_define(void *first_unused_memory) #endif { printf("NetX Test: DHCP Server Options Test..................................N/A\n"); test_control_return(3); } #endif