Merge branch 'feature/seperate_ipv6_function_from_ipv4' into 'master'

Add LWIP_IPV6 macro to strip IPv6 function

See merge request espressif/esp-idf!11977
This commit is contained in:
David Čermák 2021-02-24 11:20:53 +00:00
commit 5f0aa46cbf
31 changed files with 243 additions and 60 deletions

View File

@ -167,13 +167,17 @@ static esp_err_t esp_tls_hostname_to_fd(const char *host, size_t hostlen, int po
p->sin_port = htons(port);
ESP_LOGD(TAG, "[sock=%d] Resolved IPv4 address: %s", *fd, ipaddr_ntoa((const ip_addr_t*)&p->sin_addr.s_addr));
memcpy(address, p, sizeof(struct sockaddr ));
} else if (address_info->ai_family == AF_INET6) {
}
#if CONFIG_LWIP_IPV6
else if (address_info->ai_family == AF_INET6) {
struct sockaddr_in6 *p = (struct sockaddr_in6 *)address_info->ai_addr;
p->sin6_port = htons(port);
p->sin6_family = AF_INET6;
ESP_LOGD(TAG, "[sock=%d] Resolved IPv6 address: %s", *fd, ip6addr_ntoa((const ip6_addr_t*)&p->sin6_addr));
memcpy(address, p, sizeof(struct sockaddr_in6 ));
} else {
}
#endif
else {
ESP_LOGE(TAG, "Unsupported protocol family %d", address_info->ai_family);
close(*fd);
freeaddrinfo(address_info);

View File

@ -261,19 +261,31 @@ static void httpd_thread(void *arg)
static esp_err_t httpd_server_init(struct httpd_data *hd)
{
#if CONFIG_LWIP_IPV6
int fd = socket(PF_INET6, SOCK_STREAM, 0);
#else
int fd = socket(PF_INET, SOCK_STREAM, 0);
#endif
if (fd < 0) {
ESP_LOGE(TAG, LOG_FMT("error in socket (%d)"), errno);
return ESP_FAIL;
}
#if CONFIG_LWIP_IPV6
struct in6_addr inaddr_any = IN6ADDR_ANY_INIT;
struct sockaddr_in6 serv_addr = {
.sin6_family = PF_INET6,
.sin6_addr = inaddr_any,
.sin6_port = htons(hd->config.server_port)
};
#else
struct sockaddr_in serv_addr = {
.sin_family = PF_INET,
.sin_addr = {
.s_addr = htonl(INADDR_ANY)
},
.sin_port = htons(hd->config.server_port)
};
#endif
/* Enable SO_REUSEADDR to allow binding to the same
* address and port when restarting the server */
int enable = 1;

View File

@ -615,7 +615,7 @@ esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t ty
/** @addtogroup ESP_NETIF_NET_IP
* @{
*/
#if CONFIG_LWIP_IPV6
/**
* @brief Create interface link-local IPv6 address
*
@ -674,6 +674,7 @@ esp_err_t esp_netif_get_ip6_global(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip
* number of returned IPv6 addresses
*/
int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]);
#endif
/**
* @brief Sets IPv4 address to the specified octets

View File

@ -40,6 +40,7 @@ typedef struct esp_netif_slip_config {
*/
esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *config);
#if CONFIG_LWIP_IPV6
/** @brief Sets IPV6 address for the supplied esp-netif.
*
* @param[in] netif handle to slip esp-netif instance
@ -48,6 +49,7 @@ esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_con
* @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not SLIP
*/
esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6);
#endif
/**
* @brief Data path API to write raw packet ous the SLIP interface

View File

@ -1241,12 +1241,14 @@ static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg)
esp_netif_reset_ip_info(esp_netif);
}
#if CONFIG_LWIP_IPV6
for(int8_t i = 0 ;i < LWIP_IPV6_NUM_ADDRESSES ;i++) {
netif_ip6_addr_set(lwip_netif, i, IP6_ADDR_ANY6);
netif_ip6_addr_set_valid_life(lwip_netif, i, 0);
netif_ip6_addr_set_pref_life(lwip_netif, i, 0);
netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
}
#endif
netif_set_addr(lwip_netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
netif_set_down(lwip_netif);
@ -1424,8 +1426,9 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg)
ESP_LOGD(TAG, "set dns if=%p type=%d dns=%x", esp_netif, type, dns->ip.u_addr.ip4.addr);
ip_addr_t *lwip_ip = (ip_addr_t*)&dns->ip;
#if CONFIG_LWIP_IPV6 && LWIP_IPV4
lwip_ip->type = IPADDR_TYPE_V4;
#endif
if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) {
// if DHCP server configured to set DNS in dhcps API
if (type != ESP_NETIF_DNS_MAIN) {
@ -1488,7 +1491,11 @@ esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t ty
if (dns_ip == IP_ADDR_ANY) {
return ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED;
}
#if CONFIG_LWIP_IPV6
memcpy(&dns->ip.u_addr.ip4, &dns_ip->u_addr.ip4, sizeof(ip4_addr_t));
#else
memcpy(&dns->ip.u_addr.ip4, &dns_ip->addr, sizeof(ip4_addr_t));
#endif
return ESP_OK;
}
@ -1499,6 +1506,7 @@ esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t ty
return esp_netif_lwip_ipc_call(esp_netif_get_dns_info_api, esp_netif, (void *)&dns_param);
}
#if CONFIG_LWIP_IPV6
esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr)
{
ip6_addr_t* lwip_ip6_info = (ip6_addr_t*)ip6_addr;
@ -1625,6 +1633,7 @@ int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[])
}
return addr_count;
}
#endif
esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif)
{

View File

@ -101,10 +101,12 @@ esp_err_t esp_netif_start_slip(esp_netif_t *esp_netif)
// Set the netif up
netif_set_up(esp_netif->lwip_netif);
netif_set_link_up(esp_netif->lwip_netif);
#if CONFIG_LWIP_IPV6
int8_t addr_index = 0;
netif_ip6_addr_set(esp_netif->lwip_netif, addr_index, (ip6_addr_t *)&slip_ctx->addr);
netif_ip6_addr_set_state(esp_netif->lwip_netif, addr_index, IP6_ADDR_VALID);
#endif
return ESP_OK;
}
@ -125,12 +127,13 @@ esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_con
return ESP_ERR_INVALID_STATE;
}
memcpy(&slip_ctx->addr, &slip_config->ip6_addr, sizeof(ip6_addr_t));
memcpy(&slip_ctx->addr, &slip_config->ip6_addr, sizeof(esp_ip6_addr_t));
return ESP_OK;
}
#if CONFIG_LWIP_IPV6
esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6)
{
lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data;
@ -150,7 +153,7 @@ esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6
return ESP_OK;
}
#endif
/**
* @brief Write incoming serial data to the SLIP interface
@ -198,7 +201,11 @@ void esp_netif_lwip_slip_raw_output(esp_netif_t *slip_netif, void *buffer, size_
};
// Call slip if output function to feed data out slip interface
#if CONFIG_LWIP_IPV6
lwip_netif->output_ip6(lwip_netif, &p, NULL);
#else
lwip_netif->output(lwip_netif, &p, NULL);
#endif
}
/**

View File

@ -432,11 +432,14 @@ static BOOL xMBTCPPortMasterCheckHost(const CHAR* pcHostStr, ip_addr_t* pxHostAd
struct in_addr addr4 = ((struct sockaddr_in *) (pxAddrList->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&xTargetAddr), &addr4);
pcStr = ip4addr_ntoa_r(ip_2_ip4(&xTargetAddr), cStr, sizeof(cStr));
} else {
}
#if CONFIG_LWIP_IPV6
else {
struct in6_addr addr6 = ((struct sockaddr_in6 *) (pxAddrList->ai_addr))->sin6_addr;
inet6_addr_to_ip6addr(ip_2_ip6(&xTargetAddr), &addr6);
pcStr = ip6addr_ntoa_r(ip_2_ip6(&xTargetAddr), cStr, sizeof(cStr));
}
#endif
if (pxHostAddr) {
*pxHostAddr = xTargetAddr;
}
@ -496,7 +499,9 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
struct in_addr addr4 = ((struct sockaddr_in *) (pxCurAddr->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&xTargetAddr), &addr4);
pcStr = ip4addr_ntoa_r(ip_2_ip4(&xTargetAddr), cStr, sizeof(cStr));
} else if (pxCurAddr->ai_family == AF_INET6) {
}
#if CONFIG_LWIP_IPV6
else if (pxCurAddr->ai_family == AF_INET6) {
struct in6_addr addr6 = ((struct sockaddr_in6 *) (pxCurAddr->ai_addr))->sin6_addr;
inet6_addr_to_ip6addr(ip_2_ip6(&xTargetAddr), &addr6);
pcStr = ip6addr_ntoa_r(ip_2_ip6(&xTargetAddr), cStr, sizeof(cStr));
@ -504,7 +509,7 @@ static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo)
((struct sockaddr_in6 *) (pxCurAddr->ai_addr))->sin6_scope_id =
esp_netif_get_netif_impl_index(xMbPortConfig.pvNetIface);
}
#endif
if (pxInfo->xSockId <= 0) {
pxInfo->xSockId = socket(pxCurAddr->ai_family, pxCurAddr->ai_socktype, pxCurAddr->ai_protocol);
if (pxInfo->xSockId < 0) {

View File

@ -184,12 +184,11 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr)
MB_PORT_CHECK((xListenSockId > 0), -1, "Incorrect listen socket ID.");
// Address structure large enough for both IPv4 or IPv6 address
struct sockaddr_in6 xSrcAddr;
struct sockaddr_storage xSrcAddr;
CHAR cAddrStr[128];
int xSockId = -1;
CHAR* pcStr = NULL;
socklen_t xSize = sizeof(struct sockaddr_in6);
socklen_t xSize = sizeof(struct sockaddr_storage);
// Accept new socket connection if not active
xSockId = accept(xListenSockId, (struct sockaddr *)&xSrcAddr, &xSize);
@ -198,11 +197,14 @@ static int xMBTCPPortAcceptConnection(int xListenSockId, char** pcIPAddr)
close(xSockId);
} else {
// Get the sender's ip address as string
if (xSrcAddr.sin6_family == PF_INET) {
if (xSrcAddr.ss_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&xSrcAddr)->sin_addr.s_addr, cAddrStr, sizeof(cAddrStr) - 1);
} else if (xSrcAddr.sin6_family == PF_INET6) {
inet6_ntoa_r(xSrcAddr.sin6_addr, cAddrStr, sizeof(cAddrStr) - 1);
}
#if CONFIG_LWIP_IPV6
else if (xSrcAddr.ss_family == PF_INET6) {
inet6_ntoa_r(((struct sockaddr_in6 *)&xSrcAddr)->sin6_addr, cAddrStr, sizeof(cAddrStr) - 1);
}
#endif
ESP_LOGI(MB_TCP_SLAVE_PORT_TAG, "Socket (#%d), accept client connection from address: %s", xSockId, cAddrStr);
pcStr = calloc(1, strlen(cAddrStr) + 1);
if (pcStr && pcIPAddr) {

View File

@ -133,6 +133,7 @@ menu "LWIP"
config LWIP_IP6_FRAG
bool "Enable fragment outgoing IP6 packets"
default y
depends on LWIP_IPV6
help
Enabling this option allows fragmenting outgoing IP6 packets if their size
exceeds MTU.
@ -146,6 +147,7 @@ menu "LWIP"
config LWIP_IP6_REASSEMBLY
bool "Enable reassembly incoming fragmented IP6 packets"
default n
depends on LWIP_IPV6
help
Enabling this option allows reassemblying incoming fragmented IP6 packets.
@ -299,8 +301,18 @@ menu "LWIP"
If rate limiting self-assignment requests, wait this long between
each request.
config LWIP_IPV6
bool "Enable IPv6"
default y
help
Enable IPv6 function. If not use IPv6 function, set this option to n.
If disable LWIP_IPV6, not adding coap and asio component into the build.
Please assign them to EXCLUDE_COMPONENTS in the make or cmake file in your
project directory, so that the component will not be compiled.
config LWIP_IPV6_AUTOCONFIG
bool "Enable IPV6 stateless address autoconfiguration (SLAAC)"
depends on LWIP_IPV6
default n
help
Enabling this option allows the devices to IPV6 stateless address autoconfiguration (SLAAC).
@ -627,7 +639,7 @@ menu "LWIP"
config LWIP_PPP_ENABLE_IPV6
bool "Enable IPV6 support for PPP connections (IPV6CP)"
depends on LWIP_PPP_SUPPORT
depends on LWIP_PPP_SUPPORT && LWIP_IPV6
default y
help
Enable IPV6 support in PPP for the local link between the DTE (processor) and DCE (modem).
@ -638,6 +650,7 @@ menu "LWIP"
config LWIP_IPV6_MEMP_NUM_ND6_QUEUE
int "Max number of IPv6 packets to queue during MAC resolution"
depends on LWIP_IPV6
range 3 20
default 3
help
@ -645,6 +658,7 @@ menu "LWIP"
config LWIP_IPV6_ND6_NUM_NEIGHBORS
int "Max number of entries in IPv6 neighbor cache"
depends on LWIP_IPV6
range 3 10
default 5
help
@ -791,6 +805,7 @@ menu "LWIP"
choice LWIP_HOOK_IP6_ROUTE
prompt "IPv6 route Hook"
depends on LWIP_IPV6
default LWIP_HOOK_IP6_ROUTE_NONE
help
Enables custom IPv6 route hook.

View File

@ -114,13 +114,16 @@ static int esp_ping_receive(esp_ping_t *ep)
inet_addr_to_ip4addr(ip_2_ip4(&ep->recv_addr), &from4->sin_addr);
IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V4);
data_head = (uint16_t)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr));
} else {
}
#if CONFIG_LWIP_IPV6
else {
// IPv6
struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
inet6_addr_to_ip6addr(ip_2_ip6(&ep->recv_addr), &from6->sin6_addr);
IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V6);
data_head = (uint16_t)(sizeof(struct ip6_hdr) + sizeof(struct icmp6_echo_hdr));
}
#endif
if (len >= data_head) {
if (IP_IS_V4_VAL(ep->recv_addr)) { // Currently we process IPv4
struct ip_hdr *iphdr = (struct ip_hdr *)buf;
@ -131,7 +134,9 @@ static int esp_ping_receive(esp_ping_t *ep)
ep->recv_len = lwip_ntohs(IPH_LEN(iphdr)) - data_head; // The data portion of ICMP
return len;
}
} else if (IP_IS_V6_VAL(ep->recv_addr)) { // Currently we process IPv6
}
#if CONFIG_LWIP_IPV6
else if (IP_IS_V6_VAL(ep->recv_addr)) { // Currently we process IPv6
struct ip6_hdr *iphdr = (struct ip6_hdr *)buf;
struct icmp6_echo_hdr *iecho6 = (struct icmp6_echo_hdr *)(buf + sizeof(struct ip6_hdr)); // IPv6 head length is 40
if ((iecho6->id == ep->packet_hdr->id) && (iecho6->seqno == ep->packet_hdr->seqno)) {
@ -140,6 +145,7 @@ static int esp_ping_receive(esp_ping_t *ep)
return len;
}
}
#endif
}
fromlen = sizeof(from);
}
@ -249,11 +255,18 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c
}
/* create socket */
if (IP_IS_V4(&config->target_addr) || ip6_addr_isipv4mappedipv6(ip_2_ip6(&config->target_addr))) {
if (IP_IS_V4(&config->target_addr)
#if CONFIG_LWIP_IPV6
|| ip6_addr_isipv4mappedipv6(ip_2_ip6(&config->target_addr))
#endif
) {
ep->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
} else {
}
#if CONFIG_LWIP_IPV6
else {
ep->sock = socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
}
#endif
PING_CHECK(ep->sock > 0, "create socket failed: %d", err, ESP_FAIL, ep->sock);
/* set if index */
if(config->interface) {
@ -281,12 +294,14 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c
inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(&config->target_addr));
ep->packet_hdr->type = ICMP_ECHO;
}
#if CONFIG_LWIP_IPV6
if (IP_IS_V6(&config->target_addr)) {
struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ep->target_addr;
to6->sin6_family = AF_INET6;
inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(&config->target_addr));
ep->packet_hdr->type = ICMP6_TYPE_EREQ;
}
#endif
/* return ping handle to user */
*hdl_out = (esp_ping_handle_t)ep;
return ESP_OK;

View File

@ -85,7 +85,7 @@ typedef struct {
.timeout_ms = 1000, \
.data_size = 64, \
.tos = 0, \
.target_addr = ip_addr_any_type, \
.target_addr = *(IP_ANY_TYPE), \
.task_stack_size = 2048, \
.task_prio = 2, \
.interface = 0,\

View File

@ -23,10 +23,14 @@
#include "lwip/memp.h"
#include "esp_log.h"
#if CONFIG_LWIP_IPV6
#define DBG_LWIP_IP_SHOW(info, ip) ESP_LWIP_LOGI("%s type=%d ip=%x", (info), (ip).type, (ip).u_addr.ip4.addr)
#else
#define DBG_LWIP_IP_SHOW(info, ip) ESP_LWIP_LOGI("%s type=%d ip=%x", (info), IPADDR_TYPE_V4, (ip).addr)
#endif
#define DBG_LWIP_IP_PCB_SHOW(pcb) \
DBG_LWIP_IP_SHOW("local ip", (pcb)->local_ip);\
DBG_LWIP_IP_SHOW("remote ip", (pcb)->local_ip);\
DBG_LWIP_IP_SHOW("remote ip", (pcb)->remote_ip);\
ESP_LWIP_LOGI("so_options=%x, tos=%d ttl=%d", (pcb)->so_options, (pcb)->tos, (pcb)->ttl)
#define DBG_LWIP_SEG_SHOW(seg) while(seg) { ESP_LWIP_LOGI("\tseg=%p next=%p pbuf=%p flags=%x", (seg), (seg)->next, (seg)->p, (seg)->flags); (seg)=(seg)->next;}

View File

@ -749,7 +749,7 @@
/**
* LWIP_IPV6==1: Enable IPv6
*/
#define LWIP_IPV6 1
#define LWIP_IPV6 CONFIG_LWIP_IPV6
/**
* MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution.
@ -962,7 +962,7 @@
#define ESP_AUTO_IP 1
#define ESP_PBUF 1
#define ESP_PPP 1
#define ESP_IPV6 1
#define ESP_IPV6 LWIP_IPV6
#define ESP_SOCKET 1
#define ESP_LWIP_SELECT 1
#define ESP_LWIP_LOCK 1

View File

@ -339,6 +339,7 @@ esp_err_t mdns_query_txt(const char * instance_name, const char * service_type,
*/
esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t * addr);
#if CONFIG_LWIP_IPV6
/**
* @brief Query mDNS for A record
*
@ -353,6 +354,7 @@ esp_err_t mdns_query_a(const char * host_name, uint32_t timeout, esp_ip4_addr_t
* - ESP_ERR_INVALID_ARG parameter error
*/
esp_err_t mdns_query_aaaa(const char * host_name, uint32_t timeout, esp_ip6_addr_t * addr);
#endif
/**
* @brief System event handler

View File

@ -761,6 +761,7 @@ static uint16_t _mdns_append_a_record(uint8_t * packet, uint16_t * index, uint32
return record_length;
}
#if CONFIG_LWIP_IPV6
/**
* @brief appends AAAA record to a packet, incrementing the index
*
@ -809,6 +810,7 @@ static uint16_t _mdns_append_aaaa_record(uint8_t * packet, uint16_t * index, uin
record_length += part_length;
return record_length;
}
#endif
/**
* @brief Append question to packet
@ -874,6 +876,7 @@ static bool _mdns_if_is_dup(mdns_if_t tcpip_if)
return false;
}
#if CONFIG_LWIP_IPV6
/**
* @brief Check if IPv6 address is NULL
*/
@ -888,6 +891,7 @@ static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6)
}
return true;
}
#endif
/**
* @brief Append answer to packet
@ -936,7 +940,9 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_
return 2;
}
return 1;
} else if (answer->type == MDNS_TYPE_AAAA) {
}
#if CONFIG_LWIP_IPV6
else if (answer->type == MDNS_TYPE_AAAA) {
struct esp_ip6_addr if_ip6;
if (!_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) {
return 0;
@ -962,6 +968,7 @@ static uint8_t _mdns_append_answer(uint8_t * packet, uint16_t * index, mdns_out_
}
return 1;
}
#endif
return 0;
}
@ -1235,11 +1242,14 @@ static mdns_tx_packet_t * _mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip
packet->ip_protocol = ip_protocol;
packet->port = MDNS_SERVICE_PORT;
if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
IP_ADDR4(&packet->dst, 224, 0, 0, 251);
} else {
IP4_ADDR(&packet->dst.u_addr.ip4, 224, 0, 0, 251);
}
#if CONFIG_LWIP_IPV6
else {
esp_ip_addr_t addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t));
}
#endif
return packet;
}
@ -2253,6 +2263,7 @@ static int _mdns_check_a_collision(esp_ip4_addr_t * ip, mdns_if_t tcpip_if)
return 0;//same
}
#if CONFIG_LWIP_IPV6
/**
* @brief Detect IPv6 address collision
*/
@ -2286,6 +2297,7 @@ static int _mdns_check_aaaa_collision(esp_ip6_addr_t * ip, mdns_if_t tcpip_if)
}
return 0;//same
}
#endif
/**
* @brief Check if parsed name is discovery
@ -2678,7 +2690,12 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
parsed_packet->authoritative = header.flags.value == MDNS_FLAGS_AUTHORITATIVE;
parsed_packet->distributed = header.flags.value == MDNS_FLAGS_DISTRIBUTED;
parsed_packet->id = header.id;
#if CONFIG_LWIP_IPV6
ip_addr_copy(parsed_packet->src, packet->src);
#else
ip4_addr_copy(parsed_packet->src.u_addr.ip4, packet->src.u_addr.ip4);
#endif
parsed_packet->src_port = packet->src_port;
if (header.questions) {
@ -2977,7 +2994,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
}
}
} else if (type == MDNS_TYPE_AAAA) {//ipv6
}
#if CONFIG_LWIP_IPV6
else if (type == MDNS_TYPE_AAAA) {//ipv6
esp_ip_addr_t ip6;
ip6.type = IPADDR_TYPE_V6;
memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE);
@ -3023,7 +3042,9 @@ void mdns_parse_packet(mdns_rx_packet_t * packet)
}
}
} else if (type == MDNS_TYPE_A) {
}
#endif
else if (type == MDNS_TYPE_A) {
esp_ip_addr_t ip;
ip.type = IPADDR_TYPE_V4;
memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4);
@ -4276,13 +4297,17 @@ esp_err_t mdns_init(void)
}
#endif
uint8_t i;
#if CONFIG_LWIP_IPV6
esp_ip6_addr_t tmp_addr6;
#endif
esp_netif_ip_info_t if_ip_info;
for (i=0; i<MDNS_IF_MAX; i++) {
#if CONFIG_LWIP_IPV6
if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !_ipv6_address_is_zero(tmp_addr6)) {
_mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6);
}
#endif
if (!esp_netif_get_ip_info(_mdns_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) {
_mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V4);
}
@ -4818,6 +4843,7 @@ esp_err_t mdns_query_a(const char * name, uint32_t timeout, esp_ip4_addr_t * add
return ESP_ERR_NOT_FOUND;
}
#if CONFIG_LWIP_IPV6
esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, esp_ip6_addr_t * addr)
{
mdns_result_t * result = NULL;
@ -4850,6 +4876,7 @@ esp_err_t mdns_query_aaaa(const char * name, uint32_t timeout, esp_ip6_addr_t *
mdns_query_results_free(result);
return ESP_ERR_NOT_FOUND;
}
#endif
#ifdef MDNS_ENABLE_DEBUG

View File

@ -116,6 +116,7 @@ static void register_mdns_query_a(void)
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
}
#if CONFIG_LWIP_IPV6
static int cmd_mdns_query_aaaa(int argc, char** argv)
{
int nerrors = arg_parse(argc, argv, (void**) &mdns_query_a_args);
@ -172,6 +173,7 @@ static void register_mdns_query_aaaa(void)
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_init) );
}
#endif
static struct {
struct arg_str *instance;
@ -1049,7 +1051,9 @@ void mdns_console_register(void)
register_mdns_service_remove_all();
register_mdns_query_a();
#if CONFIG_LWIP_IPV6
register_mdns_query_aaaa();
#endif
register_mdns_query_txt();
register_mdns_query_srv();
register_mdns_query_ptr();

View File

@ -40,7 +40,7 @@ static esp_err_t _udp_pcb_main_init(void)
}
_pcb_main->mcast_ttl = 1;
_pcb_main->remote_port = MDNS_SERVICE_PORT;
ip_addr_copy(_pcb_main->remote_ip, ip_addr_any_type);
ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE));
udp_recv(_pcb_main, &_udp_recv, _mdns_server);
return ESP_OK;
}
@ -75,19 +75,21 @@ static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protoco
assert(netif);
if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
ip_addr_t multicast_addr;
IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
ip4_addr_t multicast_addr;
IP4_ADDR(&multicast_addr, 224, 0, 0, 251);
if(join){
if (igmp_joingroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
if (igmp_joingroup_netif(netif, &multicast_addr)) {
return ESP_ERR_INVALID_STATE;
}
} else {
if (igmp_leavegroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
if (igmp_leavegroup_netif(netif, &multicast_addr)) {
return ESP_ERR_INVALID_STATE;
}
}
} else {
}
#if CONFIG_LWIP_IPV6
else {
ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
if(join){
@ -100,6 +102,7 @@ static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protoco
}
}
}
#endif
return ESP_OK;
}
@ -127,20 +130,29 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip
packet->tcpip_if = MDNS_IF_MAX;
packet->pb = this_pb;
packet->src_port = rport;
#if CONFIG_LWIP_IPV6
packet->src.type = raddr->type;
memcpy(&packet->src.u_addr, &raddr->u_addr, sizeof(raddr->u_addr));
#else
packet->src.type = IPADDR_TYPE_V4;
memcpy(&packet->src.u_addr.ip4, &raddr->addr, sizeof(ip_addr_t));
#endif
packet->dest.type = packet->src.type;
if (packet->src.type == IPADDR_TYPE_V4) {
packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
} else {
packet->multicast = ip4_addr_ismulticast(&(packet->dest.u_addr.ip4));
}
#if CONFIG_LWIP_IPV6
else {
packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
packet->multicast = ip6_addr_ismulticast(&(packet->dest.u_addr.ip6));
}
packet->multicast = ip_addr_ismulticast(&(packet->dest));
#endif
//lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
struct netif * netif = NULL;
@ -150,8 +162,11 @@ static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip
netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i));
if (pcb && netif && netif == ip_current_input_netif ()) {
if (packet->src.type == IPADDR_TYPE_V4) {
#if CONFIG_LWIP_IPV6
if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) {
//packet source is not in the same subnet
#else
if ((packet->src.u_addr.ip4.addr & netif->netmask.addr) != (netif->ip_addr.addr & netif->netmask.addr)) {
#endif //packet source is not in the same subnet
pcb = NULL;
break;
}

View File

@ -51,6 +51,7 @@ tcpip_adapter_if_t tcpip_adapter_if_from_esp_netif(esp_netif_t *esp_netif);
*/
esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
#if CONFIG_LWIP_IPV6
/**
* @brief Translates to esp_netif_get_ip6_linklocal
*
@ -68,6 +69,7 @@ esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_
* @return See esp_netif_get_ip6_global
*/
esp_err_t tcpip_adapter_get_ip6_global(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6);
#endif
/**
* @brief`Translates to esp_netif_dhcpc_get_status
@ -92,12 +94,14 @@ bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if);
*/
esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif);
#if CONFIG_LWIP_IPV6
/**
* @brief Translates to esp_netif_create_ip6_linklocal
* @param tcpip_if Interface type corresponding to appropriate instance of esp-netif
* @return see esp_netif_create_ip6_linklocal
*/
esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if);
#endif
/**
* @brief Compatible version of setting ethernet default handlers

View File

@ -200,6 +200,7 @@ esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i
return esp_netif_get_ip_info(netif_from_if(tcpip_if), (esp_netif_ip_info_t *)ip_info);
}
#if CONFIG_LWIP_IPV6
esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6)
{
return esp_netif_get_ip6_linklocal(netif_from_if(tcpip_if), (esp_ip6_addr_t*)if_ip6);
@ -209,6 +210,7 @@ esp_err_t tcpip_adapter_get_ip6_global(tcpip_adapter_if_t tcpip_if, ip6_addr_t *
{
return esp_netif_get_ip6_global(netif_from_if(tcpip_if), (esp_ip6_addr_t*)if_ip6);
}
#endif
esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status)
{
@ -230,12 +232,12 @@ esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif)
}
return ESP_ERR_INVALID_ARG;
}
#if CONFIG_LWIP_IPV6
esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if)
{
return esp_netif_create_ip6_linklocal(netif_from_if(tcpip_if));
}
#endif
esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if)
{
return esp_netif_dhcps_stop(netif_from_if(tcpip_if));

View File

@ -373,6 +373,7 @@ Most lwIP RAM usage is on-demand, as RAM is allocated from the heap as needed. T
- Reducing :ref:`CONFIG_LWIP_MAX_SOCKETS` reduces the maximum number of sockets in the system. This will also cause TCP sockets in the ``WAIT_CLOSE`` state to be closed and recycled more rapidly (if needed to open a new socket), further reducing peak RAM usage.
- Reducing :ref:`CONFIG_LWIP_TCPIP_RECVMBOX_SIZE`, :ref:`CONFIG_LWIP_TCP_RECVMBOX_SIZE` and :ref:`CONFIG_LWIP_UDP_RECVMBOX_SIZE` reduce memory usage at the expense of throughput, depending on usage.
- Disable :ref:`CONFIG_LWIP_IPV6` can save about 39 KB for firmware size and 2KB RAM when system power up and 7KB RAM when TCPIP stack running. If there is no requirement for supporting IPV6 then it can be disabled to save flash and RAM footprint.
If using Wi-Fi, please also refer to :ref:`wifi-buffer-usage`.

View File

@ -189,6 +189,7 @@ menu "Example Connection Configuration"
bool "Obtain IPv6 address"
default y
depends on EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET
select LWIP_IPV6
help
By default, examples will wait until IPv4 and IPv6 local link addresses are obtained.
Disable this option if the network does not support IPv6.

View File

@ -10,7 +10,7 @@
#define HOST_IP_SIZE 128
esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_in6 *dest_addr)
esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_storage *dest_addr)
{
char host_ip[HOST_IP_SIZE];
int len;
@ -49,15 +49,18 @@ esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *ad
freeaddrinfo( addr_list );
return ESP_OK;
} else if (cur->ai_family == AF_INET6) {
}
#if CONFIG_LWIP_IPV6
else if (cur->ai_family == AF_INET6) {
*ip_protocol = IPPROTO_IPV6;
*addr_family = AF_INET6;
// add port and interface number and return on first IPv6 match
dest_addr->sin6_port = htons(port);
dest_addr->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
((struct sockaddr_in6*)dest_addr)->sin6_port = htons(port);
((struct sockaddr_in6*)dest_addr)->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
freeaddrinfo( addr_list );
return ESP_OK;
}
#endif
}
// no match found
freeaddrinfo( addr_list );

View File

@ -24,20 +24,20 @@ extern "C" {
* @brief Read and evaluate IP address from stdin
*
* This API reads stdin and parses the input address using getaddrinfo()
* to fill in struct sockaddr_in6 (for both IPv4 and IPv6) used to open
* to fill in struct sockaddr_storage (for both IPv4 and IPv6) used to open
* a socket. IP protocol is guessed from the IP address string.
*
* @param[in] port port number of expected connection
* @param[in] sock_type expected protocol: SOCK_STREAM or SOCK_DGRAM
* @param[out] ip_protocol resultant IP protocol: IPPROTO_IP or IPPROTO_IP6
* @param[out] addr_family resultant address family: AF_INET or AF_INET6
* @param[out] dest_addr sockaddr_in6 structure (for both IPv4 and IPv6)
* @param[out] dest_addr sockaddr_storage structure (for both IPv4 and IPv6)
* @return ESP_OK on success, ESP_FAIL otherwise
*/
esp_err_t get_addr_from_stdin(int port, int sock_type,
int *ip_protocol,
int *addr_family,
struct sockaddr_in6 *dest_addr);
struct sockaddr_storage *dest_addr);
#ifdef __cplusplus
}

View File

@ -60,7 +60,7 @@ static void tcp_client_task(void *pvParameters)
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
#elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
struct sockaddr_in6 dest_addr = { 0 };
struct sockaddr_storage dest_addr = { 0 };
ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr));
#endif
int sock = socket(addr_family, SOCK_STREAM, ip_protocol);

View File

@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.5)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(EXCLUDE_COMPONENTS "coap" "asio")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(tcp_server)

View File

@ -6,5 +6,6 @@
PROJECT_NAME := tcp_server
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
EXCLUDE_COMPONENTS = coap asio
include $(IDF_PATH)/make/project.mk

View File

@ -46,6 +46,12 @@ Set following parameters under Example Configuration Options:
* Set `Port` number of the socket, that server example will create.
* Set `TCP keep-alive idle time(s)` value of TCP keep alive idle time. This time is the time between the last data transmission.
* Set `TCP keep-alive interval time(s)` value of TCP keep alive interval time. This time is the interval time of keepalive probe packets.
* Set `TCP keep-alive packet retry send counts` value of TCP keep alive packet retry send counts. This is the number of retries of the keepalive probe packet.
Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
## Build and Flash

View File

@ -16,4 +16,21 @@ menu "Example Configuration"
help
Local port the example server will listen on.
config EXAMPLE_KEEPALIVE_IDLE
int "TCP keep-alive idle time(s)"
default 5
help
Keep-alive idle time. In idle time without receiving any data from peer, will send keep-alive probe packet
config EXAMPLE_KEEPALIVE_INTERVAL
int "TCP keep-alive interval time(s)"
default 5
help
Keep-alive probe packet interval time.
config EXAMPLE_KEEPALIVE_COUNT
int "TCP keep-alive packet retry send counts"
default 3
help
Keep-alive probe packet retry count.
endmenu

View File

@ -24,7 +24,10 @@
#include <lwip/netdb.h>
#define PORT CONFIG_EXAMPLE_PORT
#define PORT CONFIG_EXAMPLE_PORT
#define KEEPALIVE_IDLE CONFIG_EXAMPLE_KEEPALIVE_IDLE
#define KEEPALIVE_INTERVAL CONFIG_EXAMPLE_KEEPALIVE_INTERVAL
#define KEEPALIVE_COUNT CONFIG_EXAMPLE_KEEPALIVE_COUNT
static const char *TAG = "example";
@ -62,7 +65,11 @@ static void tcp_server_task(void *pvParameters)
char addr_str[128];
int addr_family = (int)pvParameters;
int ip_protocol = 0;
struct sockaddr_in6 dest_addr;
int keepAlive = 1;
int keepIdle = KEEPALIVE_IDLE;
int keepInterval = KEEPALIVE_INTERVAL;
int keepCount = KEEPALIVE_COUNT;
struct sockaddr_storage dest_addr;
if (addr_family == AF_INET) {
struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
@ -70,12 +77,16 @@ static void tcp_server_task(void *pvParameters)
dest_addr_ip4->sin_family = AF_INET;
dest_addr_ip4->sin_port = htons(PORT);
ip_protocol = IPPROTO_IP;
} else if (addr_family == AF_INET6) {
bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un));
dest_addr.sin6_family = AF_INET6;
dest_addr.sin6_port = htons(PORT);
}
#ifdef CONFIG_EXAMPLE_IPV6
else if (addr_family == AF_INET6) {
struct sockaddr_in6 *dest_addr_ip6 = (struct sockaddr_in6 *)&dest_addr;
bzero(&dest_addr_ip6->sin6_addr.un, sizeof(dest_addr_ip6->sin6_addr.un));
dest_addr_ip6->sin6_family = AF_INET6;
dest_addr_ip6->sin6_port = htons(PORT);
ip_protocol = IPPROTO_IPV6;
}
#endif
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0) {
@ -83,11 +94,11 @@ static void tcp_server_task(void *pvParameters)
vTaskDelete(NULL);
return;
}
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6)
// Note that by default IPV6 binds to both protocols, it is must be disabled
// if both protocols used at the same time (used in CI)
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
#endif
@ -119,12 +130,20 @@ static void tcp_server_task(void *pvParameters)
break;
}
// Set tcp keepalive option
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
// Convert ip address to string
if (source_addr.ss_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
} else if (source_addr.ss_family == PF_INET6) {
}
#ifdef CONFIG_EXAMPLE_IPV6
else if (source_addr.ss_family == PF_INET6) {
inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
}
#endif
ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
do_retransmit(sock);

View File

@ -0,0 +1,4 @@
CONFIG_EXAMPLE_IPV4=y
CONFIG_EXAMPLE_IPV6=n
CONFIG_EXAMPLE_CONNECT_IPV6=n
CONFIG_LWIP_IPV6=n

View File

@ -64,7 +64,7 @@ static void udp_client_task(void *pvParameters)
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
#elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
struct sockaddr_in6 dest_addr = { 0 };
struct sockaddr_storage dest_addr = { 0 };
ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_DGRAM, &ip_protocol, &addr_family, &dest_addr));
#endif