10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci/** 330d163575Sopenharmony_ci * @file 340d163575Sopenharmony_ci * Dynamic Host Configuration Protocol Server 350d163575Sopenharmony_ci * 360d163575Sopenharmony_ci */ 370d163575Sopenharmony_ci 380d163575Sopenharmony_ci#include "../core/ipv4/dhcp.c" /* for enum dhcp_option_idx/dhcp_option_xx/dhcp_parse_reply etc. */ 390d163575Sopenharmony_ci 400d163575Sopenharmony_ci#include "lwip/opt.h" 410d163575Sopenharmony_ci 420d163575Sopenharmony_ci#if (LWIP_DHCP) && (LWIP_DHCPS) /* don't build if not configured for use in lwipopts.h */ 430d163575Sopenharmony_ci#include <string.h> 440d163575Sopenharmony_ci 450d163575Sopenharmony_ci#include "lwip/stats.h" 460d163575Sopenharmony_ci#include "lwip/mem.h" 470d163575Sopenharmony_ci#include "lwip/udp.h" 480d163575Sopenharmony_ci#include "lwip/ip_addr.h" 490d163575Sopenharmony_ci#include "lwip/netif.h" 500d163575Sopenharmony_ci#include "lwip/def.h" 510d163575Sopenharmony_ci#include "lwip/prot/dhcp.h" 520d163575Sopenharmony_ci#include "lwip/dhcp.h" 530d163575Sopenharmony_ci#include "lwip/dhcps.h" 540d163575Sopenharmony_ci#include "lwip/sys.h" 550d163575Sopenharmony_ci#include "netif/etharp.h" 560d163575Sopenharmony_ci 570d163575Sopenharmony_ci#define DHCPS_ADDRESS_FREE 0x0 580d163575Sopenharmony_ci#define DHCPS_ADDRESS_OFFERRED 0x1 590d163575Sopenharmony_ci#define DHCPS_ADDRESS_BOUND 0x2 600d163575Sopenharmony_ci#define DHCPS_ADDRESS_DECLINED 0x3 610d163575Sopenharmony_ci 620d163575Sopenharmony_ci#define LWIP_STATIC static 630d163575Sopenharmony_ci#define DHCP_OPTION_ROUTER_SIZE 4 640d163575Sopenharmony_ci#define DHCP_OPTION_SUBNET_MASK_SIZE 4 650d163575Sopenharmony_ci#define DHCP_OPTION_LEASE_TIME_SIZE 4 660d163575Sopenharmony_ci#define DHCP_OPTION_SERVER_ID_LEN 4 670d163575Sopenharmony_ci#define DHCP_OPTION_T1_LEN 4 680d163575Sopenharmony_ci#define DHCP_OPTION_T2_LEN 4 690d163575Sopenharmony_ci 700d163575Sopenharmony_ci#define DHCP_CLIENT_PORT 68 710d163575Sopenharmony_ci#define DHCP_SERVER_PORT 67 720d163575Sopenharmony_ci 730d163575Sopenharmony_ci#define DHCP_BROADCAST_FLAG 0x8000 740d163575Sopenharmony_ci 750d163575Sopenharmony_cistruct dyn_lease_addr { 760d163575Sopenharmony_ci u8_t cli_hwaddr[DHCP_CHADDR_LEN]; 770d163575Sopenharmony_ci u32_t flags; 780d163575Sopenharmony_ci u32_t leasetime; 790d163575Sopenharmony_ci u32_t proposed_leasetime; 800d163575Sopenharmony_ci ip4_addr_t cli_addr; 810d163575Sopenharmony_ci}; 820d163575Sopenharmony_ci 830d163575Sopenharmony_cistruct dhcps { 840d163575Sopenharmony_ci struct dhcp dhcp; 850d163575Sopenharmony_ci struct udp_pcb *pcb; 860d163575Sopenharmony_ci struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE]; 870d163575Sopenharmony_ci u8_t pcb_allocated; 880d163575Sopenharmony_ci u8_t lease_num; 890d163575Sopenharmony_ci struct netif *netif; 900d163575Sopenharmony_ci ip4_addr_t start_addr; 910d163575Sopenharmony_ci ip4_addr_t end_addr; 920d163575Sopenharmony_ci}; 930d163575Sopenharmony_ci 940d163575Sopenharmony_ci#define dhcps_option_given(dhcps, idx) dhcp_option_given(&(dhcps)->dhcp, idx) 950d163575Sopenharmony_ci#define dhcps_got_option(dhcps, idx) dhcp_got_option(&(dhcps)->dhcp, idx) 960d163575Sopenharmony_ci#define dhcps_clear_option(dhcps, idx) dhcp_clear_option(&(dhcps)->dhcp, idx) 970d163575Sopenharmony_ci#define dhcps_clear_all_options(dhcps) dhcp_clear_all_options(&(dhcps)->dhcp) 980d163575Sopenharmony_ci#define dhcps_get_option_value(dhcps, idx) dhcp_get_option_value(&(dhcps)->dhcp, idx) 990d163575Sopenharmony_ci#define dhcps_set_option_value(dhcps, idx, val) dhcp_set_option_value(&(dhcps)->dhcp, idx, val) 1000d163575Sopenharmony_ci 1010d163575Sopenharmony_ci#define netif_get_dhcps(netif) ((struct dhcps*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS)) 1020d163575Sopenharmony_ci#define netif_set_dhcps(netif, dhcps) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS, dhcps) 1030d163575Sopenharmony_ci 1040d163575Sopenharmony_ciLWIP_STATIC void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len); 1050d163575Sopenharmony_ciLWIP_STATIC void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len); 1060d163575Sopenharmony_ciLWIP_STATIC void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len); 1070d163575Sopenharmony_ciLWIP_STATIC void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out); 1080d163575Sopenharmony_ciLWIP_STATIC err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps); 1090d163575Sopenharmony_ci 1100d163575Sopenharmony_ciLWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg); 1110d163575Sopenharmony_ciLWIP_STATIC void remove_stale_entries(struct dhcps *dhcps); 1120d163575Sopenharmony_ciLWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg); 1130d163575Sopenharmony_ciLWIP_STATIC int find_free_slot(struct dhcps *dhcps); 1140d163575Sopenharmony_ciLWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg); 1150d163575Sopenharmony_ciLWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, 1160d163575Sopenharmony_ci struct dyn_lease_addr **client_lease); 1170d163575Sopenharmony_ciLWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, 1180d163575Sopenharmony_ci struct dyn_lease_addr *client_lease); 1190d163575Sopenharmony_ciLWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg, 1200d163575Sopenharmony_ci struct dyn_lease_addr *client_lease, ip4_addr_t serverid); 1210d163575Sopenharmony_ciLWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, 1220d163575Sopenharmony_ci struct dyn_lease_addr *client_lease, ip4_addr_t serverid); 1230d163575Sopenharmony_ciLWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, 1240d163575Sopenharmony_ci struct dyn_lease_addr *client_lease); 1250d163575Sopenharmony_ciLWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg); 1260d163575Sopenharmony_ciLWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps, 1270d163575Sopenharmony_ci struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type); 1280d163575Sopenharmony_ciLWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, 1290d163575Sopenharmony_ci const ip_addr_t *ip_addr, u16_t port); 1300d163575Sopenharmony_ci 1310d163575Sopenharmony_ciLWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg) 1320d163575Sopenharmony_ci{ 1330d163575Sopenharmony_ci struct pbuf *srvr_msg_pbuf = NULL; 1340d163575Sopenharmony_ci struct dhcp_msg *srvr_msg = NULL; 1350d163575Sopenharmony_ci 1360d163575Sopenharmony_ci srvr_msg_pbuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); 1370d163575Sopenharmony_ci if (srvr_msg_pbuf == NULL) { 1380d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 1390d163575Sopenharmony_ci ("dhcps_create_base_msg(): could not allocate pbuf\n")); 1400d163575Sopenharmony_ci return NULL; 1410d163575Sopenharmony_ci } 1420d163575Sopenharmony_ci 1430d163575Sopenharmony_ci LWIP_ASSERT("dhcps_create_base_msg: check that first pbuf can hold struct dhcp_msg", 1440d163575Sopenharmony_ci (srvr_msg_pbuf->len >= sizeof(struct dhcp_msg))); 1450d163575Sopenharmony_ci#if DRIVER_STATUS_CHECK 1460d163575Sopenharmony_ci srvr_msg_pbuf->flags |= PBUF_FLAG_DHCP_BUF; 1470d163575Sopenharmony_ci#endif 1480d163575Sopenharmony_ci 1490d163575Sopenharmony_ci srvr_msg = (struct dhcp_msg *)srvr_msg_pbuf->payload; 1500d163575Sopenharmony_ci srvr_msg->op = DHCP_BOOTREPLY; 1510d163575Sopenharmony_ci srvr_msg->htype = client_msg->htype; 1520d163575Sopenharmony_ci srvr_msg->hlen = client_msg->hlen; 1530d163575Sopenharmony_ci srvr_msg->hops = 0; 1540d163575Sopenharmony_ci srvr_msg->xid = client_msg->xid; 1550d163575Sopenharmony_ci srvr_msg->secs = 0; 1560d163575Sopenharmony_ci srvr_msg->flags = client_msg->flags; 1570d163575Sopenharmony_ci ip4_addr_set_zero(&srvr_msg->ciaddr); 1580d163575Sopenharmony_ci ip4_addr_set_zero(&srvr_msg->yiaddr); 1590d163575Sopenharmony_ci ip4_addr_set_zero(&srvr_msg->siaddr); 1600d163575Sopenharmony_ci ip4_addr_copy(srvr_msg->giaddr, client_msg->giaddr); 1610d163575Sopenharmony_ci if (memcpy_s(srvr_msg->chaddr, sizeof(srvr_msg->chaddr), client_msg->chaddr, DHCP_CHADDR_LEN) != EOK) { 1620d163575Sopenharmony_ci (void)pbuf_free(srvr_msg_pbuf); 1630d163575Sopenharmony_ci return NULL; 1640d163575Sopenharmony_ci } 1650d163575Sopenharmony_ci (void)memset_s(srvr_msg->sname, sizeof(srvr_msg->sname), 0, DHCP_SNAME_LEN); 1660d163575Sopenharmony_ci (void)memset_s(srvr_msg->file, sizeof(srvr_msg->file), 0, DHCP_FILE_LEN); 1670d163575Sopenharmony_ci srvr_msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); 1680d163575Sopenharmony_ci 1690d163575Sopenharmony_ci return srvr_msg_pbuf; 1700d163575Sopenharmony_ci} 1710d163575Sopenharmony_ci 1720d163575Sopenharmony_ciLWIP_STATIC void remove_stale_entries(struct dhcps *dhcps) 1730d163575Sopenharmony_ci{ 1740d163575Sopenharmony_ci int i = 0; 1750d163575Sopenharmony_ci u32_t curr_time = sys_now(); 1760d163575Sopenharmony_ci 1770d163575Sopenharmony_ci for (i = 0; i < dhcps->lease_num; i++) { 1780d163575Sopenharmony_ci /* Slot should not be free or have infinite lease time */ 1790d163575Sopenharmony_ci if ((dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) && (dhcps->leasearr[i].leasetime != (u32_t)~0)) { 1800d163575Sopenharmony_ci if (dhcps->leasearr[i].leasetime < curr_time) { 1810d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 1820d163575Sopenharmony_ci ("remove_stale_entries: Removing Client Entry at Index = %"U32_F"\n", i)); 1830d163575Sopenharmony_ci (void)memset_s(&(dhcps->leasearr[i]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); 1840d163575Sopenharmony_ci dhcps->leasearr[i].flags = DHCPS_ADDRESS_FREE; 1850d163575Sopenharmony_ci } 1860d163575Sopenharmony_ci } 1870d163575Sopenharmony_ci } 1880d163575Sopenharmony_ci} 1890d163575Sopenharmony_ci 1900d163575Sopenharmony_ciLWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg) 1910d163575Sopenharmony_ci{ 1920d163575Sopenharmony_ci u32_t client_lease_time = (u32_t)(LWIP_DHCPS_LEASE_TIME); 1930d163575Sopenharmony_ci 1940d163575Sopenharmony_ci if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME)) 1950d163575Sopenharmony_ci#if (LWIP_DHCPS_LEASE_TIME != ~0) 1960d163575Sopenharmony_ci && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME) 1970d163575Sopenharmony_ci#endif 1980d163575Sopenharmony_ci ) { 1990d163575Sopenharmony_ci client_lease_time = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME); 2000d163575Sopenharmony_ci } 2010d163575Sopenharmony_ci 2020d163575Sopenharmony_ci (void)memset_s(&(dhcps->leasearr[idx]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); 2030d163575Sopenharmony_ci if (memcpy_s(dhcps->leasearr[idx].cli_hwaddr, DHCP_CHADDR_LEN, 2040d163575Sopenharmony_ci client_msg->chaddr, sizeof(client_msg->chaddr)) != EOK) { 2050d163575Sopenharmony_ci return; 2060d163575Sopenharmony_ci } 2070d163575Sopenharmony_ci /* This is called only during offer message, so adding offer time. 2080d163575Sopenharmony_ci This is later updated to lease time when request message is handled */ 2090d163575Sopenharmony_ci dhcps->leasearr[idx].leasetime = sys_now() + (LWIP_DHCPS_OFFER_TIME * 1000); 2100d163575Sopenharmony_ci dhcps->leasearr[idx].cli_addr.addr = dhcps->start_addr.addr + idx; 2110d163575Sopenharmony_ci dhcps->leasearr[idx].flags = DHCPS_ADDRESS_OFFERRED; 2120d163575Sopenharmony_ci dhcps->leasearr[idx].proposed_leasetime = client_lease_time; 2130d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("add_client_entry: Adding Client Entry at Index = %"U32_F"\n", idx)); 2140d163575Sopenharmony_ci} 2150d163575Sopenharmony_ci 2160d163575Sopenharmony_ciLWIP_STATIC int find_free_slot(struct dhcps *dhcps) 2170d163575Sopenharmony_ci{ 2180d163575Sopenharmony_ci int i; 2190d163575Sopenharmony_ci for (i = 0; i < dhcps->lease_num; i++) { 2200d163575Sopenharmony_ci if ((dhcps->leasearr[i].flags == DHCPS_ADDRESS_FREE) && 2210d163575Sopenharmony_ci (htonl(dhcps->start_addr.addr + (u32_t)i) != ip_2_ip4(&dhcps->netif->ip_addr)->addr)) { 2220d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("find_free_slot: Found Free Slot at Index = %"U32_F"\n", i)); 2230d163575Sopenharmony_ci return i; 2240d163575Sopenharmony_ci } 2250d163575Sopenharmony_ci } 2260d163575Sopenharmony_ci 2270d163575Sopenharmony_ci return -1; 2280d163575Sopenharmony_ci} 2290d163575Sopenharmony_ci 2300d163575Sopenharmony_ciLWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg) 2310d163575Sopenharmony_ci{ 2320d163575Sopenharmony_ci int i; 2330d163575Sopenharmony_ci for (i = 0; i < dhcps->lease_num; i++) { 2340d163575Sopenharmony_ci if (dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) { 2350d163575Sopenharmony_ci if (memcmp(dhcps->leasearr[i].cli_hwaddr, client_msg->chaddr, client_msg->hlen) == 0) { 2360d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2370d163575Sopenharmony_ci ("find_client_lease: Found Client Lease at Index = %"U32_F"\n", i)); 2380d163575Sopenharmony_ci return &(dhcps->leasearr[i]); 2390d163575Sopenharmony_ci } 2400d163575Sopenharmony_ci } 2410d163575Sopenharmony_ci } 2420d163575Sopenharmony_ci 2430d163575Sopenharmony_ci return NULL; 2440d163575Sopenharmony_ci} 2450d163575Sopenharmony_ci 2460d163575Sopenharmony_ciLWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, 2470d163575Sopenharmony_ci struct dyn_lease_addr **client_lease) 2480d163575Sopenharmony_ci{ 2490d163575Sopenharmony_ci ip4_addr_t client_ip; 2500d163575Sopenharmony_ci int idx = -1; 2510d163575Sopenharmony_ci 2520d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Validating Discover Message\n")); 2530d163575Sopenharmony_ci 2540d163575Sopenharmony_ci client_ip.addr = 0; 2550d163575Sopenharmony_ci if (*client_lease == NULL) { 2560d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Existing Client Lease not Found\n")); 2570d163575Sopenharmony_ci if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { 2580d163575Sopenharmony_ci client_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); 2590d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 2600d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2610d163575Sopenharmony_ci ("validate_discover function: Requested IP from client = %"U32_F"\n", client_ip.addr)); 2620d163575Sopenharmony_ci#endif 2630d163575Sopenharmony_ci 2640d163575Sopenharmony_ci if ((client_ip.addr >= dhcps->start_addr.addr) && (client_ip.addr <= dhcps->end_addr.addr)) { 2650d163575Sopenharmony_ci idx = (int)(client_ip.addr - dhcps->start_addr.addr); 2660d163575Sopenharmony_ci if ((dhcps->leasearr[idx].flags != DHCPS_ADDRESS_FREE) || 2670d163575Sopenharmony_ci (ntohl(client_ip.addr) == ip_2_ip4(&dhcps->netif->ip_addr)->addr)) { 2680d163575Sopenharmony_ci /* Requested IP is not available */ 2690d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 2700d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2710d163575Sopenharmony_ci ("validate_discover function: Requested IP from client = %"U32_F" Not available \n", client_ip.addr)); 2720d163575Sopenharmony_ci#endif 2730d163575Sopenharmony_ci idx = -1; 2740d163575Sopenharmony_ci } 2750d163575Sopenharmony_ci } 2760d163575Sopenharmony_ci } 2770d163575Sopenharmony_ci 2780d163575Sopenharmony_ci if (idx == -1) { 2790d163575Sopenharmony_ci idx = find_free_slot(dhcps); 2800d163575Sopenharmony_ci if (idx == -1) { 2810d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2820d163575Sopenharmony_ci ("validate_discover function: No Free Slot available for Storing addresses\n")); 2830d163575Sopenharmony_ci client_ip.addr = 0; 2840d163575Sopenharmony_ci return client_ip; 2850d163575Sopenharmony_ci } 2860d163575Sopenharmony_ci client_ip.addr = dhcps->start_addr.addr + (u32_t)idx; 2870d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 2880d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2890d163575Sopenharmony_ci ("validate_discover function: New IP = %"U32_F" is being assigned\n", client_ip.addr)); 2900d163575Sopenharmony_ci#endif 2910d163575Sopenharmony_ci } 2920d163575Sopenharmony_ci 2930d163575Sopenharmony_ci add_client_entry(dhcps, (unsigned int)idx, client_msg); 2940d163575Sopenharmony_ci (*client_lease) = &(dhcps->leasearr[idx]); 2950d163575Sopenharmony_ci } else { 2960d163575Sopenharmony_ci client_ip.addr = (*client_lease)->cli_addr.addr; 2970d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 2980d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 2990d163575Sopenharmony_ci ("validate_discover: Existing Client Lease Found. Existing IP =%"U32_F"\n", client_ip.addr)); 3000d163575Sopenharmony_ci#endif 3010d163575Sopenharmony_ci 3020d163575Sopenharmony_ci if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME)) 3030d163575Sopenharmony_ci#if (~0 != LWIP_DHCPS_LEASE_TIME) 3040d163575Sopenharmony_ci && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME) 3050d163575Sopenharmony_ci#endif 3060d163575Sopenharmony_ci ) { 3070d163575Sopenharmony_ci /* Assign the newly requested time or else use the existing lease time as-is */ 3080d163575Sopenharmony_ci (*client_lease)->proposed_leasetime = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME); 3090d163575Sopenharmony_ci } 3100d163575Sopenharmony_ci } 3110d163575Sopenharmony_ci 3120d163575Sopenharmony_ci return client_ip; 3130d163575Sopenharmony_ci} 3140d163575Sopenharmony_ci 3150d163575Sopenharmony_civoid dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len) 3160d163575Sopenharmony_ci{ 3170d163575Sopenharmony_ci *options_out_len = dhcp_option(*options_out_len, msg_out->options, option_type, option_len); 3180d163575Sopenharmony_ci} 3190d163575Sopenharmony_ci 3200d163575Sopenharmony_civoid dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len) 3210d163575Sopenharmony_ci{ 3220d163575Sopenharmony_ci *options_out_len = dhcp_option_byte(*options_out_len, msg_out->options, value); 3230d163575Sopenharmony_ci} 3240d163575Sopenharmony_ci 3250d163575Sopenharmony_civoid dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len) 3260d163575Sopenharmony_ci{ 3270d163575Sopenharmony_ci *options_out_len = dhcp_option_long(*options_out_len, msg_out->options, value); 3280d163575Sopenharmony_ci} 3290d163575Sopenharmony_ci 3300d163575Sopenharmony_civoid dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out) 3310d163575Sopenharmony_ci{ 3320d163575Sopenharmony_ci dhcp_option_trailer(options_out_len, msg_out->options, p_out); 3330d163575Sopenharmony_ci} 3340d163575Sopenharmony_ci 3350d163575Sopenharmony_ciLWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, 3360d163575Sopenharmony_ci struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease) 3370d163575Sopenharmony_ci{ 3380d163575Sopenharmony_ci#if !LWIP_DHCPS_DISCOVER_BROADCAST 3390d163575Sopenharmony_ci ip_addr_t client_ipaddr; 3400d163575Sopenharmony_ci#endif 3410d163575Sopenharmony_ci 3420d163575Sopenharmony_ci ip4_addr_t client_ip; 3430d163575Sopenharmony_ci ip_addr_t dst_addr; 3440d163575Sopenharmony_ci struct pbuf *out_msg = NULL; 3450d163575Sopenharmony_ci struct dhcp_msg *srvr_msg = NULL; 3460d163575Sopenharmony_ci u16_t options_len = 0; 3470d163575Sopenharmony_ci#if !LWIP_DHCPS_DISCOVER_BROADCAST 3480d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 3490d163575Sopenharmony_ci struct eth_addr ethaddr; 3500d163575Sopenharmony_ci#endif 3510d163575Sopenharmony_ci#endif 3520d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Processing Discover Message\n")); 3530d163575Sopenharmony_ci 3540d163575Sopenharmony_ci client_ip = validate_discover(dhcps, client_msg, &client_lease); 3550d163575Sopenharmony_ci if (client_ip.addr == 0) { 3560d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 3570d163575Sopenharmony_ci ("handle_discover: Returning as unable to get a proper address for client\n")); 3580d163575Sopenharmony_ci return; 3590d163575Sopenharmony_ci } 3600d163575Sopenharmony_ci 3610d163575Sopenharmony_ci out_msg = dhcps_create_base_msg(client_msg); 3620d163575Sopenharmony_ci if (out_msg == NULL) { 3630d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 3640d163575Sopenharmony_ci ("handle_discover function: Memory allocation for base message failed\n")); 3650d163575Sopenharmony_ci return; 3660d163575Sopenharmony_ci } 3670d163575Sopenharmony_ci 3680d163575Sopenharmony_ci srvr_msg = (struct dhcp_msg *)out_msg->payload; 3690d163575Sopenharmony_ci // no need check msg pointer from payload here 3700d163575Sopenharmony_ci srvr_msg->yiaddr.addr = htonl(client_ip.addr); 3710d163575Sopenharmony_ci 3720d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); 3730d163575Sopenharmony_ci dhcp_common_option_byte(srvr_msg, DHCP_OFFER, &options_len); 3740d163575Sopenharmony_ci 3750d163575Sopenharmony_ci /* hilink need this router option */ 3760d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len); 3770d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); 3780d163575Sopenharmony_ci 3790d163575Sopenharmony_ci /* netif already holds the Server ID in network order. so, no need to convert it again */ 3800d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len); 3810d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); 3820d163575Sopenharmony_ci 3830d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len); 3840d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len); 3850d163575Sopenharmony_ci 3860d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len); 3870d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len); 3880d163575Sopenharmony_ci 3890d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len); 3900d163575Sopenharmony_ci /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */ 3910d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len); 3920d163575Sopenharmony_ci 3930d163575Sopenharmony_ci /* No need to convert netmask into network order as it is already stored in network order */ 3940d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len); 3950d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip4_addr_get_u32(ip_2_ip4(&netif->netmask))), &options_len); 3960d163575Sopenharmony_ci 3970d163575Sopenharmony_ci dhcp_common_option_trailer(srvr_msg, options_len, out_msg); 3980d163575Sopenharmony_ci 3990d163575Sopenharmony_ci if (client_msg->ciaddr.addr != 0) { 4000d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: sendto(OFFER, ciaddr, DHCP_CLIENT_PORT)\n")); 4010d163575Sopenharmony_ci ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr)); 4020d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 4030d163575Sopenharmony_ci } 4040d163575Sopenharmony_ci#if !LWIP_DHCPS_DISCOVER_BROADCAST 4050d163575Sopenharmony_ci else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) { 4060d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4070d163575Sopenharmony_ci ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n")); 4080d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 4090d163575Sopenharmony_ci } else { 4100d163575Sopenharmony_ci client_ip.addr = htonl(client_ip.addr); 4110d163575Sopenharmony_ci 4120d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 4130d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Updating ARP Static Entry for unicast reply\n")); 4140d163575Sopenharmony_ci if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) { 4150d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("memcpy_s failed\n")); 4160d163575Sopenharmony_ci (void)pbuf_free(out_msg); 4170d163575Sopenharmony_ci return; 4180d163575Sopenharmony_ci } 4190d163575Sopenharmony_ci if (etharp_add_static_entry(&client_ip, ðaddr) != ERR_OK) { 4200d163575Sopenharmony_ci (void)pbuf_free(out_msg); 4210d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Adding static entry to arp cache failed\n")); 4220d163575Sopenharmony_ci return; 4230d163575Sopenharmony_ci } 4240d163575Sopenharmony_ci#endif 4250d163575Sopenharmony_ci 4260d163575Sopenharmony_ci /* Need to check and add an arp entry to make this pass through smoothly */ 4270d163575Sopenharmony_ci ip_addr_copy_from_ip4(client_ipaddr, client_ip); 4280d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, &client_ipaddr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 4290d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 4300d163575Sopenharmony_ci /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */ 4310d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4320d163575Sopenharmony_ci ("handle_discover: Removing ARP Static Entry added for unicast reply\n")); 4330d163575Sopenharmony_ci (void)etharp_remove_static_entry(&client_ip); 4340d163575Sopenharmony_ci#endif 4350d163575Sopenharmony_ci } 4360d163575Sopenharmony_ci#else 4370d163575Sopenharmony_ci else { 4380d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4390d163575Sopenharmony_ci ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n")); 4400d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 4410d163575Sopenharmony_ci } 4420d163575Sopenharmony_ci#endif 4430d163575Sopenharmony_ci 4440d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: deleting()ing\n")); 4450d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Sending Reply has been successful\n")); 4460d163575Sopenharmony_ci 4470d163575Sopenharmony_ci (void)pbuf_free(out_msg); 4480d163575Sopenharmony_ci return; 4490d163575Sopenharmony_ci} 4500d163575Sopenharmony_ci 4510d163575Sopenharmony_ciLWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg, 4520d163575Sopenharmony_ci struct dyn_lease_addr *client_lease, ip4_addr_t serverid) 4530d163575Sopenharmony_ci{ 4540d163575Sopenharmony_ci struct dhcps *dhcps = netif_get_dhcps(netif); 4550d163575Sopenharmony_ci ip4_addr_t requested_ip; 4560d163575Sopenharmony_ci requested_ip.addr = 0; 4570d163575Sopenharmony_ci 4580d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Processing Request Message\n")); 4590d163575Sopenharmony_ci 4600d163575Sopenharmony_ci if ((client_lease != NULL) && (client_lease->flags == DHCPS_ADDRESS_OFFERRED)) { 4610d163575Sopenharmony_ci /* Now, we are in selecting state */ 4620d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: In Selecting State\n")); 4630d163575Sopenharmony_ci 4640d163575Sopenharmony_ci if ((serverid.addr == 0) || (client_msg->ciaddr.addr != 0) || 4650d163575Sopenharmony_ci (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP))) { 4660d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4670d163575Sopenharmony_ci ("Server ID or ciaddr or requested ip option is not present\n")); 4680d163575Sopenharmony_ci return requested_ip; 4690d163575Sopenharmony_ci } 4700d163575Sopenharmony_ci 4710d163575Sopenharmony_ci if (serverid.addr != ip_2_ip4(&netif->ip_addr)->addr) { 4720d163575Sopenharmony_ci /* This message is not meant for us. The client intends to talk to some other server */ 4730d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4740d163575Sopenharmony_ci ("validate_request_message: Server id doesn't match with ours. Message not for us\n")); 4750d163575Sopenharmony_ci requested_ip.addr = 1; 4760d163575Sopenharmony_ci return requested_ip; 4770d163575Sopenharmony_ci } 4780d163575Sopenharmony_ci 4790d163575Sopenharmony_ci requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); 4800d163575Sopenharmony_ci } else { 4810d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4820d163575Sopenharmony_ci ("validate_request_message: In Init-Reboot, Renew or Rebinding State\n")); 4830d163575Sopenharmony_ci 4840d163575Sopenharmony_ci /* Now, we can be either in Init-reboot state or renew state or rebinding state */ 4850d163575Sopenharmony_ci if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { 4860d163575Sopenharmony_ci /* Requested IP option is filled in. Indicates we are mostly in Init-Reboot State */ 4870d163575Sopenharmony_ci if (client_lease == NULL) { 4880d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4890d163575Sopenharmony_ci ("validate_request_message: No Configuration found corresponding to request message\n")); 4900d163575Sopenharmony_ci return requested_ip; 4910d163575Sopenharmony_ci } 4920d163575Sopenharmony_ci 4930d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4940d163575Sopenharmony_ci ("validate_request_message: Requested IP Option is present. So, considering as Init-Reboot State\n")); 4950d163575Sopenharmony_ci 4960d163575Sopenharmony_ci if (client_msg->ciaddr.addr != 0) { 4970d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 4980d163575Sopenharmony_ci ("validate_request_message: Error: ciaddr is filled in the Init-Reboot state. \n")); 4990d163575Sopenharmony_ci return requested_ip; 5000d163575Sopenharmony_ci } 5010d163575Sopenharmony_ci 5020d163575Sopenharmony_ci requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP); 5030d163575Sopenharmony_ci } else { 5040d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: \ 5050d163575Sopenharmony_ci Requested IP Option is not present. So, considering as Renewing or Rebinding State\n")); 5060d163575Sopenharmony_ci 5070d163575Sopenharmony_ci if (client_msg->ciaddr.addr == 0) { 5080d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 5090d163575Sopenharmony_ci ("validate_request_message: Error: ciaddr is not filled in the Renewing or Rebinding state. \n")); 5100d163575Sopenharmony_ci return requested_ip; 5110d163575Sopenharmony_ci } 5120d163575Sopenharmony_ci 5130d163575Sopenharmony_ci requested_ip.addr = ntohl(client_msg->ciaddr.addr); 5140d163575Sopenharmony_ci } 5150d163575Sopenharmony_ci } 5160d163575Sopenharmony_ci 5170d163575Sopenharmony_ci /* requested_ip is in host order and DHCP Server IP is in network order, 5180d163575Sopenharmony_ci so converting the former to network order for check */ 5190d163575Sopenharmony_ci if (htonl(requested_ip.addr) == ip_2_ip4(&netif->ip_addr)->addr) { 5200d163575Sopenharmony_ci /* This requested_ip is the dhcp server is using, it is invalid */ 5210d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Requested IP addr is invalid\n")); 5220d163575Sopenharmony_ci requested_ip.addr = 1; 5230d163575Sopenharmony_ci } 5240d163575Sopenharmony_ci 5250d163575Sopenharmony_ci return requested_ip; 5260d163575Sopenharmony_ci} 5270d163575Sopenharmony_ci 5280d163575Sopenharmony_ciLWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, 5290d163575Sopenharmony_ci struct dyn_lease_addr *client_lease, ip4_addr_t serverid) 5300d163575Sopenharmony_ci{ 5310d163575Sopenharmony_ci ip4_addr_t requested_ip; 5320d163575Sopenharmony_ci struct pbuf *out_msg = NULL; 5330d163575Sopenharmony_ci struct dhcp_msg *srvr_msg = NULL; 5340d163575Sopenharmony_ci u16_t options_len = 0; 5350d163575Sopenharmony_ci ip_addr_t dst_addr; 5360d163575Sopenharmony_ci ip_addr_t ip_send; 5370d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 5380d163575Sopenharmony_ci struct eth_addr ethaddr; 5390d163575Sopenharmony_ci#endif 5400d163575Sopenharmony_ci 5410d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Processing Request Message\n")); 5420d163575Sopenharmony_ci 5430d163575Sopenharmony_ci requested_ip = validate_request_message(netif, client_msg, client_lease, serverid); 5440d163575Sopenharmony_ci if (requested_ip.addr == 1) { 5450d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 5460d163575Sopenharmony_ci ("handle_request: Validation of request message failed. Dropping the packet.\n")); 5470d163575Sopenharmony_ci return; 5480d163575Sopenharmony_ci } 5490d163575Sopenharmony_ci 5500d163575Sopenharmony_ci out_msg = dhcps_create_base_msg(client_msg); 5510d163575Sopenharmony_ci if (out_msg == NULL) { 5520d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Creating base message failed\n")); 5530d163575Sopenharmony_ci return; 5540d163575Sopenharmony_ci } 5550d163575Sopenharmony_ci 5560d163575Sopenharmony_ci srvr_msg = (struct dhcp_msg *)out_msg->payload; 5570d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len); 5580d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); 5590d163575Sopenharmony_ci 5600d163575Sopenharmony_ci /* hilink need this router option */ 5610d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len); 5620d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len); 5630d163575Sopenharmony_ci 5640d163575Sopenharmony_ci if ((client_lease != NULL) && (client_lease->cli_addr.addr == requested_ip.addr)) { 5650d163575Sopenharmony_ci if (client_lease->proposed_leasetime != (u32_t)(~0)) { 5660d163575Sopenharmony_ci if (client_lease->flags == DHCPS_ADDRESS_OFFERRED) { 5670d163575Sopenharmony_ci client_lease->leasetime = sys_now() + (client_lease->proposed_leasetime * 1000); 5680d163575Sopenharmony_ci } else { 5690d163575Sopenharmony_ci client_lease->leasetime += (client_lease->proposed_leasetime * 1000); 5700d163575Sopenharmony_ci } 5710d163575Sopenharmony_ci } else { 5720d163575Sopenharmony_ci client_lease->leasetime = client_lease->proposed_leasetime; 5730d163575Sopenharmony_ci } 5740d163575Sopenharmony_ci 5750d163575Sopenharmony_ci client_lease->flags = DHCPS_ADDRESS_BOUND; 5760d163575Sopenharmony_ci srvr_msg->yiaddr.addr = htonl(client_lease->cli_addr.addr); 5770d163575Sopenharmony_ci 5780d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); 5790d163575Sopenharmony_ci dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len); 5800d163575Sopenharmony_ci 5810d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len); 5820d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len); 5830d163575Sopenharmony_ci 5840d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len); 5850d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len); 5860d163575Sopenharmony_ci 5870d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len); 5880d163575Sopenharmony_ci /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */ 5890d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len); 5900d163575Sopenharmony_ci 5910d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len); 5920d163575Sopenharmony_ci dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->netmask)->addr), &options_len); 5930d163575Sopenharmony_ci 5940d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 5950d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 5960d163575Sopenharmony_ci ("handle_request: Send ACK. to=%"U32_F" lease time=%"U32_F"\n", 5970d163575Sopenharmony_ci requested_ip.addr, client_lease->proposed_leasetime)); 5980d163575Sopenharmony_ci#endif 5990d163575Sopenharmony_ci } else { 6000d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); 6010d163575Sopenharmony_ci dhcp_common_option_byte(srvr_msg, DHCP_NAK, &options_len); 6020d163575Sopenharmony_ci 6030d163575Sopenharmony_ci /* Just set this here, so that the NAK message is brcasted. 6040d163575Sopenharmony_ci The correct flags has already been added in the response message during base message creation */ 6050d163575Sopenharmony_ci client_msg->flags |= htons(DHCP_BROADCAST_FLAG); 6060d163575Sopenharmony_ci client_msg->ciaddr.addr = 0; /* This is done so that NAK Gets brcasted */ 6070d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 6080d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 6090d163575Sopenharmony_ci ("handle_request: Send NAK. Requested from=%"U32_F"\n", requested_ip.addr)); 6100d163575Sopenharmony_ci#endif 6110d163575Sopenharmony_ci } 6120d163575Sopenharmony_ci 6130d163575Sopenharmony_ci requested_ip.addr = htonl(requested_ip.addr); 6140d163575Sopenharmony_ci dhcp_common_option_trailer(srvr_msg, options_len, out_msg); 6150d163575Sopenharmony_ci 6160d163575Sopenharmony_ci if (client_msg->ciaddr.addr != 0) { 6170d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sendto(ACK, ciaddr, DHCP_CLIENT_PORT)\n")); 6180d163575Sopenharmony_ci ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr)); 6190d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 6200d163575Sopenharmony_ci } else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) { 6210d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sending reply using brdcast \n")); 6220d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 6230d163575Sopenharmony_ci } else { 6240d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 6250d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Updating ARP Static Entry for unicast reply\n")); 6260d163575Sopenharmony_ci if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) { 6270d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Copy chaddr failed\n")); 6280d163575Sopenharmony_ci (void)pbuf_free(out_msg); 6290d163575Sopenharmony_ci return; 6300d163575Sopenharmony_ci } 6310d163575Sopenharmony_ci if (ERR_OK != etharp_add_static_entry(&requested_ip, ðaddr)) { 6320d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Adding static entry to arp cache failed\n")); 6330d163575Sopenharmony_ci (void)pbuf_free(out_msg); 6340d163575Sopenharmony_ci return; 6350d163575Sopenharmony_ci } 6360d163575Sopenharmony_ci#endif 6370d163575Sopenharmony_ci /* Need to check and add an arp entry to make this pass through smoothly */ 6380d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 6390d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 6400d163575Sopenharmony_ci ("handle_request: sending reply using unicast Client IP =%"U32_F"\n", requested_ip.addr)); 6410d163575Sopenharmony_ci#endif 6420d163575Sopenharmony_ci ip_send.u_addr.ip4.addr = requested_ip.addr; 6430d163575Sopenharmony_ci ip_send.type = IPADDR_TYPE_V4; 6440d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, &ip_send, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 6450d163575Sopenharmony_ci 6460d163575Sopenharmony_ci#if ETHARP_SUPPORT_STATIC_ENTRIES 6470d163575Sopenharmony_ci /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */ 6480d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 6490d163575Sopenharmony_ci ("handle_request: Removing ARP Static Entry added for unicast reply\n")); 6500d163575Sopenharmony_ci (void)etharp_remove_static_entry(&requested_ip); 6510d163575Sopenharmony_ci#endif 6520d163575Sopenharmony_ci } 6530d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: deleting\n")); 6540d163575Sopenharmony_ci 6550d163575Sopenharmony_ci (void)pbuf_free(out_msg); 6560d163575Sopenharmony_ci return; 6570d163575Sopenharmony_ci} 6580d163575Sopenharmony_ci 6590d163575Sopenharmony_ciLWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, 6600d163575Sopenharmony_ci struct dyn_lease_addr *client_lease) 6610d163575Sopenharmony_ci{ 6620d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_decline: Processing Decline Message\n")); 6630d163575Sopenharmony_ci 6640d163575Sopenharmony_ci if ((client_lease != NULL) && (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) && 6650d163575Sopenharmony_ci (client_msg->ciaddr.addr == 0)) { 6660d163575Sopenharmony_ci if (client_lease->cli_addr.addr == (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) { 6670d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 6680d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 6690d163575Sopenharmony_ci ("handle_decline: Marking Client Entry as declined. Client IP =%"U32_F"\n", 6700d163575Sopenharmony_ci client_lease->cli_addr.addr)); 6710d163575Sopenharmony_ci#endif 6720d163575Sopenharmony_ci (void)memset_s(client_lease->cli_hwaddr, sizeof(client_lease->cli_hwaddr), 0, DHCP_CHADDR_LEN); 6730d163575Sopenharmony_ci client_lease->proposed_leasetime = 0; 6740d163575Sopenharmony_ci client_lease->leasetime = sys_now() + (LWIP_DHCPS_DECLINE_TIME * 1000); 6750d163575Sopenharmony_ci client_lease->flags = DHCPS_ADDRESS_DECLINED; 6760d163575Sopenharmony_ci } 6770d163575Sopenharmony_ci } 6780d163575Sopenharmony_ci} 6790d163575Sopenharmony_ci 6800d163575Sopenharmony_ciLWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg) 6810d163575Sopenharmony_ci{ 6820d163575Sopenharmony_ci struct pbuf *out_msg = NULL; 6830d163575Sopenharmony_ci struct dhcp_msg *srvr_msg = NULL; 6840d163575Sopenharmony_ci u16_t options_len = 0; 6850d163575Sopenharmony_ci ip_addr_t dst_addr; 6860d163575Sopenharmony_ci 6870d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Processing Inform Message\n")); 6880d163575Sopenharmony_ci 6890d163575Sopenharmony_ci if (client_msg->ciaddr.addr == 0) { 6900d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: ciaddr is empty. Can't send back a response\n")); 6910d163575Sopenharmony_ci return; 6920d163575Sopenharmony_ci } 6930d163575Sopenharmony_ci 6940d163575Sopenharmony_ci out_msg = dhcps_create_base_msg(client_msg); 6950d163575Sopenharmony_ci if (out_msg == NULL) { 6960d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Creating base message failed\n")); 6970d163575Sopenharmony_ci return; 6980d163575Sopenharmony_ci } 6990d163575Sopenharmony_ci 7000d163575Sopenharmony_ci srvr_msg = (struct dhcp_msg *)out_msg->payload; 7010d163575Sopenharmony_ci dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len); 7020d163575Sopenharmony_ci dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len); 7030d163575Sopenharmony_ci 7040d163575Sopenharmony_ci dhcp_common_option_trailer(srvr_msg, options_len, out_msg); 7050d163575Sopenharmony_ci 7060d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 7070d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 7080d163575Sopenharmony_ci ("handle_inform: Send ACK to Client. Client is=%"U32_F"\n", client_msg->ciaddr.addr)); 7090d163575Sopenharmony_ci#endif 7100d163575Sopenharmony_ci ip_addr_set_ip4_u32_val(dst_addr, client_msg->ciaddr.addr); 7110d163575Sopenharmony_ci (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr)); 7120d163575Sopenharmony_ci 7130d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: deleting pbuf\n")); 7140d163575Sopenharmony_ci (void)pbuf_free(out_msg); 7150d163575Sopenharmony_ci 7160d163575Sopenharmony_ci return; 7170d163575Sopenharmony_ci} 7180d163575Sopenharmony_ci 7190d163575Sopenharmony_ciLWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps, 7200d163575Sopenharmony_ci struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type) 7210d163575Sopenharmony_ci{ 7220d163575Sopenharmony_ci struct dyn_lease_addr *client_lease = NULL; 7230d163575Sopenharmony_ci 7240d163575Sopenharmony_ci client_lease = find_client_lease(dhcps, client_msg); 7250d163575Sopenharmony_ci switch (msg_type) { 7260d163575Sopenharmony_ci case DHCP_DISCOVER: 7270d163575Sopenharmony_ci handle_discover(netif, dhcps, client_msg, client_lease); 7280d163575Sopenharmony_ci break; 7290d163575Sopenharmony_ci case DHCP_REQUEST: 7300d163575Sopenharmony_ci handle_request(netif, dhcps, client_msg, client_lease, serverid); 7310d163575Sopenharmony_ci break; 7320d163575Sopenharmony_ci case DHCP_DECLINE: 7330d163575Sopenharmony_ci handle_decline(netif, dhcps, client_msg, client_lease); 7340d163575Sopenharmony_ci break; 7350d163575Sopenharmony_ci case DHCP_RELEASE: 7360d163575Sopenharmony_ci if ((client_lease != NULL) && (client_lease->cli_addr.addr == ntohl(client_msg->ciaddr.addr))) { 7370d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 7380d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP Release: Client IPAdd =%"U32_F"\n", client_msg->ciaddr.addr)); 7390d163575Sopenharmony_ci#endif 7400d163575Sopenharmony_ci (void)memset_s(client_lease, sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr)); 7410d163575Sopenharmony_ci client_lease->flags = DHCPS_ADDRESS_FREE; 7420d163575Sopenharmony_ci } 7430d163575Sopenharmony_ci break; 7440d163575Sopenharmony_ci case DHCP_INFORM: 7450d163575Sopenharmony_ci handle_inform(netif, dhcps, client_msg); 7460d163575Sopenharmony_ci break; 7470d163575Sopenharmony_ci default: 7480d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 7490d163575Sopenharmony_ci ("DHCP Server. Invalid message type received %d\n", msg_type)); 7500d163575Sopenharmony_ci } 7510d163575Sopenharmony_ci} 7520d163575Sopenharmony_ci 7530d163575Sopenharmony_cierr_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps) 7540d163575Sopenharmony_ci{ 7550d163575Sopenharmony_ci return dhcp_parse_reply(p, &dhcps->dhcp); 7560d163575Sopenharmony_ci} 7570d163575Sopenharmony_ci 7580d163575Sopenharmony_ciLWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *ip_addr, u16_t port) 7590d163575Sopenharmony_ci{ 7600d163575Sopenharmony_ci struct netif *netif = (struct netif *)arg; 7610d163575Sopenharmony_ci struct dhcps *dhcps = netif_get_dhcps(netif); 7620d163575Sopenharmony_ci struct dhcp_msg *client_msg = (struct dhcp_msg *)p->payload; 7630d163575Sopenharmony_ci u8_t msg_type; 7640d163575Sopenharmony_ci ip4_addr_t serverid; 7650d163575Sopenharmony_ci ip4_addr_t addr; 7660d163575Sopenharmony_ci 7670d163575Sopenharmony_ci if (client_msg == NULL) { 7680d163575Sopenharmony_ci return; 7690d163575Sopenharmony_ci } 7700d163575Sopenharmony_ci addr.addr = ip_addr->u_addr.ip4.addr; 7710d163575Sopenharmony_ci serverid.addr = 0; 7720d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 7730d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 7740d163575Sopenharmony_ci ("dhcps_recv(pbuf = %p) from DHCP Client %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, 7750d163575Sopenharmony_ci ip4_addr1_16(&addr), ip4_addr2_16(&addr), ip4_addr3_16(&addr), ip4_addr4_16(&addr), port)); 7760d163575Sopenharmony_ci#endif 7770d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); 7780d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); 7790d163575Sopenharmony_ci /* prevent warnings about unused arguments */ 7800d163575Sopenharmony_ci LWIP_UNUSED_ARG(pcb); 7810d163575Sopenharmony_ci LWIP_UNUSED_ARG(addr); 7820d163575Sopenharmony_ci LWIP_UNUSED_ARG(port); 7830d163575Sopenharmony_ci 7840d163575Sopenharmony_ci dhcps_clear_all_options(dhcps); 7850d163575Sopenharmony_ci 7860d163575Sopenharmony_ci /* Check and remove old entries on each call to dhcp_recv. This way, we don't need to maintain timers */ 7870d163575Sopenharmony_ci remove_stale_entries(dhcps); 7880d163575Sopenharmony_ci 7890d163575Sopenharmony_ci if (p->len < DHCP_OPTIONS_OFS) { 7900d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 7910d163575Sopenharmony_ci ("DHCP client message or pbuf too short. pbuf len =%"U16_F" DHCP MIN Reply Len = %"U32_F"\n", 7920d163575Sopenharmony_ci p->len, DHCP_MIN_REPLY_LEN)); 7930d163575Sopenharmony_ci goto free_pbuf_and_return; 7940d163575Sopenharmony_ci } 7950d163575Sopenharmony_ci 7960d163575Sopenharmony_ci if (client_msg->op != DHCP_BOOTREQUEST) { 7970d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 7980d163575Sopenharmony_ci ("Not a DHCP reply message, Type %"U16_F"\n", (u16_t)client_msg->op)); 7990d163575Sopenharmony_ci goto free_pbuf_and_return; 8000d163575Sopenharmony_ci } 8010d163575Sopenharmony_ci 8020d163575Sopenharmony_ci if (client_msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE)) { 8030d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8040d163575Sopenharmony_ci ("DHCP Server. Cookie Value is incorrect. %"U32_F"\n", (u32_t)client_msg->cookie)); 8050d163575Sopenharmony_ci goto free_pbuf_and_return; 8060d163575Sopenharmony_ci } 8070d163575Sopenharmony_ci 8080d163575Sopenharmony_ci if (client_msg->hlen != ETHARP_HWADDR_LEN) { 8090d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8100d163575Sopenharmony_ci ("DHCP Server. Invalid hardware address length %"U16_F"\n", (u16_t)client_msg->hlen)); 8110d163575Sopenharmony_ci goto free_pbuf_and_return; 8120d163575Sopenharmony_ci } 8130d163575Sopenharmony_ci 8140d163575Sopenharmony_ci if (dhcps_parse_options(p, dhcps) != ERR_OK) { 8150d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8160d163575Sopenharmony_ci ("Parsing of Options failed in DHCP Client Message\n")); 8170d163575Sopenharmony_ci goto free_pbuf_and_return; 8180d163575Sopenharmony_ci } 8190d163575Sopenharmony_ci 8200d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("Searching DHCP_OPTION_MESSAGE_TYPE\n")); 8210d163575Sopenharmony_ci /* obtain pointer to DHCP message type */ 8220d163575Sopenharmony_ci if (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_MSG_TYPE)) { 8230d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8240d163575Sopenharmony_ci ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); 8250d163575Sopenharmony_ci goto free_pbuf_and_return; 8260d163575Sopenharmony_ci } 8270d163575Sopenharmony_ci 8280d163575Sopenharmony_ci /* read DHCP message type */ 8290d163575Sopenharmony_ci msg_type = (u8_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_MSG_TYPE); 8300d163575Sopenharmony_ci 8310d163575Sopenharmony_ci if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_SERVER_ID)) { 8320d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8330d163575Sopenharmony_ci ("DHCP_OPTION_SERVER_ID option found\n")); 8340d163575Sopenharmony_ci /* Parse options would have changed it to host order. But, we have our IP stored in netif in network order */ 8350d163575Sopenharmony_ci serverid.addr = htonl((u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_SERVER_ID)); 8360d163575Sopenharmony_ci } 8370d163575Sopenharmony_ci 8380d163575Sopenharmony_ci if ((serverid.addr != 0) && ((msg_type == DHCP_DISCOVER) || (msg_type == DHCP_INFORM))) { 8390d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8400d163575Sopenharmony_ci ("Serverid present in DHCP_DISCOVER and DHCP_INFORM messages\n")); 8410d163575Sopenharmony_ci goto free_pbuf_and_return; 8420d163575Sopenharmony_ci } 8430d163575Sopenharmony_ci 8440d163575Sopenharmony_ci if ((!ip4_addr_cmp(&serverid, ip_2_ip4(&netif->ip_addr))) && 8450d163575Sopenharmony_ci ((msg_type == DHCP_DECLINE) || (msg_type == DHCP_RELEASE))) { 8460d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 8470d163575Sopenharmony_ci ("Serverid not present in DHCP_RELEASE and DHCP_DECLINE messages\n")); 8480d163575Sopenharmony_ci goto free_pbuf_and_return; 8490d163575Sopenharmony_ci } 8500d163575Sopenharmony_ci 8510d163575Sopenharmony_ci handle_client_messages(netif, dhcps, client_msg, serverid, msg_type); 8520d163575Sopenharmony_ci 8530d163575Sopenharmony_cifree_pbuf_and_return: 8540d163575Sopenharmony_ci (void)pbuf_free(p); 8550d163575Sopenharmony_ci} 8560d163575Sopenharmony_ci 8570d163575Sopenharmony_cierr_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num) 8580d163575Sopenharmony_ci{ 8590d163575Sopenharmony_ci struct dhcps *dhcps = NULL; 8600d163575Sopenharmony_ci ip4_addr_t address_in_hton; 8610d163575Sopenharmony_ci int err; 8620d163575Sopenharmony_ci 8630d163575Sopenharmony_ci LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG); 8640d163575Sopenharmony_ci dhcps = netif_get_dhcps(netif); 8650d163575Sopenharmony_ci 8660d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 8670d163575Sopenharmony_ci ("dhcps_start(netif=%p) %s\n", (void *)netif, netif_get_name(netif))); 8680d163575Sopenharmony_ci 8690d163575Sopenharmony_ci if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { 8700d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 8710d163575Sopenharmony_ci ("MTU =%"U16_F",DHCP Msg Len Required =%"U32_F"\n", netif->mtu, DHCP_MAX_MSG_LEN_MIN_REQUIRED)); 8720d163575Sopenharmony_ci return ERR_MEM; 8730d163575Sopenharmony_ci } 8740d163575Sopenharmony_ci 8750d163575Sopenharmony_ci if (dhcps != NULL) { 8760d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): DHCP Server is already started\n")); 8770d163575Sopenharmony_ci return ERR_MEM; 8780d163575Sopenharmony_ci } 8790d163575Sopenharmony_ci 8800d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting new DHCP Server\n")); 8810d163575Sopenharmony_ci dhcps = (struct dhcps *)mem_malloc(sizeof(struct dhcps)); 8820d163575Sopenharmony_ci if (dhcps == NULL) { 8830d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): could not allocate dhcp\n")); 8840d163575Sopenharmony_ci return ERR_MEM; 8850d163575Sopenharmony_ci } 8860d163575Sopenharmony_ci 8870d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): allocated dhcp")); 8880d163575Sopenharmony_ci 8890d163575Sopenharmony_ci (void)memset_s(dhcps, sizeof(struct dhcps), 0, sizeof(struct dhcps)); 8900d163575Sopenharmony_ci 8910d163575Sopenharmony_ci dhcps->pcb = udp_new(); 8920d163575Sopenharmony_ci if (dhcps->pcb == NULL) { 8930d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate pcb\n")); 8940d163575Sopenharmony_ci mem_free((void *)dhcps); 8950d163575Sopenharmony_ci return ERR_MEM; 8960d163575Sopenharmony_ci } 8970d163575Sopenharmony_ci 8980d163575Sopenharmony_ci#if LWIP_SO_BINDTODEVICE 8990d163575Sopenharmony_ci /* bind dhcp udp_pcb to specific netif, this could make dhcp server start on multiple netif */ 9000d163575Sopenharmony_ci dhcps->pcb->ifindex = netif->ifindex; 9010d163575Sopenharmony_ci#endif 9020d163575Sopenharmony_ci if ((start_ip == NULL) || (ip_num == 0)) { 9030d163575Sopenharmony_ci /* use default ip lease configuration. */ 9040d163575Sopenharmony_ci dhcps->start_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr & ip_2_ip4(&netif->netmask)->addr) + 1; 9050d163575Sopenharmony_ci dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1; 9060d163575Sopenharmony_ci dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1); 9070d163575Sopenharmony_ci if (dhcps->lease_num > LWIP_DHCPS_MAX_LEASE) { 9080d163575Sopenharmony_ci dhcps->lease_num = LWIP_DHCPS_MAX_LEASE; 9090d163575Sopenharmony_ci dhcps->end_addr.addr = dhcps->start_addr.addr + LWIP_DHCPS_MAX_LEASE - 1; 9100d163575Sopenharmony_ci } 9110d163575Sopenharmony_ci } else { 9120d163575Sopenharmony_ci dhcps->start_addr.addr = ntohl(ipaddr_addr(start_ip)); 9130d163575Sopenharmony_ci dhcps->end_addr.addr = (u32_t)(dhcps->start_addr.addr + 9140d163575Sopenharmony_ci (u32_t)(LWIP_MIN(ip_num - 1, LWIP_DHCPS_MAX_LEASE - 1))); 9150d163575Sopenharmony_ci 9160d163575Sopenharmony_ci ip4_addr_set_hton(&address_in_hton, &dhcps->start_addr); 9170d163575Sopenharmony_ci 9180d163575Sopenharmony_ci if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) || 9190d163575Sopenharmony_ci ip4_addr_isbroadcast((&address_in_hton), netif)) { 9200d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): %s in not a valid ip lease\n", start_ip)); 9210d163575Sopenharmony_ci udp_remove(dhcps->pcb); 9220d163575Sopenharmony_ci mem_free((void *)dhcps); 9230d163575Sopenharmony_ci return ERR_ARG; 9240d163575Sopenharmony_ci } 9250d163575Sopenharmony_ci 9260d163575Sopenharmony_ci ip4_addr_set_hton(&address_in_hton, &dhcps->end_addr); 9270d163575Sopenharmony_ci 9280d163575Sopenharmony_ci if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) || 9290d163575Sopenharmony_ci ip4_addr_isbroadcast((&address_in_hton), netif)) { 9300d163575Sopenharmony_ci dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1; 9310d163575Sopenharmony_ci } 9320d163575Sopenharmony_ci dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1); 9330d163575Sopenharmony_ci } 9340d163575Sopenharmony_ci 9350d163575Sopenharmony_ci dhcps->netif = netif; 9360d163575Sopenharmony_ci dhcps->pcb->so_options |= SOF_BROADCAST; 9370d163575Sopenharmony_ci err = udp_bind(dhcps->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); 9380d163575Sopenharmony_ci if (err != ERR_OK) { 9390d163575Sopenharmony_ci udp_remove(dhcps->pcb); 9400d163575Sopenharmony_ci mem_free((void *)dhcps); 9410d163575Sopenharmony_ci return ERR_MEM; 9420d163575Sopenharmony_ci } 9430d163575Sopenharmony_ci 9440d163575Sopenharmony_ci err = udp_connect(dhcps->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); 9450d163575Sopenharmony_ci if (err != ERR_OK) { 9460d163575Sopenharmony_ci udp_remove(dhcps->pcb); 9470d163575Sopenharmony_ci mem_free((void *)dhcps); 9480d163575Sopenharmony_ci return ERR_MEM; 9490d163575Sopenharmony_ci } 9500d163575Sopenharmony_ci udp_recv(dhcps->pcb, dhcps_recv, netif); 9510d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting DHCPS Successfully\n")); 9520d163575Sopenharmony_ci#ifdef LWIP_DEV_DEBUG 9530d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 9540d163575Sopenharmony_ci ("dhcps_start(): DHCPS Conf:: netif addr = %"U32_F" dhcps start addr%"U32_F" dhcp end addr%"U32_F"\n", 9550d163575Sopenharmony_ci ip_2_ip4(&netif->ip_addr)->addr, dhcps->start_addr.addr, dhcps->end_addr.addr)); 9560d163575Sopenharmony_ci#endif 9570d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 9580d163575Sopenharmony_ci ("dhcps_start(): DHCPS Lease Conf:: Lease Time = %"U32_F" Offer Time = %"U32_F"\n", 9590d163575Sopenharmony_ci LWIP_DHCPS_LEASE_TIME, LWIP_DHCPS_OFFER_TIME)); 9600d163575Sopenharmony_ci netif_set_dhcps(netif, dhcps); 9610d163575Sopenharmony_ci return ERR_OK; 9620d163575Sopenharmony_ci} 9630d163575Sopenharmony_ci 9640d163575Sopenharmony_civoid dhcps_stop(struct netif *netif) 9650d163575Sopenharmony_ci{ 9660d163575Sopenharmony_ci LWIP_ERROR("dhcps_stop: netif != NULL", (netif != NULL), return); 9670d163575Sopenharmony_ci struct dhcps *dhcps = netif_get_dhcps(netif); 9680d163575Sopenharmony_ci if (dhcps != NULL) { 9690d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Stopping DHCP Server\n")); 9700d163575Sopenharmony_ci if (dhcps->pcb != NULL) { 9710d163575Sopenharmony_ci LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Removing UDP PCB\n")); 9720d163575Sopenharmony_ci udp_remove(dhcps->pcb); 9730d163575Sopenharmony_ci dhcps->pcb = NULL; 9740d163575Sopenharmony_ci } 9750d163575Sopenharmony_ci 9760d163575Sopenharmony_ci mem_free(dhcps); 9770d163575Sopenharmony_ci netif_set_dhcps(netif, NULL); 9780d163575Sopenharmony_ci } 9790d163575Sopenharmony_ci} 9800d163575Sopenharmony_ci 9810d163575Sopenharmony_ci#endif 9820d163575Sopenharmony_ci 983