mirror of
https://github.com/espressif/esp-lwip.git
synced 2026-10-02 13:57:37 +00:00
ipv6: Support IPv4/IPv6 mapped PCBs
This change also drops UDP IPv4 packet received on IPv6-only socket. Ref IDF-4845
This commit is contained in:
@@ -248,6 +248,16 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ESP_LWIP && LWIP_IPV6
|
||||||
|
/* This should be eventually moved to a flag on the UDP PCB, and this drop can happen
|
||||||
|
more correctly in udp_input(). This will also allow icmp_dest_unreach() to be called. */
|
||||||
|
if (conn->flags & NETCONN_FLAG_IPV6_V6ONLY && !ip_current_is_v6()) {
|
||||||
|
LWIP_DEBUGF(API_MSG_DEBUG, ("recv_udp: Dropping IPv4 UDP packet (IPv6-only socket)"));
|
||||||
|
pbuf_free(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV6 */
|
||||||
|
|
||||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
@@ -668,6 +678,15 @@ pcb_new(struct api_msg *msg)
|
|||||||
if (msg->conn->pcb.ip == NULL) {
|
if (msg->conn->pcb.ip == NULL) {
|
||||||
msg->err = ERR_MEM;
|
msg->err = ERR_MEM;
|
||||||
}
|
}
|
||||||
|
#if ESP_LWIP && LWIP_IPV4 && LWIP_IPV6
|
||||||
|
else {
|
||||||
|
if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
|
||||||
|
/* Convert IPv4 PCB manually to an IPv6 PCB */
|
||||||
|
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
|
||||||
|
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV4 && LWIP_IPV6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1233,6 +1252,20 @@ lwip_netconn_do_bind(void *m)
|
|||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
|
#if ESP_LWIP && LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
|
||||||
|
* and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
|
||||||
|
*/
|
||||||
|
if (ip_addr_cmp(API_EXPR_REF(msg->msg.bc.ipaddr), IP6_ADDR_ANY) &&
|
||||||
|
(netconn_get_ipv6only(msg->conn) == 0)) {
|
||||||
|
/* change PCB type to IPADDR_TYPE_ANY */
|
||||||
|
IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
|
||||||
|
IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
|
||||||
|
|
||||||
|
/* bind to IPADDR_TYPE_ANY */
|
||||||
|
API_EXPR_REF(msg->msg.bc.ipaddr) = IP_ANY_TYPE;
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV4 && LWIP_IPV6 */
|
||||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
#if LWIP_RAW
|
#if LWIP_RAW
|
||||||
case NETCONN_RAW:
|
case NETCONN_RAW:
|
||||||
@@ -1548,6 +1581,14 @@ lwip_netconn_do_send(void *m)
|
|||||||
struct api_msg *msg = (struct api_msg *)m;
|
struct api_msg *msg = (struct api_msg *)m;
|
||||||
|
|
||||||
err_t err = netconn_err(msg->conn);
|
err_t err = netconn_err(msg->conn);
|
||||||
|
|
||||||
|
#if ESP_LWIP && LWIP_IPV4 && LWIP_IPV6
|
||||||
|
if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) &&IP_IS_V4MAPPEDV6(&msg->msg.b->addr)) {
|
||||||
|
LWIP_DEBUGF(API_MSG_DEBUG, ("lwip_netconn_do_send: Dropping IPv4 packet on IPv6-only socket"));
|
||||||
|
msg->err = ERR_VAL;
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
if (msg->conn->pcb.tcp != NULL) {
|
if (msg->conn->pcb.tcp != NULL) {
|
||||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||||
|
|||||||
@@ -335,6 +335,11 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
|||||||
type = NETCONN_DNS_IPV4;
|
type = NETCONN_DNS_IPV4;
|
||||||
} else if (ai_family == AF_INET6) {
|
} else if (ai_family == AF_INET6) {
|
||||||
type = NETCONN_DNS_IPV6;
|
type = NETCONN_DNS_IPV6;
|
||||||
|
#if ESP_LWIP
|
||||||
|
if (hints->ai_flags & AI_V4MAPPED) {
|
||||||
|
type = NETCONN_DNS_IPV6_IPV4;
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP */
|
||||||
}
|
}
|
||||||
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */
|
||||||
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
|
err = netconn_gethostbyname_addrtype(nodename, &addr, type);
|
||||||
@@ -351,6 +356,14 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ESP_LWIP && LWIP_IPV4 && LWIP_IPV6
|
||||||
|
if (ai_family == AF_INET6 && (hints->ai_flags & AI_V4MAPPED)
|
||||||
|
&& IP_GET_TYPE(&addr) == IPADDR_TYPE_V4) {
|
||||||
|
/* Convert native V4 address to a V4-mapped IPV6 address */
|
||||||
|
ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&addr), ip_2_ip4(&addr));
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
|
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);
|
||||||
if (nodename != NULL) {
|
if (nodename != NULL) {
|
||||||
namelen = strlen(nodename);
|
namelen = strlen(nodename);
|
||||||
|
|||||||
+12
-1
@@ -540,9 +540,20 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
|
|||||||
if (!IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) {
|
if (!IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
#if ESP_LWIP && LWIP_IPV4 && LWIP_IPV6
|
||||||
|
/* Unwrap IPV4-mapped IPV6 addresses and convert to native IPV4 here */
|
||||||
|
if (IP_IS_V4MAPPEDV6(dst_ip)) {
|
||||||
|
ip_addr_t dest_ipv4;
|
||||||
|
unmap_ipv4_mapped_ipv6(ip_2_ip4(&dest_ipv4), ip_2_ip6(dst_ip));
|
||||||
|
#if LWIP_CHECKSUM_ON_COPY
|
||||||
|
return udp_sendto_chksum(pcb, p, &dest_ipv4, dst_port, have_chksum, chksum);
|
||||||
|
#else
|
||||||
|
return udp_sendto(pcb, p, &dest_ipv4, dst_port);
|
||||||
|
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||||
|
}
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV4 && LWIP_IPV6 */
|
||||||
|
|
||||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||||
|
|
||||||
if (pcb->netif_idx != NETIF_NO_INDEX) {
|
if (pcb->netif_idx != NETIF_NO_INDEX) {
|
||||||
netif = netif_get_by_index(pcb->netif_idx);
|
netif = netif_get_by_index(pcb->netif_idx);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -133,6 +133,11 @@ extern const ip_addr_t ip_addr_any_type;
|
|||||||
ip_2_ip6(ipaddr)->addr[3] = 0; \
|
ip_2_ip6(ipaddr)->addr[3] = 0; \
|
||||||
ip6_addr_clear_zone(ip_2_ip6(ipaddr)); }while(0)
|
ip6_addr_clear_zone(ip_2_ip6(ipaddr)); }while(0)
|
||||||
|
|
||||||
|
#if ESP_LWIP && LWIP_IPV6
|
||||||
|
#define IP_V6_EQ_PART(ipaddr, WORD, VAL) (ip_2_ip6(ipaddr)->addr[WORD] == htonl(VAL))
|
||||||
|
#define IP_IS_V4MAPPEDV6(ipaddr) (IP_IS_V6(ipaddr) && IP_V6_EQ_PART(ipaddr, 0, 0) && IP_V6_EQ_PART(ipaddr, 1, 0) && IP_V6_EQ_PART(ipaddr, 2, 0x0000FFFF))
|
||||||
|
#endif /* ESP_LWIP && LWIP_IPV6 */
|
||||||
|
|
||||||
/** @ingroup ipaddr */
|
/** @ingroup ipaddr */
|
||||||
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \
|
||||||
ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
|
ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \
|
||||||
|
|||||||
Reference in New Issue
Block a user