From 2fef87449494b93742ee187519bba013f7139401 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 25 Apr 2017 16:13:39 +0200 Subject: [PATCH] task #14270: DHCP should support user-defined additional options: added two hooks for adding and parsing user defined DHCP options --- src/core/ipv4/dhcp.c | 28 ++++++++++++++++++++---- src/include/lwip/opt.h | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/core/ipv4/dhcp.c b/src/core/ipv4/dhcp.c index 85f5a4de..29e54ae8 100644 --- a/src/core/ipv4/dhcp.c +++ b/src/core/ipv4/dhcp.c @@ -78,6 +78,16 @@ #include +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif +#ifndef LWIP_HOOK_DHCP_APPEND_OPTIONS +#define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type) +#endif +#ifndef LWIP_HOOK_DHCP_PARSE_OPTION +#define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) +#endif + /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) */ @@ -381,6 +391,7 @@ dhcp_select(struct netif *netif) dhcp_option_hostname(dhcp, netif); #endif /* LWIP_NETIF_HOSTNAME */ + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REQUESTING, dhcp->msg_out, DHCP_REQUEST); dhcp_option_trailer(dhcp); /* shrink the pbuf to the actual content length */ pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -815,6 +826,7 @@ dhcp_inform(struct netif *netif) dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, &dhcp, DHCP_STATE_INFORMING, dhcp.msg_out, DHCP_INFORM); dhcp_option_trailer(&dhcp); pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); @@ -927,6 +939,7 @@ dhcp_decline(struct netif *netif) dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_BACKING_OFF, dhcp->msg_out, DHCP_DECLINE); dhcp_option_trailer(dhcp); /* resize pbuf to reflect true size of options */ pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -977,6 +990,7 @@ dhcp_discover(struct netif *netif) for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_SELECTING, dhcp->msg_out, DHCP_DISCOVER); dhcp_option_trailer(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); @@ -1146,6 +1160,7 @@ dhcp_renew(struct netif *netif) dhcp_option_hostname(dhcp, netif); #endif /* LWIP_NETIF_HOSTNAME */ + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_RENEWING, dhcp->msg_out, DHCP_REQUEST); /* append DHCP message trailer */ dhcp_option_trailer(dhcp); @@ -1198,6 +1213,7 @@ dhcp_rebind(struct netif *netif) dhcp_option_hostname(dhcp, netif); #endif /* LWIP_NETIF_HOSTNAME */ + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBINDING, dhcp->msg_out, DHCP_DISCOVER); dhcp_option_trailer(dhcp); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -1246,7 +1262,7 @@ dhcp_reboot(struct netif *netif) for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); } - + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBOOTING, dhcp->msg_out, DHCP_REQUEST); dhcp_option_trailer(dhcp); pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); @@ -1309,11 +1325,12 @@ dhcp_release_and_stop(struct netif *netif) if (result == ERR_OK) { dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); - + + LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, dhcp->state, dhcp->msg_out, DHCP_RELEASE); dhcp_option_trailer(dhcp); - + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - + udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); dhcp_delete_msg(dhcp); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); @@ -1579,6 +1596,9 @@ again: default: decode_len = 0; LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op)); + LWIP_HOOK_DHCP_PARSE_OPTION(ip_current_netif(), dhcp, dhcp->state, dhcp->msg_in, + dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) ? (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) : 0, + op, len, q, val_offset); break; } offset += len + 2; diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index ed956bd4..f14cfdbb 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -2717,6 +2717,55 @@ #ifdef __DOXYGEN__ #define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) #endif + +/** + * LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type): + * Called from various dhcp functions when sending a DHCP message. + * This hook is called just before the DHCP message trailer is added, so the + * options are at the end of a DHCP message. + * Arguments: + * - netif: struct netif that the packet will be sent through + * - dhcp: struct dhcp on that netif + * - state: current dhcp state (dhcp_state_enum_t as an u8_t) + * - msg: struct dhcp_msg that will be sent + * - msg_type: dhcp message type to be sent (u8_t) + * Returns void + * + * Options need to appended like this: + * LWIP_ASSERT("dhcp option overflow", dhcp->options_out_len + option_len + 2 <= DHCP_OPTIONS_LEN); + * dhcp->msg_out->options[dhcp->options_out_len++] = ; + * dhcp->msg_out->options[dhcp->options_out_len++] = ; + * dhcp->msg_out->options[dhcp->options_out_len++] = ; + * [...] + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type) +#endif + +/** + * LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset): + * Called from dhcp_parse_reply when receiving a DHCP message. + * This hook is called for every option in the received message that is not handled internally. + * Arguments: + * - netif: struct netif that the packet will be sent through + * - dhcp: struct dhcp on that netif + * - state: current dhcp state (dhcp_state_enum_t as an u8_t) + * - msg: struct dhcp_msg that was received + * - msg_type: dhcp message type received (u8_t, ATTENTION: only valid after + * the message type option has been parsed!) + * - option: option value (u8_t) + * - len: option data length (u8_t) + * - pbuf: pbuf where option data is contained + * - offset: offset in pbuf where option *data* begins + * Returns void + * + * A nice way to get the option contents is @ref pbuf_get_contiguous: + * u8_t buf[32]; + * u8_t *ptr = (u8_t*)pbuf_get_contiguous(p, buf, sizeof(buf), LWIP_MIN(option_len, sizeof(buf)), offset); + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) +#endif /** * @} */