Skip to content

Commit

Permalink
lwip/dhcp: add 60 option for vendor class identify
Browse files Browse the repository at this point in the history
  • Loading branch information
lhespress committed Aug 17, 2021
1 parent 55ea9d9 commit ae7edc2
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 3 deletions.
164 changes: 162 additions & 2 deletions src/core/ipv4/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@
#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
#endif

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
#define DHCP_OPTION_VSI_MAX 16
static u32_t dhcp_option_vsi[DHCP_OPTION_VSI_MAX] = {0};
#endif

/** Option handling: options are parsed in dhcp_parse_reply
* and saved in an array where other functions can load them from.
* This might be moved into the struct dhcp (not necessarily since
Expand All @@ -144,6 +149,10 @@ enum dhcp_option_idx {
#if ESP_DHCP
DHCP_OPTION_IDX_MTU,
#endif /* ESP_DHCP */
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
DHCP_OPTION_IDX_VSI,
DHCP_OPTION_IDX_VSI_LAST = DHCP_OPTION_IDX_VSI + DHCP_OPTION_VSI_MAX -1,
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
DHCP_OPTION_IDX_DNS_SERVER,
DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
Expand All @@ -167,6 +176,9 @@ static u8_t dhcp_discover_request_options[] = {
DHCP_OPTION_SUBNET_MASK,
DHCP_OPTION_ROUTER,
DHCP_OPTION_BROADCAST
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
, DHCP_OPTION_VSI
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */
#if LWIP_DHCP_PROVIDE_DNS_SERVERS
, DHCP_OPTION_DNS_SERVER
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
Expand Down Expand Up @@ -224,6 +236,12 @@ static u16_t dhcp_option_hostname(u16_t options_out_len, u8_t *options, struct n
#if ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID
static u16_t dhcp_option_client_id(struct netif *netif, struct dhcp_msg *msg_out, u16_t options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
/* set dhcp option60 */
static u16_t dhcp_option_vendor_class_identifier(struct netif *netif, struct dhcp_msg *msg_out, u16_t options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

/* always add the DHCP options trailer to end and pad */
static void dhcp_option_trailer(u16_t options_out_len, u8_t *options, struct pbuf *p_out);

Expand Down Expand Up @@ -350,6 +368,14 @@ dhcp_handle_offer(struct netif *netif, struct dhcp_msg *msg_in)

LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
(void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));

/* Vendor Specific Information */
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
for (u8_t n = 0; (n < DHCP_OPTION_VSI_MAX) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_VSI + n); n++) {
dhcp_option_vsi[n] = lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_VSI + n));
}
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

/* obtain the server address */
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
dhcp->request_timeout = 0; /* stop timer */
Expand Down Expand Up @@ -410,6 +436,11 @@ dhcp_select(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */


options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_SERVER_ID, 4);
options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));

Expand Down Expand Up @@ -658,9 +689,9 @@ dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in)
{
struct dhcp *dhcp = netif_dhcp_data(netif);

#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV || !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
u8_t n;
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV || !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */
#if LWIP_DHCP_GET_NTP_SRV
ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
#endif
Expand Down Expand Up @@ -694,6 +725,14 @@ dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in)
}
}
#endif /* ESP_DHCP */

/* Vendor Specific Information */
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
for (n = 0; (n < DHCP_OPTION_VSI_MAX) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_VSI + n); n++) {
dhcp_option_vsi[n] = lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_VSI + n));
}
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

/* renewal period given? */
if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
/* remember given rebind period */
Expand Down Expand Up @@ -1062,6 +1101,10 @@ dhcp_decline(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_BACKING_OFF, msg_out, DHCP_DECLINE, &options_out_len);
dhcp_option_trailer(options_out_len, msg_out->options, p_out);

Expand Down Expand Up @@ -1123,6 +1166,10 @@ dhcp_discover(struct netif *netif)
#if !ESP_DHCP_DISABLE_CLIENT_ID
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* !ESP_DHCP_DISABLE_CLIENT_ID */

#if !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */
#endif/* ESP_DHCP */

options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
Expand Down Expand Up @@ -1368,6 +1415,10 @@ dhcp_renew(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_RENEWING, msg_out, DHCP_REQUEST, &options_out_len);
dhcp_option_trailer(options_out_len, msg_out->options, p_out);

Expand Down Expand Up @@ -1427,6 +1478,10 @@ dhcp_rebind(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBINDING, msg_out, DHCP_DISCOVER, &options_out_len);
dhcp_option_trailer(options_out_len, msg_out->options, p_out);

Expand Down Expand Up @@ -1488,6 +1543,10 @@ dhcp_reboot(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBOOTING, msg_out, DHCP_REQUEST, &options_out_len);
dhcp_option_trailer(options_out_len, msg_out->options, p_out);

Expand Down Expand Up @@ -1559,6 +1618,10 @@ dhcp_release_and_stop(struct netif *netif)
options_out_len = dhcp_option_client_id(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
options_out_len = dhcp_option_vendor_class_identifier(netif, msg_out, options_out_len);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, dhcp->state, msg_out, DHCP_RELEASE, &options_out_len);
dhcp_option_trailer(options_out_len, msg_out->options, p_out);

Expand Down Expand Up @@ -1719,6 +1782,95 @@ dhcp_option_client_id(struct netif *netif, struct dhcp_msg *msg_out, u16_t optio
}
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_CLIENT_ID */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
static u8_t vendor_class_len = 0;
static char *vendor_class_buf = NULL;

err_t
dhcp_set_vendor_class_identifier(u8_t len, char *str)
{
if (len == 0 || str == NULL) {
return ERR_ARG;
}

if (vendor_class_buf && vendor_class_len != len) {
mem_free(vendor_class_buf);
vendor_class_buf = NULL;
}

if (!vendor_class_buf) {
vendor_class_buf = (char *)mem_malloc(len + 1);
if (vendor_class_buf == NULL) {
return ERR_MEM;
}

vendor_class_len = len;
}

memcpy(vendor_class_buf, str, len);
return ERR_OK;
}

err_t
dhcp_get_vendor_specific_information(u8_t len, char *str)
{
u8_t copy_len = 0;

if (len == 0 || str == NULL) {
return ERR_ARG;
}

copy_len = LWIP_MIN(len, sizeof(dhcp_option_vsi));

memcpy(str, dhcp_option_vsi, copy_len);

return ERR_OK;
}

static u16_t
dhcp_option_vendor_class_identifier(struct netif *netif, struct dhcp_msg *msg_out, u16_t options_out_len)
{
size_t i;
int available;
const char *p = NULL;
u8_t len = 0;

if (netif == NULL || msg_out == NULL) {
return ERR_ARG;
}

/* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME and 1 byte for trailer) */

available = DHCP_OPTIONS_LEN - options_out_len - 3;
LWIP_ASSERT("DHCP: problem unfolding DHCP options - too short on memory!", 0 <= available);

if (vendor_class_buf && vendor_class_len) {
p = vendor_class_buf;
LWIP_ASSERT("DHCP: vendor_class_len is too long!", vendor_class_len <= available);
len = vendor_class_len;
} else {
#if LWIP_NETIF_HOSTNAME
if (netif->hostname != NULL) {
size_t namelen = strlen(netif->hostname);
if ((namelen > 0) && (namelen < 0xFF)) {
p = netif->hostname;
LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
len = (u8_t)namelen;
}
}
#endif
}

len = LWIP_MIN(len, available);
if (p) {
options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_VCI, len);
for (i = 0; i < len; i ++) {
options_out_len = dhcp_option_byte(options_out_len, msg_out->options, p[i]);
}
}
return options_out_len;
}
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

/**
* Extract the DHCP message and the DHCP options.
Expand Down Expand Up @@ -1867,6 +2019,9 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
decode_idx = DHCP_OPTION_IDX_T2;
break;
case (DHCP_OPTION_VSI):
decode_idx = DHCP_OPTION_IDX_VSI;
break;
default:
decode_len = 0;
LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op));
Expand Down Expand Up @@ -1896,7 +2051,10 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
if (decode_len > 4) {
/* decode more than one u32_t */
u16_t next_val_offset;
#if ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
/* correct DHCP VCI data might not be aligned, so remove it. */
LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
#endif /* ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */
dhcp_got_option(dhcp, decode_idx);
dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
decode_len = (u8_t)(decode_len - 4);
Expand All @@ -1913,6 +2071,8 @@ dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
#if ESP_DHCP
} else if (decode_len == 2) {
value = (u32_t)lwip_htons((u16_t)value);
} else if (decode_len == 3) {
value = lwip_ntohl(value);
#endif /* ESP_DHCP */
} else {
LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
Expand Down
5 changes: 5 additions & 0 deletions src/include/lwip/dhcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ void dhcp_fine_tmr(void);
extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs);
#endif /* LWIP_DHCP_GET_NTP_SRV */

#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
err_t dhcp_set_vendor_class_identifier(u8_t len, char *str);
err_t dhcp_get_vendor_specific_information(u8_t len, char *str);
#endif /* ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER */

#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))

#ifdef __cplusplus
Expand Down
3 changes: 2 additions & 1 deletion src/include/lwip/prot/dhcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ typedef enum {

#define DHCP_OPTION_T1 58 /* T1 renewal time */
#define DHCP_OPTION_T2 59 /* T2 rebinding time */
#define DHCP_OPTION_US 60
#define DHCP_OPTION_VCI 60
#define DHCP_OPTION_VSI 43
#define DHCP_OPTION_CLIENT_ID 61
#define DHCP_OPTION_TFTP_SERVERNAME 66
#define DHCP_OPTION_BOOTFILE 67
Expand Down
1 change: 1 addition & 0 deletions test/unit/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
#define ESP_DHCP_DEBUG 1
#define ESP_THREAD_PROTECTION 0
#define ESP_DHCP_DISABLE_CLIENT_ID 0
#define ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER 0

#ifdef IP_NAPT
#define IP_NAPT_MAX 16
Expand Down

0 comments on commit ae7edc2

Please sign in to comment.