diff --git a/src/api/api_lib.c b/src/api/api_lib.c index b4fc403d..9be38b71 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -231,6 +231,14 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); #endif /* LWIP_MPU_COMPATIBLE */ API_MSG_VAR_FREE(msg); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */ + if (NETCONNTYPE_ISIPV6(netconn_type(conn)) && IP_IS_V4(addr)) { + ip4_2_ipv6_mapped_ipv4(ip_2_ip6(addr), ip_2_ip4(addr)); + IP_SET_TYPE(addr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ return err; } @@ -250,6 +258,7 @@ err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) { API_MSG_VAR_DECLARE(msg); + ip_addr_t ipaddr; err_t err; LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); @@ -258,10 +267,28 @@ netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) if (addr == NULL) { addr = IP4_ADDR_ANY; } + + ip_addr_copy(ipaddr, *addr); + + #if 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 0, use IP_ANY_TYPE to bind + */ + if ((netconn_get_ipv6only(conn) == 0) && + ip_addr_cmp(&ipaddr, IP6_ADDR_ANY)) { + ip_addr_copy(ipaddr, *IP_ANY_TYPE); + } + + /* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ + if (IP_IS_V6_VAL(ipaddr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&ipaddr))) { + unmap_ipv6_mapped_ipv4(ip_2_ip4(&ipaddr), ip_2_ip6(&ipaddr)); + IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(&ipaddr); API_MSG_VAR_REF(msg).msg.bc.port = port; err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); @@ -282,6 +309,7 @@ err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) { API_MSG_VAR_DECLARE(msg); + ip_addr_t ipaddr; err_t err; LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); @@ -291,9 +319,27 @@ netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) addr = IP4_ADDR_ANY; } + ip_addr_copy(ipaddr, *addr); + + #if 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 0, use IP_ANY_TYPE to bind + */ + if ((netconn_get_ipv6only(conn) == 0) && + ip_addr_cmp(&ipaddr, IP6_ADDR_ANY)) { + ip_addr_copy(ipaddr, *IP_ANY_TYPE); + } + + /* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ + if (IP_IS_V6_VAL(ipaddr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&ipaddr))) { + unmap_ipv6_mapped_ipv4(ip_2_ip4(&ipaddr), ip_2_ip6(&ipaddr)); + IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(&ipaddr); API_MSG_VAR_REF(msg).msg.bc.port = port; err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); @@ -561,8 +607,18 @@ netconn_recv_data(struct netconn *conn, void **new_buf) #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ #if (LWIP_UDP || LWIP_RAW) { + struct netbuf* nbuf = (struct netbuf*)buf; + LWIP_ASSERT("buf != NULL", buf != NULL); - len = netbuf_len((struct netbuf *)buf); + len = netbuf_len(nbuf); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv6 mapped IPv4 */ + if (NETCONNTYPE_ISIPV6(netconn_type(conn)) && IP_IS_V4_VAL(nbuf->addr)) { + ip4_2_ipv6_mapped_ipv4(ip_2_ip6(&nbuf->addr), ip_2_ip4(&nbuf->addr)); + IP_SET_TYPE_VAL(nbuf->addr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ } #endif /* (LWIP_UDP || LWIP_RAW) */ @@ -697,6 +753,15 @@ netconn_send(struct netconn *conn, struct netbuf *buf) LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ + if (IP_IS_V6_VAL(buf->addr) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&buf->addr))) { + unmap_ipv6_mapped_ipv4(ip_2_ip4(&buf->addr), ip_2_ip6(&buf->addr)); + IP_SET_TYPE_VAL(buf->addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; API_MSG_VAR_REF(msg).msg.b = buf; diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 2b76f077..e19a6a0c 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -545,13 +545,18 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) static void pcb_new(struct api_msg *msg) { - LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + enum lwip_ip_addr_type iptype; + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ + iptype = NETCONNTYPE_ISIPV6(netconn_type(msg->conn))? IPADDR_TYPE_ANY : IPADDR_TYPE_V4; + /* Allocate a PCB for this connection */ switch(NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: - msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); if (msg->conn->pcb.raw != NULL) { raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); } @@ -559,7 +564,7 @@ pcb_new(struct api_msg *msg) #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: - msg->conn->pcb.udp = udp_new(); + msg->conn->pcb.udp = udp_new_ip_type(iptype); if (msg->conn->pcb.udp != NULL) { #if LWIP_UDPLITE if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { @@ -575,7 +580,7 @@ pcb_new(struct api_msg *msg) #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - msg->conn->pcb.tcp = tcp_new(); + msg->conn->pcb.tcp = tcp_new_ip_type(iptype); if (msg->conn->pcb.tcp != NULL) { setup_tcp(msg->conn); } @@ -589,15 +594,6 @@ pcb_new(struct api_msg *msg) if (msg->conn->pcb.ip == NULL) { msg->err = ERR_MEM; } -#if 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 /* LWIP_IPV4 && LWIP_IPV6 */ } /** @@ -1114,37 +1110,20 @@ lwip_netconn_do_bind(void *m) } else { msg->err = ERR_VAL; if (msg->conn->pcb.tcp != NULL) { - const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr); - -#if 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(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 */ - ipaddr = IP_ANY_TYPE; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: - msg->err = raw_bind(msg->conn->pcb.raw, ipaddr); + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: - msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port); + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port); + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); break; #endif /* LWIP_TCP */ default: @@ -1398,15 +1377,6 @@ lwip_netconn_do_send(void *m) } else { msg->err = ERR_CONN; if (msg->conn->pcb.tcp != NULL) { - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv6 mapped IPv4 addresses */ - if (NETCONNTYPE_ISIPV6(netconn_type(msg->conn)) && ip6_addr_isipv6mappedipv4(ip_2_ip6(&msg->msg.b->addr))) { - unmap_ipv6_mapped_ipv4(ip_2_ip4(&msg->msg.b->addr), ip_2_ip6(&msg->msg.b->addr)); - IP_SET_TYPE(&msg->msg.b->addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: @@ -1720,14 +1690,6 @@ lwip_netconn_do_getaddr(void *m) ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), msg->conn->pcb.ip->remote_ip); } - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Map IPv4 addresses to IPv6 */ - if (NETCONNTYPE_ISIPV6(netconn_type(msg->conn)) && IP_IS_V4_VAL(API_EXPR_DEREF(msg->msg.ad.ipaddr))) { - ip4_2_ipv6_mapped_ipv4(ip_2_ip6(&API_EXPR_DEREF(msg->msg.ad.ipaddr)), ip_2_ip4(&API_EXPR_DEREF(msg->msg.ad.ipaddr))); - IP_SET_TYPE_VAL(API_EXPR_DEREF(msg->msg.ad.ipaddr), IPADDR_TYPE_V6); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ msg->err = ERR_OK; switch (NETCONNTYPE_GROUP(msg->conn->type)) { diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index e8620dd8..d1394533 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -90,6 +90,7 @@ extern "C" { #define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) #define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) #else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISIPV6(t) (0) #define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) #define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) #endif /* LWIP_IPV6 */