lwip/dhcp: add 60 option for vendor class identify

Closes https://github.com/espressif/esp-idf/issues/6786
This commit is contained in:
Liu Han
2021-06-04 16:36:38 +08:00
parent 55ea9d9c7d
commit ae7edc2a93
4 changed files with 170 additions and 3 deletions

View File

@ -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
@ -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,
@ -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 */
@ -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);
@ -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 */
@ -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))));
@ -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
@ -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 */
@ -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);
@ -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));
@ -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);
@ -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);
@ -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);
@ -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);
@ -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.
@ -1867,6 +2019,9 @@ again:
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));
@ -1896,7 +2051,10 @@ decode_next:
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);
@ -1913,6 +2071,8 @@ decode_next:
#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;);

View File

@ -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

View File

@ -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

View File

@ -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