summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-17 07:37:44 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-17 07:37:44 -0600
commit480fa9b47778b9089a8e25129f913239a638c5c3 (patch)
treebcfdb60c75f771ae58b07e8f9c2a3b018eb9b461
parent25392034e99f6ecac1c5987c226e32324dfe6f67 (diff)
downloadnuttx-480fa9b47778b9089a8e25129f913239a638c5c3.tar.gz
nuttx-480fa9b47778b9089a8e25129f913239a638c5c3.tar.bz2
nuttx-480fa9b47778b9089a8e25129f913239a638c5c3.zip
Move some useful internal logic from recvfrom.c and udp_callback.c and put them in ip.h where they can be used more generally
-rw-r--r--nuttx/include/nuttx/net/ip.h43
-rw-r--r--nuttx/net/socket/recvfrom.c19
-rw-r--r--nuttx/net/udp/udp_callback.c19
3 files changed, 60 insertions, 21 deletions
diff --git a/nuttx/include/nuttx/net/ip.h b/nuttx/include/nuttx/net/ip.h
index 3bb221f10..0f80cd2e1 100644
--- a/nuttx/include/nuttx/net/ip.h
+++ b/nuttx/include/nuttx/net/ip.h
@@ -328,17 +328,50 @@ EXTERN const net_ipv6addr_t g_ipv6_llnetmask; /* Netmask for local link addres
} while (0)
/****************************************************************************
+ * Macro: ip6_map_ipv4addr
+ *
+ * Description:
+ * Hybrid dual-stack IPv6/IPv4 implementations recognize a special class
+ * of addresses, the IPv4-mapped IPv6 addresses. These addresses consist
+ * of:
+ *
+ * 1. An 80-bit prefix of zeros,
+ * 2. Te next 16 bits are one, and
+ * 3. he remaining, least-significant 32 bits contain the IPv4 address.
+ *
+ * This macro encodes an IPv4 address in an IPv6 address in this fashion.
+ *
+ * Input Parameters:
+ * ipv4addr - The IPv4 address to be mapped (scalar)
+ * ipv6addr - The IPv6 address in which to map the IPv4 address (array)
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#define ip6_map_ipv4addr(ipv4addr, ipv6addr) \
+ do \
+ { \
+ memset(ipv6addr, 0, 5 * sizeof(uint16_t)); \
+ ipv6addr[5] = 0xffff; \
+ ipv6addr[6] = (uint16_t)((uint32_t)ip4addr >> 16); \
+ ipv6addr[7] = (uint16_t)ip4addr & 0xffff; \
+ } \
+ while (0)
+
+/****************************************************************************
* Macro: ip6_get_ipv4addr
*
* Description:
- * Decode an encoded IPv4 address.
+ * Decode an IPv4-mapped IPv6 address.
*
* Input Parameters:
- * ipv6addr - The IPv6 address (net_ipv6addr_t) containing the encoded
+ * ipv6addr - The IPv6 address (net_ipv6addr_t array) containing the mapped
* IPv4 address
*
* Returned Value:
- * The decode IPv4 addreses (in_addr_t)
+ * The decoded IPv4 address (scalar in_addr_t)
*
****************************************************************************/
@@ -352,13 +385,13 @@ EXTERN const net_ipv6addr_t g_ipv6_llnetmask; /* Netmask for local link addres
* Macro: ip6_is_ipv4addr
*
* Description:
- * Test if an IPv6 is an encoded IPv4 address.
+ * Test if an IPv6 is an IPv4-mapped IPv6 address.
*
* Input Parameters:
* ipv6addr - The IPv6 address to be tested
*
* Returned Value:
- * True is returned if ipv6addr holds an encoded IPv4 address.
+ * True is returned if ipv6addr holds a mapped IPv4 address.
*
****************************************************************************/
diff --git a/nuttx/net/socket/recvfrom.c b/nuttx/net/socket/recvfrom.c
index 3ca7b125e..13d42061a 100644
--- a/nuttx/net/socket/recvfrom.c
+++ b/nuttx/net/socket/recvfrom.c
@@ -971,20 +971,23 @@ static inline void recvfrom_udpsender(struct net_driver_s *dev, struct recvfrom_
FAR struct udp_conn_s *conn = (FAR struct udp_conn_s*)pstate->rf_sock->s_conn;
FAR struct sockaddr_in6 *infrom6 = (FAR struct sockaddr_in6 *)infrom;
+ /* Hybrid dual-stack IPv6/IPv4 implementations recognize a special
+ * class of addresses, the IPv4-mapped IPv6 addresses.
+ */
+
if (conn->domain == PF_INET6)
{
+ in_addr_t ipv4addr;
+
+ /* Encode the IPv4 address as an IPv4-mapped IPv6 address */
+
infrom6->sin6_family = AF_INET6;
infrom6->sin6_port = udp->srcport;
*fromlen = sizeof(struct sockaddr_in6);
- memset(infrom6->sin6_addr.s6_addr, 0,
- sizeof(infrom6->sin6_addr.s6_addr) - sizeof(in_addr_t));
-
- infrom6->sin6_addr.s6_addr[10] = 0xff;
- infrom6->sin6_addr.s6_addr[11] = 0xff;
-
- memcpy(&infrom6->sin6_addr.s6_addr[12], ipv4->srcipaddr
- sizeof(in_addr_t));
+ ipv4addr = net_ip4addr_conv32(ipv4->srcipaddr);
+ ip6_map_ipv4addr(ipv4addr,
+ (net_ipv6addr_t)src_addr6.sin6_addr.s6_addr16);
}
else
#endif
diff --git a/nuttx/net/udp/udp_callback.c b/nuttx/net/udp/udp_callback.c
index 583f348af..807c12446 100644
--- a/nuttx/net/udp/udp_callback.c
+++ b/nuttx/net/udp/udp_callback.c
@@ -133,19 +133,22 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev, FAR struct udp_con
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
#ifdef CONFIG_NET_IPv6
+ /* Hybrid dual-stack IPv6/IPv4 implementations recognize a special
+ * class of addresses, the IPv4-mapped IPv6 addresses.
+ */
+
if (conn->domain == PF_INET6)
{
- src_addr6.sin6_family = AF_INET6;
- src_addr6.sin6_port = udp->srcport;
+ in_addr_t ipv4addr;
- memset(src_addr6.sin6_addr.s6_addr, 0,
- sizeof(src_addr6.sin6_addr.s6_addr) - sizeof(in_addr_t));
+ /* Encode the IPv4 address as an IPv-mapped IPv6 address */
- src_addr6.sin6_addr.s6_addr[10] = 0xff;
- src_addr6.sin6_addr.s6_addr[11] = 0xff;
+ src_addr6.sin6_family = AF_INET6;
+ src_addr6.sin6_port = udp->srcport;
- memcpy(&src_addr6.sin6_addr.s6_addr[12], ipv4->srcipaddr,
- sizeof(in_addr_t));
+ ipv4addr = net_ip4addr_conv32(ipv4->srcipaddr);
+ ip6_map_ipv4addr(ipv4addr,
+ (net_ipv6addr_t)src_addr6.sin6_addr.s6_addr16);
src_addr_size = sizeof(src_addr6);
src_addr = &src_addr6;