更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
dhcps.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/**
33 * @file
34 * Dynamic Host Configuration Protocol Server
35 *
36 */
37
38#include "../core/ipv4/dhcp.c" /* for enum dhcp_option_idx/dhcp_option_xx/dhcp_parse_reply etc. */
39
40#include "lwip/opt.h"
41
42#if (LWIP_DHCP) && (LWIP_DHCPS) /* don't build if not configured for use in lwipopts.h */
43#include <string.h>
44
45#include "lwip/stats.h"
46#include "lwip/mem.h"
47#include "lwip/udp.h"
48#include "lwip/ip_addr.h"
49#include "lwip/netif.h"
50#include "lwip/def.h"
51#include "lwip/prot/dhcp.h"
52#include "lwip/dhcp.h"
53#include "lwip/dhcps.h"
54#include "lwip/sys.h"
55#include "netif/etharp.h"
56
57#define DHCPS_ADDRESS_FREE 0x0
58#define DHCPS_ADDRESS_OFFERRED 0x1
59#define DHCPS_ADDRESS_BOUND 0x2
60#define DHCPS_ADDRESS_DECLINED 0x3
61
62#define LWIP_STATIC static
63#define DHCP_OPTION_ROUTER_SIZE 4
64#define DHCP_OPTION_SUBNET_MASK_SIZE 4
65#define DHCP_OPTION_LEASE_TIME_SIZE 4
66#define DHCP_OPTION_SERVER_ID_LEN 4
67#define DHCP_OPTION_T1_LEN 4
68#define DHCP_OPTION_T2_LEN 4
69
70#define DHCP_CLIENT_PORT 68
71#define DHCP_SERVER_PORT 67
72
73#define DHCP_BROADCAST_FLAG 0x8000
74
76 u8_t cli_hwaddr[DHCP_CHADDR_LEN];
77 u32_t flags;
78 u32_t leasetime;
80 ip4_addr_t cli_addr;
81};
82
83struct dhcps {
84 struct dhcp dhcp;
85 struct udp_pcb *pcb;
86 struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE];
89 struct netif *netif;
90 ip4_addr_t start_addr;
91 ip4_addr_t end_addr;
92};
93
94#define dhcps_option_given(dhcps, idx) dhcp_option_given(&(dhcps)->dhcp, idx)
95#define dhcps_got_option(dhcps, idx) dhcp_got_option(&(dhcps)->dhcp, idx)
96#define dhcps_clear_option(dhcps, idx) dhcp_clear_option(&(dhcps)->dhcp, idx)
97#define dhcps_clear_all_options(dhcps) dhcp_clear_all_options(&(dhcps)->dhcp)
98#define dhcps_get_option_value(dhcps, idx) dhcp_get_option_value(&(dhcps)->dhcp, idx)
99#define dhcps_set_option_value(dhcps, idx, val) dhcp_set_option_value(&(dhcps)->dhcp, idx, val)
100
101#define netif_get_dhcps(netif) ((struct dhcps*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS))
102#define netif_set_dhcps(netif, dhcps) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCPS, dhcps)
103
104LWIP_STATIC void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len);
105LWIP_STATIC void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len);
106LWIP_STATIC void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len);
107LWIP_STATIC void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out);
108LWIP_STATIC err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps);
109
110LWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg);
111LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps);
112LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg);
113LWIP_STATIC int find_free_slot(struct dhcps *dhcps);
114LWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg);
115LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg,
116 struct dyn_lease_addr **client_lease);
117LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg,
118 struct dyn_lease_addr *client_lease);
119LWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg,
120 struct dyn_lease_addr *client_lease, ip4_addr_t serverid);
121LWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg,
122 struct dyn_lease_addr *client_lease, ip4_addr_t serverid);
123LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg,
124 struct dyn_lease_addr *client_lease);
125LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg);
126LWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps,
127 struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type);
128LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
129 const ip_addr_t *ip_addr, u16_t port);
130
131LWIP_STATIC struct pbuf *dhcps_create_base_msg(struct dhcp_msg *client_msg)
132{
133 struct pbuf *srvr_msg_pbuf = NULL;
134 struct dhcp_msg *srvr_msg = NULL;
135
136 srvr_msg_pbuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
137 if (srvr_msg_pbuf == NULL) {
138 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
139 ("dhcps_create_base_msg(): could not allocate pbuf\n"));
140 return NULL;
141 }
142
143 LWIP_ASSERT("dhcps_create_base_msg: check that first pbuf can hold struct dhcp_msg",
144 (srvr_msg_pbuf->len >= sizeof(struct dhcp_msg)));
145#if DRIVER_STATUS_CHECK
146 srvr_msg_pbuf->flags |= PBUF_FLAG_DHCP_BUF;
147#endif
148
149 srvr_msg = (struct dhcp_msg *)srvr_msg_pbuf->payload;
150 srvr_msg->op = DHCP_BOOTREPLY;
151 srvr_msg->htype = client_msg->htype;
152 srvr_msg->hlen = client_msg->hlen;
153 srvr_msg->hops = 0;
154 srvr_msg->xid = client_msg->xid;
155 srvr_msg->secs = 0;
156 srvr_msg->flags = client_msg->flags;
157 ip4_addr_set_zero(&srvr_msg->ciaddr);
158 ip4_addr_set_zero(&srvr_msg->yiaddr);
159 ip4_addr_set_zero(&srvr_msg->siaddr);
160 ip4_addr_copy(srvr_msg->giaddr, client_msg->giaddr);
161 if (memcpy_s(srvr_msg->chaddr, sizeof(srvr_msg->chaddr), client_msg->chaddr, DHCP_CHADDR_LEN) != EOK) {
162 (void)pbuf_free(srvr_msg_pbuf);
163 return NULL;
164 }
165 (void)memset_s(srvr_msg->sname, sizeof(srvr_msg->sname), 0, DHCP_SNAME_LEN);
166 (void)memset_s(srvr_msg->file, sizeof(srvr_msg->file), 0, DHCP_FILE_LEN);
167 srvr_msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
168
169 return srvr_msg_pbuf;
170}
171
172LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps)
173{
174 int i = 0;
175 u32_t curr_time = sys_now();
176
177 for (i = 0; i < dhcps->lease_num; i++) {
178 /* Slot should not be free or have infinite lease time */
179 if ((dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) && (dhcps->leasearr[i].leasetime != (u32_t)~0)) {
180 if (dhcps->leasearr[i].leasetime < curr_time) {
181 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
182 ("remove_stale_entries: Removing Client Entry at Index = %"U32_F"\n", i));
183 (void)memset_s(&(dhcps->leasearr[i]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr));
184 dhcps->leasearr[i].flags = DHCPS_ADDRESS_FREE;
185 }
186 }
187 }
188}
189
190LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg)
191{
192 u32_t client_lease_time = (u32_t)(LWIP_DHCPS_LEASE_TIME);
193
194 if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME))
195#if (LWIP_DHCPS_LEASE_TIME != ~0)
196 && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME)
197#endif
198 ) {
199 client_lease_time = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME);
200 }
201
202 (void)memset_s(&(dhcps->leasearr[idx]), sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr));
203 if (memcpy_s(dhcps->leasearr[idx].cli_hwaddr, DHCP_CHADDR_LEN,
204 client_msg->chaddr, sizeof(client_msg->chaddr)) != EOK) {
205 return;
206 }
207 /* This is called only during offer message, so adding offer time.
208 This is later updated to lease time when request message is handled */
209 dhcps->leasearr[idx].leasetime = sys_now() + (LWIP_DHCPS_OFFER_TIME * 1000);
210 dhcps->leasearr[idx].cli_addr.addr = dhcps->start_addr.addr + idx;
211 dhcps->leasearr[idx].flags = DHCPS_ADDRESS_OFFERRED;
212 dhcps->leasearr[idx].proposed_leasetime = client_lease_time;
213 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("add_client_entry: Adding Client Entry at Index = %"U32_F"\n", idx));
214}
215
216LWIP_STATIC int find_free_slot(struct dhcps *dhcps)
217{
218 int i;
219 for (i = 0; i < dhcps->lease_num; i++) {
220 if ((dhcps->leasearr[i].flags == DHCPS_ADDRESS_FREE) &&
221 (htonl(dhcps->start_addr.addr + (u32_t)i) != ip_2_ip4(&dhcps->netif->ip_addr)->addr)) {
222 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("find_free_slot: Found Free Slot at Index = %"U32_F"\n", i));
223 return i;
224 }
225 }
226
227 return -1;
228}
229
230LWIP_STATIC struct dyn_lease_addr *find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg)
231{
232 int i;
233 for (i = 0; i < dhcps->lease_num; i++) {
234 if (dhcps->leasearr[i].flags != DHCPS_ADDRESS_FREE) {
235 if (memcmp(dhcps->leasearr[i].cli_hwaddr, client_msg->chaddr, client_msg->hlen) == 0) {
236 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
237 ("find_client_lease: Found Client Lease at Index = %"U32_F"\n", i));
238 return &(dhcps->leasearr[i]);
239 }
240 }
241 }
242
243 return NULL;
244}
245
246LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg,
247 struct dyn_lease_addr **client_lease)
248{
249 ip4_addr_t client_ip;
250 int idx = -1;
251
252 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Validating Discover Message\n"));
253
254 client_ip.addr = 0;
255 if (*client_lease == NULL) {
256 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_discover: Existing Client Lease not Found\n"));
257 if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) {
258 client_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP);
259#ifdef LWIP_DEV_DEBUG
260 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
261 ("validate_discover function: Requested IP from client = %"U32_F"\n", client_ip.addr));
262#endif
263
264 if ((client_ip.addr >= dhcps->start_addr.addr) && (client_ip.addr <= dhcps->end_addr.addr)) {
265 idx = (int)(client_ip.addr - dhcps->start_addr.addr);
266 if ((dhcps->leasearr[idx].flags != DHCPS_ADDRESS_FREE) ||
267 (ntohl(client_ip.addr) == ip_2_ip4(&dhcps->netif->ip_addr)->addr)) {
268 /* Requested IP is not available */
269#ifdef LWIP_DEV_DEBUG
270 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
271 ("validate_discover function: Requested IP from client = %"U32_F" Not available \n", client_ip.addr));
272#endif
273 idx = -1;
274 }
275 }
276 }
277
278 if (idx == -1) {
279 idx = find_free_slot(dhcps);
280 if (idx == -1) {
281 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
282 ("validate_discover function: No Free Slot available for Storing addresses\n"));
283 client_ip.addr = 0;
284 return client_ip;
285 }
286 client_ip.addr = dhcps->start_addr.addr + (u32_t)idx;
287#ifdef LWIP_DEV_DEBUG
288 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
289 ("validate_discover function: New IP = %"U32_F" is being assigned\n", client_ip.addr));
290#endif
291 }
292
293 add_client_entry(dhcps, (unsigned int)idx, client_msg);
294 (*client_lease) = &(dhcps->leasearr[idx]);
295 } else {
296 client_ip.addr = (*client_lease)->cli_addr.addr;
297#ifdef LWIP_DEV_DEBUG
298 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
299 ("validate_discover: Existing Client Lease Found. Existing IP =%"U32_F"\n", client_ip.addr));
300#endif
301
302 if ((dhcps_option_given(dhcps, DHCP_OPTION_IDX_LEASE_TIME))
303#if (~0 != LWIP_DHCPS_LEASE_TIME)
304 && (dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME) < LWIP_DHCPS_LEASE_TIME)
305#endif
306 ) {
307 /* Assign the newly requested time or else use the existing lease time as-is */
308 (*client_lease)->proposed_leasetime = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_LEASE_TIME);
309 }
310 }
311
312 return client_ip;
313}
314
315void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len)
316{
317 *options_out_len = dhcp_option(*options_out_len, msg_out->options, option_type, option_len);
318}
319
320void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len)
321{
322 *options_out_len = dhcp_option_byte(*options_out_len, msg_out->options, value);
323}
324
325void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len)
326{
327 *options_out_len = dhcp_option_long(*options_out_len, msg_out->options, value);
328}
329
330void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out)
331{
332 dhcp_option_trailer(options_out_len, msg_out->options, p_out);
333}
334
335LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps,
336 struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease)
337{
338#if !LWIP_DHCPS_DISCOVER_BROADCAST
339 ip_addr_t client_ipaddr;
340#endif
341
342 ip4_addr_t client_ip;
343 ip_addr_t dst_addr;
344 struct pbuf *out_msg = NULL;
345 struct dhcp_msg *srvr_msg = NULL;
346 u16_t options_len = 0;
347#if !LWIP_DHCPS_DISCOVER_BROADCAST
348#if ETHARP_SUPPORT_STATIC_ENTRIES
349 struct eth_addr ethaddr;
350#endif
351#endif
352 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Processing Discover Message\n"));
353
354 client_ip = validate_discover(dhcps, client_msg, &client_lease);
355 if (client_ip.addr == 0) {
356 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
357 ("handle_discover: Returning as unable to get a proper address for client\n"));
358 return;
359 }
360
361 out_msg = dhcps_create_base_msg(client_msg);
362 if (out_msg == NULL) {
363 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
364 ("handle_discover function: Memory allocation for base message failed\n"));
365 return;
366 }
367
368 srvr_msg = (struct dhcp_msg *)out_msg->payload;
369 // no need check msg pointer from payload here
370 srvr_msg->yiaddr.addr = htonl(client_ip.addr);
371
372 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
373 dhcp_common_option_byte(srvr_msg, DHCP_OFFER, &options_len);
374
375 /* hilink need this router option */
376 dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len);
377 dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len);
378
379 /* netif already holds the Server ID in network order. so, no need to convert it again */
380 dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len);
381 dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len);
382
383 dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len);
384 dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len);
385
386 dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len);
387 dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len);
388
389 dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len);
390 /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */
391 dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len);
392
393 /* No need to convert netmask into network order as it is already stored in network order */
394 dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len);
395 dhcp_common_option_long(srvr_msg, ntohl(ip4_addr_get_u32(ip_2_ip4(&netif->netmask))), &options_len);
396
397 dhcp_common_option_trailer(srvr_msg, options_len, out_msg);
398
399 if (client_msg->ciaddr.addr != 0) {
400 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: sendto(OFFER, ciaddr, DHCP_CLIENT_PORT)\n"));
401 ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr));
402 (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
403 }
404#if !LWIP_DHCPS_DISCOVER_BROADCAST
405 else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) {
406 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
407 ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n"));
408 (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
409 } else {
410 client_ip.addr = htonl(client_ip.addr);
411
412#if ETHARP_SUPPORT_STATIC_ENTRIES
413 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Updating ARP Static Entry for unicast reply\n"));
414 if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) {
415 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("memcpy_s failed\n"));
416 (void)pbuf_free(out_msg);
417 return;
418 }
419 if (etharp_add_static_entry(&client_ip, &ethaddr) != ERR_OK) {
420 (void)pbuf_free(out_msg);
421 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Adding static entry to arp cache failed\n"));
422 return;
423 }
424#endif
425
426 /* Need to check and add an arp entry to make this pass through smoothly */
427 ip_addr_copy_from_ip4(client_ipaddr, client_ip);
428 (void)udp_sendto_if_src(dhcps->pcb, out_msg, &client_ipaddr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
429#if ETHARP_SUPPORT_STATIC_ENTRIES
430 /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */
431 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
432 ("handle_discover: Removing ARP Static Entry added for unicast reply\n"));
433 (void)etharp_remove_static_entry(&client_ip);
434#endif
435 }
436#else
437 else {
438 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
439 ("handle_discover: sendto(OFFER, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT)\n"));
440 (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
441 }
442#endif
443
444 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: deleting()ing\n"));
445 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_discover: Sending Reply has been successful\n"));
446
447 (void)pbuf_free(out_msg);
448 return;
449}
450
451LWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg,
452 struct dyn_lease_addr *client_lease, ip4_addr_t serverid)
453{
454 struct dhcps *dhcps = netif_get_dhcps(netif);
455 ip4_addr_t requested_ip;
456 requested_ip.addr = 0;
457
458 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Processing Request Message\n"));
459
460 if ((client_lease != NULL) && (client_lease->flags == DHCPS_ADDRESS_OFFERRED)) {
461 /* Now, we are in selecting state */
462 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: In Selecting State\n"));
463
464 if ((serverid.addr == 0) || (client_msg->ciaddr.addr != 0) ||
465 (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP))) {
466 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
467 ("Server ID or ciaddr or requested ip option is not present\n"));
468 return requested_ip;
469 }
470
471 if (serverid.addr != ip_2_ip4(&netif->ip_addr)->addr) {
472 /* This message is not meant for us. The client intends to talk to some other server */
473 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
474 ("validate_request_message: Server id doesn't match with ours. Message not for us\n"));
475 requested_ip.addr = 1;
476 return requested_ip;
477 }
478
479 requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP);
480 } else {
481 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
482 ("validate_request_message: In Init-Reboot, Renew or Rebinding State\n"));
483
484 /* Now, we can be either in Init-reboot state or renew state or rebinding state */
485 if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) {
486 /* Requested IP option is filled in. Indicates we are mostly in Init-Reboot State */
487 if (client_lease == NULL) {
488 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
489 ("validate_request_message: No Configuration found corresponding to request message\n"));
490 return requested_ip;
491 }
492
493 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
494 ("validate_request_message: Requested IP Option is present. So, considering as Init-Reboot State\n"));
495
496 if (client_msg->ciaddr.addr != 0) {
497 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
498 ("validate_request_message: Error: ciaddr is filled in the Init-Reboot state. \n"));
499 return requested_ip;
500 }
501
502 requested_ip.addr = (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP);
503 } else {
504 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: \
505 Requested IP Option is not present. So, considering as Renewing or Rebinding State\n"));
506
507 if (client_msg->ciaddr.addr == 0) {
508 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
509 ("validate_request_message: Error: ciaddr is not filled in the Renewing or Rebinding state. \n"));
510 return requested_ip;
511 }
512
513 requested_ip.addr = ntohl(client_msg->ciaddr.addr);
514 }
515 }
516
517 /* requested_ip is in host order and DHCP Server IP is in network order,
518 so converting the former to network order for check */
519 if (htonl(requested_ip.addr) == ip_2_ip4(&netif->ip_addr)->addr) {
520 /* This requested_ip is the dhcp server is using, it is invalid */
521 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("validate_request_message: Requested IP addr is invalid\n"));
522 requested_ip.addr = 1;
523 }
524
525 return requested_ip;
526}
527
528LWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg,
529 struct dyn_lease_addr *client_lease, ip4_addr_t serverid)
530{
531 ip4_addr_t requested_ip;
532 struct pbuf *out_msg = NULL;
533 struct dhcp_msg *srvr_msg = NULL;
534 u16_t options_len = 0;
535 ip_addr_t dst_addr;
536 ip_addr_t ip_send;
537#if ETHARP_SUPPORT_STATIC_ENTRIES
538 struct eth_addr ethaddr;
539#endif
540
541 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Processing Request Message\n"));
542
543 requested_ip = validate_request_message(netif, client_msg, client_lease, serverid);
544 if (requested_ip.addr == 1) {
545 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
546 ("handle_request: Validation of request message failed. Dropping the packet.\n"));
547 return;
548 }
549
550 out_msg = dhcps_create_base_msg(client_msg);
551 if (out_msg == NULL) {
552 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Creating base message failed\n"));
553 return;
554 }
555
556 srvr_msg = (struct dhcp_msg *)out_msg->payload;
557 dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len);
558 dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len);
559
560 /* hilink need this router option */
561 dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len);
562 dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->ip_addr)->addr), &options_len);
563
564 if ((client_lease != NULL) && (client_lease->cli_addr.addr == requested_ip.addr)) {
565 if (client_lease->proposed_leasetime != (u32_t)(~0)) {
566 if (client_lease->flags == DHCPS_ADDRESS_OFFERRED) {
567 client_lease->leasetime = sys_now() + (client_lease->proposed_leasetime * 1000);
568 } else {
569 client_lease->leasetime += (client_lease->proposed_leasetime * 1000);
570 }
571 } else {
572 client_lease->leasetime = client_lease->proposed_leasetime;
573 }
574
575 client_lease->flags = DHCPS_ADDRESS_BOUND;
576 srvr_msg->yiaddr.addr = htonl(client_lease->cli_addr.addr);
577
578 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
579 dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len);
580
581 dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len);
582 dhcp_common_option_long(srvr_msg, client_lease->proposed_leasetime, &options_len);
583
584 dhcp_common_option(srvr_msg, DHCP_OPTION_T1, DHCP_OPTION_T1_LEN, &options_len);
585 dhcp_common_option_long(srvr_msg, (client_lease->proposed_leasetime / 2), &options_len);
586
587 dhcp_common_option(srvr_msg, DHCP_OPTION_T2, DHCP_OPTION_T2_LEN, &options_len);
588 /* calculate safe periods for lease (proposed_leasetime * 0.875 -> 87.5%) */
589 dhcp_common_option_long(srvr_msg, ((client_lease->proposed_leasetime * 7) / 8), &options_len);
590
591 dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len);
592 dhcp_common_option_long(srvr_msg, ntohl(ip_2_ip4(&netif->netmask)->addr), &options_len);
593
594#ifdef LWIP_DEV_DEBUG
595 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
596 ("handle_request: Send ACK. to=%"U32_F" lease time=%"U32_F"\n",
597 requested_ip.addr, client_lease->proposed_leasetime));
598#endif
599 } else {
600 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
601 dhcp_common_option_byte(srvr_msg, DHCP_NAK, &options_len);
602
603 /* Just set this here, so that the NAK message is brcasted.
604 The correct flags has already been added in the respose message during base message creation */
605 client_msg->flags |= htons(DHCP_BROADCAST_FLAG);
606 client_msg->ciaddr.addr = 0; /* This is done so that NAK Gets brcasted */
607#ifdef LWIP_DEV_DEBUG
608 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
609 ("handle_request: Send NAK. Requested from=%"U32_F"\n", requested_ip.addr));
610#endif
611 }
612
613 requested_ip.addr = htonl(requested_ip.addr);
614 dhcp_common_option_trailer(srvr_msg, options_len, out_msg);
615
616 if (client_msg->ciaddr.addr != 0) {
617 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sendto(ACK, ciaddr, DHCP_CLIENT_PORT)\n"));
618 ip_addr_set_ip4_u32_val(dst_addr, (u32_t)(client_msg->ciaddr.addr));
619 (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
620 } else if (ntohs(client_msg->flags) & DHCP_BROADCAST_FLAG) {
621 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: sending reply using brdcast \n"));
622 (void)udp_sendto_if_src(dhcps->pcb, out_msg, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
623 } else {
624#if ETHARP_SUPPORT_STATIC_ENTRIES
625 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Updating ARP Static Entry for unicast reply\n"));
626 if (memcpy_s(ethaddr.addr, ETHARP_HWADDR_LEN, client_msg->chaddr, client_msg->hlen) != EOK) {
627 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Copy chaddr failed\n"));
628 (void)pbuf_free(out_msg);
629 return;
630 }
631 if (ERR_OK != etharp_add_static_entry(&requested_ip, &ethaddr)) {
632 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: Adding static entry to arp cache failed\n"));
633 (void)pbuf_free(out_msg);
634 return;
635 }
636#endif
637 /* Need to check and add an arp entry to make this pass through smoothly */
638#ifdef LWIP_DEV_DEBUG
639 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
640 ("handle_request: sending reply using unicast Client IP =%"U32_F"\n", requested_ip.addr));
641#endif
642 ip_send.u_addr.ip4.addr = requested_ip.addr;
643 ip_send.type = IPADDR_TYPE_V4;
644 (void)udp_sendto_if_src(dhcps->pcb, out_msg, &ip_send, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
645
646#if ETHARP_SUPPORT_STATIC_ENTRIES
647 /* We just added the entry above and checked for it's success too. so, the below function call cannot fail */
648 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
649 ("handle_request: Removing ARP Static Entry added for unicast reply\n"));
650 (void)etharp_remove_static_entry(&requested_ip);
651#endif
652 }
653 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_request: deleting\n"));
654
655 (void)pbuf_free(out_msg);
656 return;
657}
658
659LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg,
660 struct dyn_lease_addr *client_lease)
661{
662 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_decline: Processing Decline Message\n"));
663
664 if ((client_lease != NULL) && (dhcps_option_given(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) &&
665 (client_msg->ciaddr.addr == 0)) {
666 if (client_lease->cli_addr.addr == (u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) {
667#ifdef LWIP_DEV_DEBUG
668 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
669 ("handle_decline: Marking Client Entry as declined. Client IP =%"U32_F"\n",
670 client_lease->cli_addr.addr));
671#endif
672 (void)memset_s(client_lease->cli_hwaddr, sizeof(client_lease->cli_hwaddr), 0, DHCP_CHADDR_LEN);
673 client_lease->proposed_leasetime = 0;
674 client_lease->leasetime = sys_now() + (LWIP_DHCPS_DECLINE_TIME * 1000);
675 client_lease->flags = DHCPS_ADDRESS_DECLINED;
676 }
677 }
678}
679
680LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg)
681{
682 struct pbuf *out_msg = NULL;
683 struct dhcp_msg *srvr_msg = NULL;
684 u16_t options_len = 0;
685 ip_addr_t dst_addr;
686
687 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Processing Inform Message\n"));
688
689 if (client_msg->ciaddr.addr == 0) {
690 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: ciaddr is empty. Can't send back a response\n"));
691 return;
692 }
693
694 out_msg = dhcps_create_base_msg(client_msg);
695 if (out_msg == NULL) {
696 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: Creating base message failed\n"));
697 return;
698 }
699
700 srvr_msg = (struct dhcp_msg *)out_msg->payload;
701 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
702 dhcp_common_option_byte(srvr_msg, DHCP_ACK, &options_len);
703
704 dhcp_common_option_trailer(srvr_msg, options_len, out_msg);
705
706#ifdef LWIP_DEV_DEBUG
707 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
708 ("handle_inform: Send ACK to Client. Client is=%"U32_F"\n", client_msg->ciaddr.addr));
709#endif
710 ip_addr_set_ip4_u32_val(dst_addr, client_msg->ciaddr.addr);
711 (void)udp_sendto_if_src(dhcps->pcb, out_msg, &dst_addr, DHCP_CLIENT_PORT, netif, &(netif->ip_addr));
712
713 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("handle_inform: deleting pbuf\n"));
714 (void)pbuf_free(out_msg);
715
716 return;
717}
718
719LWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps,
720 struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type)
721{
722 struct dyn_lease_addr *client_lease = NULL;
723
724 client_lease = find_client_lease(dhcps, client_msg);
725 switch (msg_type) {
726 case DHCP_DISCOVER:
727 handle_discover(netif, dhcps, client_msg, client_lease);
728 break;
729 case DHCP_REQUEST:
730 handle_request(netif, dhcps, client_msg, client_lease, serverid);
731 break;
732 case DHCP_DECLINE:
733 handle_decline(netif, dhcps, client_msg, client_lease);
734 break;
735 case DHCP_RELEASE:
736 if ((client_lease != NULL) && (client_lease->cli_addr.addr == ntohl(client_msg->ciaddr.addr))) {
737#ifdef LWIP_DEV_DEBUG
738 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP Release: Client IPAdd =%"U32_F"\n", client_msg->ciaddr.addr));
739#endif
740 (void)memset_s(client_lease, sizeof(struct dyn_lease_addr), 0, sizeof(struct dyn_lease_addr));
741 client_lease->flags = DHCPS_ADDRESS_FREE;
742 }
743 break;
744 case DHCP_INFORM:
745 handle_inform(netif, dhcps, client_msg);
746 break;
747 default:
748 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
749 ("DHCP Server. Invalid message type received %d\n", msg_type));
750 }
751}
752
753err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps)
754{
755 return dhcp_parse_reply(p, &dhcps->dhcp);
756}
757
758LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *ip_addr, u16_t port)
759{
760 struct netif *netif = (struct netif *)arg;
761 struct dhcps *dhcps = netif_get_dhcps(netif);
762 struct dhcp_msg *client_msg = (struct dhcp_msg *)p->payload;
763 u8_t msg_type;
764 ip4_addr_t serverid;
765 ip4_addr_t addr;
766
767 if (client_msg == NULL) {
768 return;
769 }
770 addr.addr = ip_addr->u_addr.ip4.addr;
771 serverid.addr = 0;
772#ifdef LWIP_DEV_DEBUG
773 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
774 ("dhcps_recv(pbuf = %p) from DHCP Client %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
775 ip4_addr1_16(&addr), ip4_addr2_16(&addr), ip4_addr3_16(&addr), ip4_addr4_16(&addr), port));
776#endif
777 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
778 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
779 /* prevent warnings about unused arguments */
780 LWIP_UNUSED_ARG(pcb);
781 LWIP_UNUSED_ARG(addr);
782 LWIP_UNUSED_ARG(port);
783
784 dhcps_clear_all_options(dhcps);
785
786 /* Check and remove old entries on each call to dhcp_recv. This way, we don't need to maintain timers */
788
789 if (p->len < DHCP_OPTIONS_OFS) {
790 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
791 ("DHCP client message or pbuf too short. pbuf len =%"U16_F" DHCP MIN Reply Len = %"U32_F"\n",
792 p->len, DHCP_MIN_REPLY_LEN));
793 goto free_pbuf_and_return;
794 }
795
796 if (client_msg->op != DHCP_BOOTREQUEST) {
797 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
798 ("Not a DHCP reply message, Type %"U16_F"\n", (u16_t)client_msg->op));
799 goto free_pbuf_and_return;
800 }
801
802 if (client_msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE)) {
803 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
804 ("DHCP Server. Cookie Value is incorrect. %"U32_F"\n", (u32_t)client_msg->cookie));
805 goto free_pbuf_and_return;
806 }
807
808 if (client_msg->hlen != ETHARP_HWADDR_LEN) {
809 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
810 ("DHCP Server. Invalid hardware address length %"U16_F"\n", (u16_t)client_msg->hlen));
811 goto free_pbuf_and_return;
812 }
813
814 if (dhcps_parse_options(p, dhcps) != ERR_OK) {
815 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
816 ("Parsing of Options failed in DHCP Client Message\n"));
817 goto free_pbuf_and_return;
818 }
819
820 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("Searching DHCP_OPTION_MESSAGE_TYPE\n"));
821 /* obtain pointer to DHCP message type */
822 if (!dhcps_option_given(dhcps, DHCP_OPTION_IDX_MSG_TYPE)) {
823 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
824 ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
825 goto free_pbuf_and_return;
826 }
827
828 /* read DHCP message type */
829 msg_type = (u8_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_MSG_TYPE);
830
831 if (dhcps_option_given(dhcps, DHCP_OPTION_IDX_SERVER_ID)) {
832 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
833 ("DHCP_OPTION_SERVER_ID option found\n"));
834 /* Parse options would have changed it to host order. But, we have our IP stored in netif in network order */
835 serverid.addr = htonl((u32_t)dhcps_get_option_value(dhcps, DHCP_OPTION_IDX_SERVER_ID));
836 }
837
838 if ((serverid.addr != 0) && ((msg_type == DHCP_DISCOVER) || (msg_type == DHCP_INFORM))) {
839 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
840 ("Serverid present in DHCP_DISCOVER and DHCP_INFORM messages\n"));
841 goto free_pbuf_and_return;
842 }
843
844 if ((!ip4_addr_cmp(&serverid, ip_2_ip4(&netif->ip_addr))) &&
845 ((msg_type == DHCP_DECLINE) || (msg_type == DHCP_RELEASE))) {
846 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
847 ("Serverid not present in DHCP_RELEASE and DHCP_DECLINE messages\n"));
848 goto free_pbuf_and_return;
849 }
850
851 handle_client_messages(netif, dhcps, client_msg, serverid, msg_type);
852
853free_pbuf_and_return:
854 (void)pbuf_free(p);
855}
856
857err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num)
858{
859 struct dhcps *dhcps = NULL;
860 ip4_addr_t address_in_hton;
861 int err;
862
863 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
864 dhcps = netif_get_dhcps(netif);
865
866 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
867 ("dhcps_start(netif=%p) %s\n", (void *)netif, netif_get_name(netif)));
868
869 if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
870 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
871 ("MTU =%"U16_F",DHCP Msg Len Required =%"U32_F"\n", netif->mtu, DHCP_MAX_MSG_LEN_MIN_REQUIRED));
872 return ERR_MEM;
873 }
874
875 if (dhcps != NULL) {
876 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): DHCP Server is already started\n"));
877 return ERR_MEM;
878 }
879
880 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting new DHCP Server\n"));
881 dhcps = (struct dhcps *)mem_malloc(sizeof(struct dhcps));
882 if (dhcps == NULL) {
883 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): could not allocate dhcp\n"));
884 return ERR_MEM;
885 }
886
887 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): allocated dhcp"));
888
889 (void)memset_s(dhcps, sizeof(struct dhcps), 0, sizeof(struct dhcps));
890
891 dhcps->pcb = udp_new();
892 if (dhcps->pcb == NULL) {
893 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate pcb\n"));
894 mem_free((void *)dhcps);
895 return ERR_MEM;
896 }
897
898#if LWIP_SO_BINDTODEVICE
899 /* bind dhcp udp_pcb to specific netif, this could make dhcp server start on multiple netif */
900 dhcps->pcb->ifindex = netif->ifindex;
901#endif
902 if ((start_ip == NULL) || (ip_num == 0)) {
903 /* use default ip lease configuration. */
904 dhcps->start_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr & ip_2_ip4(&netif->netmask)->addr) + 1;
905 dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1;
906 dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1);
907 if (dhcps->lease_num > LWIP_DHCPS_MAX_LEASE) {
908 dhcps->lease_num = LWIP_DHCPS_MAX_LEASE;
909 dhcps->end_addr.addr = dhcps->start_addr.addr + LWIP_DHCPS_MAX_LEASE - 1;
910 }
911 } else {
912 dhcps->start_addr.addr = ntohl(ipaddr_addr(start_ip));
913 dhcps->end_addr.addr = (u32_t)(dhcps->start_addr.addr +
914 (u32_t)(LWIP_MIN(ip_num - 1, LWIP_DHCPS_MAX_LEASE - 1)));
915
916 ip4_addr_set_hton(&address_in_hton, &dhcps->start_addr);
917
918 if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) ||
919 ip4_addr_isbroadcast((&address_in_hton), netif)) {
920 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): %s in not a valid ip lease\n", start_ip));
921 udp_remove(dhcps->pcb);
922 mem_free((void *)dhcps);
923 return ERR_ARG;
924 }
925
926 ip4_addr_set_hton(&address_in_hton, &dhcps->end_addr);
927
928 if (!ip4_addr_netcmp((&address_in_hton), ip_2_ip4(&netif->ip_addr), ip_2_ip4(&netif->netmask)) ||
929 ip4_addr_isbroadcast((&address_in_hton), netif)) {
930 dhcps->end_addr.addr = ntohl(ip_2_ip4(&netif->ip_addr)->addr | (~ip_2_ip4(&netif->netmask)->addr)) - 1;
931 }
932 dhcps->lease_num = (u8_t)(dhcps->end_addr.addr - dhcps->start_addr.addr + 1);
933 }
934
935 dhcps->netif = netif;
936 dhcps->pcb->so_options |= SOF_BROADCAST;
937 err = udp_bind(dhcps->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
938 if (err != ERR_OK) {
939 udp_remove(dhcps->pcb);
940 mem_free((void *)dhcps);
941 return ERR_MEM;
942 }
943
944 err = udp_connect(dhcps->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
945 if (err != ERR_OK) {
946 udp_remove(dhcps->pcb);
947 mem_free((void *)dhcps);
948 return ERR_MEM;
949 }
950 udp_recv(dhcps->pcb, dhcps_recv, netif);
951 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_start(): starting DHCPS Successfully\n"));
952#ifdef LWIP_DEV_DEBUG
953 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
954 ("dhcps_start(): DHCPS Conf:: netif addr = %"U32_F" dhcps start addr%"U32_F" dhcp end addr%"U32_F"\n",
955 ip_2_ip4(&netif->ip_addr)->addr, dhcps->start_addr.addr, dhcps->end_addr.addr));
956#endif
957 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
958 ("dhcps_start(): DHCPS Lease Conf:: Lease Time = %"U32_F" Offer Time = %"U32_F"\n",
959 LWIP_DHCPS_LEASE_TIME, LWIP_DHCPS_OFFER_TIME));
960 netif_set_dhcps(netif, dhcps);
961 return ERR_OK;
962}
963
964void dhcps_stop(struct netif *netif)
965{
966 LWIP_ERROR("dhcps_stop: netif != NULL", (netif != NULL), return);
967 struct dhcps *dhcps = netif_get_dhcps(netif);
968 if (dhcps != NULL) {
969 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Stopping DHCP Server\n"));
970 if (dhcps->pcb != NULL) {
971 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcps_stop(): Removing UDP PCB\n"));
972 udp_remove(dhcps->pcb);
973 dhcps->pcb = NULL;
974 }
975
976 mem_free(dhcps);
977 netif_set_dhcps(netif, NULL);
978 }
979}
980
981#endif
982
LWIP_STATIC struct dyn_lease_addr * find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg)
Definition: dhcps.c:230
LWIP_STATIC struct pbuf * dhcps_create_base_msg(struct dhcp_msg *client_msg)
Definition: dhcps.c:131
LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr **client_lease)
Definition: dhcps.c:246
LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg)
Definition: dhcps.c:190
LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps)
Definition: dhcps.c:172
LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg)
Definition: dhcps.c:680
LWIP_STATIC void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len)
Definition: dhcps.c:325
void dhcps_stop(struct netif *netif)
Definition: dhcps.c:964
LWIP_STATIC ip4_addr_t validate_request_message(struct netif *netif, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease, ip4_addr_t serverid)
Definition: dhcps.c:451
LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease)
Definition: dhcps.c:335
LWIP_STATIC void handle_client_messages(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type)
Definition: dhcps.c:719
LWIP_STATIC void handle_request(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease, ip4_addr_t serverid)
Definition: dhcps.c:528
LWIP_STATIC void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out)
Definition: dhcps.c:330
LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease)
Definition: dhcps.c:659
LWIP_STATIC int find_free_slot(struct dhcps *dhcps)
Definition: dhcps.c:216
err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num)
Definition: dhcps.c:857
LWIP_STATIC err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps)
Definition: dhcps.c:753
LWIP_STATIC void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len)
Definition: dhcps.c:320
LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *ip_addr, u16_t port)
Definition: dhcps.c:758
LWIP_STATIC void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len)
Definition: dhcps.c:315
int memcmp(const void *str1, const void *str2, size_t n)
Definition: memcmp.c:37
Definition: dhcps.c:83
u8_t pcb_allocated
Definition: dhcps.c:87
struct dhcp dhcp
Definition: dhcps.c:84
struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE]
Definition: dhcps.c:86
u8_t lease_num
Definition: dhcps.c:88
ip4_addr_t end_addr
Definition: dhcps.c:91
ip4_addr_t start_addr
Definition: dhcps.c:90
struct udp_pcb * pcb
Definition: dhcps.c:85
struct netif * netif
Definition: dhcps.c:89
u32_t flags
Definition: dhcps.c:77
u32_t leasetime
Definition: dhcps.c:78
u32_t proposed_leasetime
Definition: dhcps.c:79
ip4_addr_t cli_addr
Definition: dhcps.c:80
u8_t cli_hwaddr[DHCP_CHADDR_LEN]
Definition: dhcps.c:76
u32_t sys_now(void)
Definition: sys_arch.c:92
ARG_NUM_3 int
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
if(tv==NULL)
Definition: time.c:430