38#include "../core/ipv4/dhcp.c"
42#if (LWIP_DHCP) && (LWIP_DHCPS)
45#include "lwip/stats.h"
48#include "lwip/ip_addr.h"
51#include "lwip/prot/dhcp.h"
55#include "netif/etharp.h"
57#define DHCPS_ADDRESS_FREE 0x0
58#define DHCPS_ADDRESS_OFFERRED 0x1
59#define DHCPS_ADDRESS_BOUND 0x2
60#define DHCPS_ADDRESS_DECLINED 0x3
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
70#define DHCP_CLIENT_PORT 68
71#define DHCP_SERVER_PORT 67
73#define DHCP_BROADCAST_FLAG 0x8000
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)
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)
104LWIP_STATIC
void dhcp_common_option(
struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len);
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);
133 struct pbuf *srvr_msg_pbuf = NULL;
134 struct dhcp_msg *srvr_msg = NULL;
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"));
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;
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;
154 srvr_msg->xid = client_msg->xid;
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);
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);
169 return srvr_msg_pbuf;
181 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
182 (
"remove_stale_entries: Removing Client Entry at Index = %"U32_F
"\n", i));
192 u32_t client_lease_time = (u32_t)(LWIP_DHCPS_LEASE_TIME);
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)
199 client_lease_time = (u32_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_LEASE_TIME);
204 client_msg->chaddr,
sizeof(client_msg->chaddr)) != EOK) {
213 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"add_client_entry: Adding Client Entry at Index = %"U32_F
"\n", idx));
222 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"find_free_slot: Found Free Slot at Index = %"U32_F
"\n", i));
236 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
237 (
"find_client_lease: Found Client Lease at Index = %"U32_F
"\n", i));
249 ip4_addr_t client_ip;
252 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"validate_discover: Validating Discover Message\n"));
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);
260 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
261 (
"validate_discover function: Requested IP from client = %"U32_F
"\n", client_ip.addr));
267 (ntohl(client_ip.addr) == ip_2_ip4(&
dhcps->
netif->ip_addr)->addr)) {
270 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
271 (
"validate_discover function: Requested IP from client = %"U32_F
" Not available \n", client_ip.addr));
281 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
282 (
"validate_discover function: No Free Slot available for Storing addresses\n"));
288 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
289 (
"validate_discover function: New IP = %"U32_F
" is being assigned\n", client_ip.addr));
296 client_ip.addr = (*client_lease)->cli_addr.addr;
298 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
299 (
"validate_discover: Existing Client Lease Found. Existing IP =%"U32_F
"\n", client_ip.addr));
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)
308 (*client_lease)->proposed_leasetime = (u32_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_LEASE_TIME);
315void dhcp_common_option(
struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len)
317 *options_out_len = dhcp_option(*options_out_len, msg_out->options, option_type, option_len);
322 *options_out_len = dhcp_option_byte(*options_out_len, msg_out->options, value);
327 *options_out_len = dhcp_option_long(*options_out_len, msg_out->options, value);
332 dhcp_option_trailer(options_out_len, msg_out->options, p_out);
338#if !LWIP_DHCPS_DISCOVER_BROADCAST
339 ip_addr_t client_ipaddr;
342 ip4_addr_t client_ip;
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;
352 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_discover: Processing Discover Message\n"));
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"));
362 if (out_msg == NULL) {
363 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
364 (
"handle_discover function: Memory allocation for base message failed\n"));
368 srvr_msg = (
struct dhcp_msg *)out_msg->payload;
370 srvr_msg->yiaddr.addr = htonl(client_ip.addr);
372 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
376 dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len);
380 dhcp_common_option(srvr_msg, DHCP_OPTION_SERVER_ID, DHCP_OPTION_SERVER_ID_LEN, &options_len);
383 dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len);
394 dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len);
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));
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));
410 client_ip.addr = htonl(client_ip.addr);
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);
419 if (etharp_add_static_entry(&client_ip, ðaddr) != 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"));
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
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);
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));
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"));
447 (
void)pbuf_free(out_msg);
455 ip4_addr_t requested_ip;
456 requested_ip.addr = 0;
458 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"validate_request_message: Processing Request Message\n"));
460 if ((client_lease != NULL) && (client_lease->
flags == DHCPS_ADDRESS_OFFERRED)) {
462 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"validate_request_message: In Selecting State\n"));
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"));
471 if (serverid.addr != ip_2_ip4(&
netif->ip_addr)->addr) {
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;
479 requested_ip.addr = (u32_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_REQUESTED_IP);
481 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
482 (
"validate_request_message: In Init-Reboot, Renew or Rebinding State\n"));
485 if (dhcps_option_given(
dhcps, DHCP_OPTION_IDX_REQUESTED_IP)) {
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"));
493 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
494 (
"validate_request_message: Requested IP Option is present. So, considering as Init-Reboot State\n"));
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"));
502 requested_ip.addr = (u32_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_REQUESTED_IP);
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"));
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"));
513 requested_ip.addr = ntohl(client_msg->ciaddr.addr);
519 if (htonl(requested_ip.addr) == ip_2_ip4(&
netif->ip_addr)->addr) {
521 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"validate_request_message: Requested IP addr is invalid\n"));
522 requested_ip.addr = 1;
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;
537#if ETHARP_SUPPORT_STATIC_ENTRIES
538 struct eth_addr ethaddr;
541 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_request: Processing Request Message\n"));
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"));
551 if (out_msg == NULL) {
552 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_request: Creating base message failed\n"));
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);
561 dhcp_common_option(srvr_msg, DHCP_OPTION_ROUTER, DHCP_OPTION_ROUTER_SIZE, &options_len);
564 if ((client_lease != NULL) && (client_lease->
cli_addr.addr == requested_ip.addr)) {
566 if (client_lease->
flags == DHCPS_ADDRESS_OFFERRED) {
575 client_lease->
flags = DHCPS_ADDRESS_BOUND;
576 srvr_msg->yiaddr.addr = htonl(client_lease->
cli_addr.addr);
578 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
581 dhcp_common_option(srvr_msg, DHCP_OPTION_LEASE_TIME, DHCP_OPTION_LEASE_TIME_SIZE, &options_len);
591 dhcp_common_option(srvr_msg, DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_SUBNET_MASK_SIZE, &options_len);
595 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
596 (
"handle_request: Send ACK. to=%"U32_F
" lease time=%"U32_F
"\n",
600 dhcp_common_option(srvr_msg, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, &options_len);
605 client_msg->flags |= htons(DHCP_BROADCAST_FLAG);
606 client_msg->ciaddr.addr = 0;
608 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
609 (
"handle_request: Send NAK. Requested from=%"U32_F
"\n", requested_ip.addr));
613 requested_ip.addr = htonl(requested_ip.addr);
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));
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);
631 if (ERR_OK != etharp_add_static_entry(&requested_ip, ðaddr)) {
632 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_request: Adding static entry to arp cache failed\n"));
633 (
void)pbuf_free(out_msg);
639 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
640 (
"handle_request: sending reply using unicast Client IP =%"U32_F
"\n", requested_ip.addr));
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));
646#if ETHARP_SUPPORT_STATIC_ENTRIES
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);
653 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_request: deleting\n"));
655 (
void)pbuf_free(out_msg);
662 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_decline: Processing Decline Message\n"));
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)) {
668 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
669 (
"handle_decline: Marking Client Entry as declined. Client IP =%"U32_F
"\n",
675 client_lease->
flags = DHCPS_ADDRESS_DECLINED;
682 struct pbuf *out_msg = NULL;
683 struct dhcp_msg *srvr_msg = NULL;
684 u16_t options_len = 0;
687 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_inform: Processing Inform Message\n"));
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"));
695 if (out_msg == NULL) {
696 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_inform: Creating base message failed\n"));
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);
707 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
708 (
"handle_inform: Send ACK to Client. Client is=%"U32_F
"\n", client_msg->ciaddr.addr));
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));
713 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"handle_inform: deleting pbuf\n"));
714 (
void)pbuf_free(out_msg);
720 struct dhcp_msg *client_msg, ip4_addr_t serverid, u8_t msg_type)
736 if ((client_lease != NULL) && (client_lease->
cli_addr.addr == ntohl(client_msg->ciaddr.addr))) {
738 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"DHCP Release: Client IPAdd =%"U32_F
"\n", client_msg->ciaddr.addr));
741 client_lease->
flags = DHCPS_ADDRESS_FREE;
748 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
749 (
"DHCP Server. Invalid message type received %d\n", msg_type));
755 return dhcp_parse_reply(p, &
dhcps->
dhcp);
758LWIP_STATIC
void dhcps_recv(
void *arg,
struct udp_pcb *pcb,
struct pbuf *p,
const ip_addr_t *ip_addr, u16_t port)
760 struct netif *netif = (
struct netif *)arg;
762 struct dhcp_msg *client_msg = (
struct dhcp_msg *)p->payload;
767 if (client_msg == NULL) {
770 addr.addr = ip_addr->u_addr.ip4.addr;
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));
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));
780 LWIP_UNUSED_ARG(pcb);
781 LWIP_UNUSED_ARG(addr);
782 LWIP_UNUSED_ARG(port);
784 dhcps_clear_all_options(
dhcps);
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;
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;
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;
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;
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;
820 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"Searching DHCP_OPTION_MESSAGE_TYPE\n"));
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;
829 msg_type = (u8_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_MSG_TYPE);
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"));
835 serverid.addr = htonl((u32_t)dhcps_get_option_value(
dhcps, DHCP_OPTION_IDX_SERVER_ID));
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;
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;
857err_t
dhcps_start(
struct netif *netif,
const char *start_ip, u16_t ip_num)
860 ip4_addr_t address_in_hton;
863 LWIP_ERROR(
"netif != NULL", (
netif != NULL),
return ERR_ARG);
866 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
867 (
"dhcps_start(netif=%p) %s\n", (
void *)
netif, netif_get_name(
netif)));
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));
876 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_start(): DHCP Server is already started\n"));
880 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_start(): starting new DHCP Server\n"));
883 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_start(): could not allocate dhcp\n"));
887 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_start(): allocated dhcp"));
893 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcp_start(): could not allocate pcb\n"));
894 mem_free((
void *)
dhcps);
898#if LWIP_SO_BINDTODEVICE
902 if ((start_ip == NULL) || (ip_num == 0)) {
914 (u32_t)(LWIP_MIN(ip_num - 1, LWIP_DHCPS_MAX_LEASE - 1)));
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));
922 mem_free((
void *)
dhcps);
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)) {
936 dhcps->
pcb->so_options |= SOF_BROADCAST;
937 err = udp_bind(
dhcps->
pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
940 mem_free((
void *)
dhcps);
944 err = udp_connect(
dhcps->
pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
947 mem_free((
void *)
dhcps);
951 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_start(): starting DHCPS Successfully\n"));
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",
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));
966 LWIP_ERROR(
"dhcps_stop: netif != NULL", (
netif != NULL),
return);
969 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_stop(): Stopping DHCP Server\n"));
971 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, (
"dhcps_stop(): Removing UDP PCB\n"));
977 netif_set_dhcps(
netif, NULL);
LWIP_STATIC struct dyn_lease_addr * find_client_lease(struct dhcps *dhcps, struct dhcp_msg *client_msg)
LWIP_STATIC struct pbuf * dhcps_create_base_msg(struct dhcp_msg *client_msg)
LWIP_STATIC ip4_addr_t validate_discover(struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr **client_lease)
LWIP_STATIC void add_client_entry(struct dhcps *dhcps, unsigned int idx, struct dhcp_msg *client_msg)
LWIP_STATIC void remove_stale_entries(struct dhcps *dhcps)
LWIP_STATIC void handle_inform(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg)
LWIP_STATIC void dhcp_common_option_long(struct dhcp_msg *msg_out, u32_t value, u16_t *options_out_len)
void dhcps_stop(struct netif *netif)
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)
LWIP_STATIC void handle_discover(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease)
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)
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)
LWIP_STATIC void dhcp_common_option_trailer(struct dhcp_msg *msg_out, u16_t options_out_len, struct pbuf *p_out)
LWIP_STATIC void handle_decline(struct netif *netif, struct dhcps *dhcps, struct dhcp_msg *client_msg, struct dyn_lease_addr *client_lease)
LWIP_STATIC int find_free_slot(struct dhcps *dhcps)
err_t dhcps_start(struct netif *netif, const char *start_ip, u16_t ip_num)
LWIP_STATIC err_t dhcps_parse_options(struct pbuf *p, struct dhcps *dhcps)
LWIP_STATIC void dhcp_common_option_byte(struct dhcp_msg *msg_out, u8_t value, u16_t *options_out_len)
LWIP_STATIC void dhcps_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *ip_addr, u16_t port)
LWIP_STATIC void dhcp_common_option(struct dhcp_msg *msg_out, u8_t option_type, u8_t option_len, u16_t *options_out_len)
int memcmp(const void *str1, const void *str2, size_t n)
struct dyn_lease_addr leasearr[LWIP_DHCPS_MAX_LEASE]
u8_t cli_hwaddr[DHCP_CHADDR_LEN]
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