mirror of
https://github.com/espressif/esp-lwip.git
synced 2026-06-05 21:04:45 +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;
|
||||
}
|
||||
|
||||
#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);
|
||||
if (buf == NULL) {
|
||||
pbuf_free(p);
|
||||
@@ -668,6 +678,15 @@ pcb_new(struct api_msg *msg)
|
||||
if (msg->conn->pcb.ip == NULL) {
|
||||
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;
|
||||
|
||||
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)) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
@@ -1548,6 +1581,14 @@ lwip_netconn_do_send(void *m)
|
||||
struct api_msg *msg = (struct api_msg *)m;
|
||||
|
||||
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 (msg->conn->pcb.tcp != NULL) {
|
||||
switch (NETCONNTYPE_GROUP(msg->conn->type)) {
|
||||
|
||||
@@ -335,6 +335,11 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
type = NETCONN_DNS_IPV4;
|
||||
} else if (ai_family == AF_INET6) {
|
||||
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 */
|
||||
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);
|
||||
if (nodename != NULL) {
|
||||
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)) {
|
||||
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"));
|
||||
|
||||
if (pcb->netif_idx != NETIF_NO_INDEX) {
|
||||
netif = netif_get_by_index(pcb->netif_idx);
|
||||
} else {
|
||||
|
||||
@@ -133,6 +133,11 @@ extern const ip_addr_t ip_addr_any_type;
|
||||
ip_2_ip6(ipaddr)->addr[3] = 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 */
|
||||
#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{ \
|
||||
|
||||
Reference in New Issue
Block a user