Networking: Drivers can have both IPv4 and IPv6 addesses, but a socket can only only one or the other; The socket connnection structures need to include a union of IPv4 and IPv6 addresses for the local address binding and for the remote address connections

This commit is contained in:
Gregory Nutt 2015-01-16 10:01:54 -06:00
parent fe8b3c5220
commit bee89be4f4
17 changed files with 113 additions and 75 deletions

View File

@ -90,7 +90,7 @@
* Public Type Definitions
****************************************************************************/
/* Representation of an IP address */
/* Representation of an IP address in the IPv6 domains */
typedef uint16_t net_ipv6addr_t[8];
@ -100,6 +100,52 @@ typedef net_ipv6addr_t net_ipaddr_t;
typedef in_addr_t net_ipaddr_t;
#endif
/* Describes and address in either the IPv4 or IPv6 domain */
union ip_addr_u
{
#ifdef CONFIG_NET_IPv4
/* IPv4 address */
in_addr_t ipv4;
#endif
#ifdef CONFIG_NET_IPv6
/* IPv6 addresse */
net_ipv6addr_t ipv6;
#endif
};
/* Describes address binding for a PF_INET or PF_INET6 socket */
union ip_binding_u
{
#ifdef CONFIG_NET_IPv4
/* IPv4 addresses (for PF_INET socket) */
struct
{
#ifdef CONFIG_NETDEV_MULTINIC
in_addr_t laddr; /* The bound local IPv4 address */
#endif
in_addr_t raddr; /* The IPv4 address of the remote host */
} ipv4;
#endif /* CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6
/* IPv6 addresses (for PF_INET6 socket) */
struct
{
#ifdef CONFIG_NETDEV_MULTINIC
net_ipv6addr_t laddr; /* The bound local IPv6 address */
#endif
net_ipv6addr_t raddr; /* The IPv6 address of the remote host */
} ipv6;
#endif /* CONFIG_NET_IPv6 */
};
#ifdef CONFIG_NET_IPv4
/* The IPv4 header */

View File

@ -209,7 +209,7 @@ int ipv6_input(FAR struct net_driver_s *dev)
else
#endif
#ifdef CONFIG_NET_ICMPv6
if (net_ipv6addr_cmp(dev->d_ipaddr, g_allzeroaddr))
if (net_ipv6addr_cmp(dev->d_ipv6addr, g_allzeroaddr))
{
/* If we are configured to use ping IP address configuration and
* hasn't been assigned an IP address yet, we accept all ICMP
@ -233,7 +233,7 @@ int ipv6_input(FAR struct net_driver_s *dev)
* multicast packets that are sent to the ff02::/16 addresses.
*/
if (!net_ipv6addr_cmp(pbuf->destipaddr, dev->d_ipaddr) &&
if (!net_ipv6addr_cmp(pbuf->destipaddr, dev->d_ipv6addr) &&
pbuf->destipaddr[0] != 0xff02)
{
#ifdef CONFIG_NET_STATISTICS

View File

@ -160,7 +160,7 @@ netdev_finddevice_ipv6addr(const net_ipv6addr_t ripaddr)
{
/* Yes.. check for an address match (under the netmask) */
if (net_ipaddr_maskcmp(dev->d_ipv6ipaddr, ripaddr, dev->d_ipv6netmask))
if (net_ipaddr_maskcmp(dev->d_ipv6addr, ripaddr, dev->d_ipv6netmask))
{
/* Its a match */

View File

@ -112,7 +112,7 @@ static inline void accept_tcpsender(FAR struct tcp_conn_s *conn,
{
addr->sin_family = AF_INET6;
addr->sin_port = conn->rport;
net_ipaddr_copy(addr->sin6_addr.s6_addr, conn->ripaddr);
net_ipaddr_copy(addr->sin6_addr.s6_addr, conn->u.ipv4.raddr);
}
}
#else
@ -123,7 +123,7 @@ static inline void accept_tcpsender(FAR struct tcp_conn_s *conn,
{
addr->sin_family = AF_INET;
addr->sin_port = conn->rport;
net_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr);
net_ipaddr_copy(addr->sin_addr.s_addr, conn->u.ipv4.raddr);
}
}
#endif /* CONFIG_NET_IPv6 */

View File

@ -121,8 +121,8 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
lipaddr = tcp_conn->lipaddr;
ripaddr = tcp_conn->ripaddr;
lipaddr = tcp_conn->u.ipv4.laddr;
ripaddr = tcp_conn->u.ipv4.raddr;
#endif
}
break;
@ -134,8 +134,8 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
outaddr->sin_port = udp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
lipaddr = udp_conn->lipaddr;
ripaddr = udp_conn->ripaddr;
lipaddr = udp_conn->u.ipv4.laddr;
ripaddr = udp_conn->u.ipv4.raddr;
#endif
}
break;
@ -244,8 +244,8 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
lipaddr = tcp_conn->lipaddr;
ripaddr = tcp_conn->ripaddr;
lipaddr = &tcp_conn->u.ipv6.laddr;
ripaddr = &tcp_conn->u.ipv6.raddr;
#endif
}
break;
@ -257,16 +257,15 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
outaddr->sin_port = udp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
lipaddr = &udp_conn->lipaddr;
ripaddr = &udp_conn->ripaddr;
lipaddr = &udp_conn->u.ipv6.laddr;
ripaddr = &udp_conn->u.ipv6.raddr;
#endif
}
break;
#endif
default:
err = EOPNOTSUPP;
goto errout;
return -EOPNOTSUPP;
}
/* The socket/connection does not know its IP address unless
@ -296,7 +295,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
outaddr->sin_family = AF_INET6;
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16);
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipv6addr, 16);
*addrlen = sizeof(struct sockaddr_in6);
#endif
netdev_semgive();

View File

@ -358,9 +358,9 @@ static inline int netclose_disconnect(FAR struct socket *psock)
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NET_MULTILINK
netdev_txnotify(conn->lipaddr, conn->ripaddr);
netdev_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_txnotify(conn->ripaddr);
netdev_txnotify(conn->u.ipv4.raddr);
#endif
#ifdef CONFIG_NET_SOLINGER

View File

@ -330,7 +330,7 @@ static uint16_t sendfile_interrupt(FAR struct net_driver_s *dev, FAR void *pvcon
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (pstate->snd_sent != 0 || arp_find(conn->ripaddr) != NULL)
if (pstate->snd_sent != 0 || arp_find(conn->u.ipv4.raddr) != NULL)
#endif
{
/* Update the amount of data sent (but not necessarily ACKed) */
@ -484,7 +484,7 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
/* Make sure that the IP address mapping is in the ARP table */
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
ret = arp_send(conn->u.ipv4.raddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
@ -565,9 +565,9 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NET_MULTILINK
netdev_txnotify(conn->lipaddr, conn->ripaddr);
netdev_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_txnotify(conn->ripaddr);
netdev_txnotify(conn->u.ipv4.raddr);
#endif
net_lockedwait(&state.snd_sem);
}

View File

@ -1097,9 +1097,9 @@ static ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
#if 0 /* No */
#ifdef CONFIG_NET_MULTILINK
netdev_rxnotify(conn->lipaddr, conn->ripaddr);
netdev_rxnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_rxnotify(conn->ripaddr);
netdev_rxnotify(conn->u.ipv4.raddr);
#endif
#endif
@ -1196,9 +1196,9 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Notify the device driver of the receive call */
#ifdef CONFIG_NET_MULTILINK
netdev_rxnotify(conn->lipaddr, conn->ripaddr);
netdev_rxnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_rxnotify(conn->ripaddr);
netdev_rxnotify(conn->u.ipv4.raddr);
#endif
/* Wait for either the receive to complete or for an error/timeout to occur.

View File

@ -420,9 +420,9 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NET_MULTILINK
netdev_txnotify(conn->lipaddr, conn->ripaddr);
netdev_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_txnotify(conn->ripaddr);
netdev_txnotify(conn->u.ipv4.raddr);
#endif
/* Wait for either the receive to complete or for an error/timeout to occur.

View File

@ -90,7 +90,6 @@
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* Representation of a TCP connection.
*
* The tcp_conn_s structure is used for identifying a connection. All
@ -108,10 +107,7 @@ struct tcp_hdr_s; /* Forward reference */
struct tcp_conn_s
{
dq_entry_t node; /* Implements a doubly linked list */
#ifdef CONFIG_NETDEV_MULTINIC
net_ipaddr_t lipaddr; /* The bound local IP address */
#endif
net_ipaddr_t ripaddr; /* The IP address of the remote host */
union ip_binding_u u; /* IP address binding */
uint8_t rcvseq[4]; /* The sequence number that we expect to
* receive next */
uint8_t sndseq[4]; /* The sequence number that was last sent by us */

View File

@ -132,11 +132,11 @@ static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
* with INADDR_ANY.
*/
if (net_ipaddr_cmp(conn->lipaddr, ipaddr) ||
if (net_ipaddr_cmp(conn->u.ipv4.laddr, ipaddr) ||
#ifdef CONFIG_NET_IPv6
net_ipaddr_cmp(conn->lipaddr, g_allzeroaddr))
net_ipaddr_cmp(conn->u.ipv4.laddr, g_allzeroaddr))
#else
net_ipaddr_cmp(conn->lipaddr, INADDR_ANY))
net_ipaddr_cmp(conn->u.ipv4.laddr, INADDR_ANY))
#endif
#endif
{
@ -525,10 +525,10 @@ FAR struct tcp_conn_s *tcp_active(FAR struct net_driver_s *dev,
tcp->destport == conn->lport &&
tcp->srcport == conn->rport &&
#ifdef CONFIG_NETDEV_MULTINIC
(net_ipaddr_cmp(conn->lipaddr, g_allzeroaddr) ||
net_ipaddr_cmp(destipaddr, conn->lipaddr)) &&
(net_ipaddr_cmp(conn->u.ipv4.laddr, g_allzeroaddr) ||
net_ipaddr_cmp(destipaddr, conn->u.ipv4.laddr)) &&
#endif
net_ipaddr_cmp(srcipaddr, conn->ripaddr))
net_ipaddr_cmp(srcipaddr, conn->u.ipv4.raddr))
{
/* Matching connection found.. break out of the loop and return a
* reference to it.
@ -601,9 +601,9 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
conn->lport = tcp->destport;
conn->rport = tcp->srcport;
conn->mss = TCP_INITIAL_MSS(dev);
net_ipaddr_copy(conn->ripaddr, net_ip4addr_conv32(ip->srcipaddr));
net_ipaddr_copy(conn->u.ipv4.raddr, net_ip4addr_conv32(ip->srcipaddr));
#ifdef CONFIG_NETDEV_MULTINIC
net_ipaddr_copy(conn->lipaddr, net_ip4addr_conv32(ip->destipaddr));
net_ipaddr_copy(conn->u.ipv4.laddr, net_ip4addr_conv32(ip->destipaddr));
#endif
conn->tcpstateflags = TCP_SYN_RCVD;
@ -707,7 +707,7 @@ int tcp_bind(FAR struct tcp_conn_s *conn,
conn->lport = addr->sin_port;
#ifdef CONFIG_NETDEV_MULTINIC
net_ipaddr_copy(conn->lipaddr, ipaddr);
net_ipaddr_copy(conn->u.ipv4.laddr, ipaddr);
#endif
return OK;
@ -761,7 +761,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn,
flags = net_lock();
#ifdef CONFIG_NETDEV_MULTINIC
port = tcp_selectport(conn->lipaddr, ntohs(conn->lport));
port = tcp_selectport(conn->u.ipv4.laddr, ntohs(conn->lport));
#else
port = tcp_selectport(ntohs(conn->lport));
#endif
@ -801,7 +801,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn,
/* The sockaddr address is 32-bits in network order. */
net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr);
net_ipaddr_copy(conn->u.ipv4.raddr, addr->sin_addr.s_addr);
#ifdef CONFIG_NET_TCP_READAHEAD
/* Initialize the list of TCP read-ahead buffers */

View File

@ -188,7 +188,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
pbuf->destport = conn->rport;
net_ipaddr_hdrcopy(pbuf->srcipaddr, &dev->d_ipaddr);
net_ipaddr_hdrcopy(pbuf->destipaddr, &conn->ripaddr);
net_ipaddr_hdrcopy(pbuf->destipaddr, &conn->u.ipv4.raddr);
if (conn->tcpstateflags & TCP_STOPPED)
{

View File

@ -552,7 +552,7 @@ static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev,
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (arp_find(conn->ripaddr) != NULL)
if (arp_find(conn->u.ipv4.raddr) != NULL)
#endif
{
FAR struct tcp_wrbuffer_s *wrb;
@ -754,7 +754,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
conn = (FAR struct tcp_conn_s *)psock->s_conn;
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
ret = arp_send(conn->u.ipv4.raddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
@ -829,9 +829,9 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NET_MULTILINK
netdev_txnotify(conn->lipaddr, conn->ripaddr);
netdev_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_txnotify(conn->ripaddr);
netdev_txnotify(conn->u.ipv4.raddr);
#endif
result = len;
}

View File

@ -397,7 +397,7 @@ static uint16_t tcpsend_interrupt(FAR struct net_driver_s *dev,
#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \
!defined(CONFIG_NET_ARP_SEND)
if (pstate->snd_sent != 0 || arp_find(conn->ripaddr) != NULL)
if (pstate->snd_sent != 0 || arp_find(conn->u.ipv4.raddr) != NULL)
#endif
{
/* Update the amount of data sent (but not necessarily ACKed) */
@ -538,7 +538,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
conn = (FAR struct tcp_conn_s *)psock->s_conn;
#ifdef CONFIG_NET_ARP_SEND
ret = arp_send(conn->ripaddr);
ret = arp_send(conn->u.ipv4.raddr);
if (ret < 0)
{
ndbg("ERROR: Not reachable\n");
@ -591,15 +591,15 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
state.snd_cb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL |
TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT);
state.snd_cb->priv = (void*)&state;
state.snd_cb->priv = (FAR void *)&state;
state.snd_cb->event = tcpsend_interrupt;
/* Notify the device driver of the availability of TX data */
#ifdef CONFIG_NET_MULTILINK
netdev_txnotify(conn->lipaddr, conn->ripaddr);
netdev_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
#else
netdev_txnotify(conn->ripaddr);
netdev_txnotify(conn->u.ipv4.raddr);
#endif
/* Wait for the send to complete or an error to occur: NOTES: (1)

View File

@ -67,10 +67,7 @@ struct udp_hdr_s; /* Forward reference */
struct udp_conn_s
{
dq_entry_t node; /* Supports a doubly linked list */
#ifdef CONFIG_NETDEV_MULTINIC
net_ipaddr_t lipaddr; /* Bound local IP address (network byte order) */
#endif
net_ipaddr_t ripaddr; /* IP address of remote peer (network byte order) */
union ip_binding_u u; /* IP address binding */
uint16_t lport; /* Bound local port number (network byte order) */
uint16_t rport; /* Remote port number (network byte order) */
uint8_t ttl; /* Default time-to-live */

View File

@ -150,11 +150,11 @@ static FAR struct udp_conn_s *udp_find_conn(uint16_t portno)
*/
if (conn->lport == portno &&
(net_ipaddr_cmp(conn->lipaddr, ipaddr) ||
(net_ipaddr_cmp(conn->u.ipv4.laddr, ipaddr) ||
#ifdef CONFIG_NET_IPv6
net_ipaddr_cmp(conn->lipaddr, g_allzeroaddr)))
net_ipaddr_cmp(conn->u.ipv4.laddr, g_allzeroaddr)))
#else
net_ipaddr_cmp(conn->lipaddr, INADDR_ANY)))
net_ipaddr_cmp(conn->u.ipv4.laddr, INADDR_ANY)))
#endif
{
return conn;
@ -368,7 +368,7 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
* IP address is available and we will insist that the
* destination IP matches the bound address (or the destination
* IP address is a broadcast address). If a socket is bound to
* INADDRY_ANY (lipaddr), then it should receive all packets
* INADDRY_ANY (laddr), then it should receive all packets
* directed to the port.
* - Finally, if the connection is bound to a remote IP address,
* the source IP address of the packet is checked. Broadcast
@ -381,13 +381,13 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
if (conn->lport != 0 && udp->destport == conn->lport &&
(conn->rport == 0 || udp->srcport == conn->rport) &&
#ifdef CONFIG_NETDEV_MULTINIC
(net_ipaddr_cmp(conn->lipaddr, g_allzeroaddr) ||
net_ipaddr_cmp(conn->lipaddr, g_alloneaddr) ||
net_ipaddr_hdrcmp(ip->destipaddr, &conn->lipaddr)) &&
(net_ipaddr_cmp(conn->u.ipv4.laddr, g_allzeroaddr) ||
net_ipaddr_cmp(conn->u.ipv4.laddr, g_alloneaddr) ||
net_ipaddr_hdrcmp(ip->destipaddr, &conn->u.ipv4.laddr)) &&
#endif
(net_ipaddr_cmp(conn->ripaddr, g_allzeroaddr) ||
net_ipaddr_cmp(conn->ripaddr, g_alloneaddr) ||
net_ipaddr_hdrcmp(ip->srcipaddr, &conn->ripaddr)))
(net_ipaddr_cmp(conn->u.ipv4.raddr, g_allzeroaddr) ||
net_ipaddr_cmp(conn->u.ipv4.raddr, g_alloneaddr) ||
net_ipaddr_hdrcmp(ip->srcipaddr, &conn->u.ipv4.raddr)))
{
/* Matching connection found.. return a reference to it */
@ -467,7 +467,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr_in *addr)
* for receiving (Sending will use the default port).
*/
net_ipaddr_copy(conn->lipaddr, ipaddr);
net_ipaddr_copy(conn->u.ipv4.laddr, ipaddr);
#endif
/* Is the user requesting to bind to any port? */
@ -553,7 +553,7 @@ int udp_connect(FAR struct udp_conn_s *conn,
*/
#ifdef CONFIG_NETDEV_MULTINIC
conn->lport = htons(udp_select_port(conn->lipaddr));
conn->lport = htons(udp_select_port(conn->u.ipv4.laddr));
#else
conn->lport = htons(udp_select_port());
#endif
@ -564,12 +564,12 @@ int udp_connect(FAR struct udp_conn_s *conn,
if (addr)
{
conn->rport = addr->sin_port;
net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr);
net_ipaddr_copy(conn->u.ipv4.raddr, addr->sin_addr.s_addr);
}
else
{
conn->rport = 0;
net_ipaddr_copy(conn->ripaddr, g_allzeroaddr);
net_ipaddr_copy(conn->u.ipv4.raddr, g_allzeroaddr);
}
conn->ttl = IP_TTL;

View File

@ -126,7 +126,7 @@ void udp_send(struct net_driver_s *dev, struct udp_conn_s *conn)
pudpbuf->ttl = conn->ttl;
net_ipaddr_copy(pudpbuf->srcipaddr, &dev->d_ipaddr);
net_ipaddr_copy(pudpbuf->destipaddr, &conn->ripaddr);
net_ipaddr_copy(pudpbuf->destipaddr, &conn->u.ipv4.raddr);
#else /* CONFIG_NET_IPv6 */
@ -143,7 +143,7 @@ void udp_send(struct net_driver_s *dev, struct udp_conn_s *conn)
pudpbuf->proto = IP_PROTO_UDP;
net_ipaddr_hdrcopy(pudpbuf->srcipaddr, &dev->d_ipaddr);
net_ipaddr_hdrcopy(pudpbuf->destipaddr, &conn->ripaddr);
net_ipaddr_hdrcopy(pudpbuf->destipaddr, &conn->u.ipv4.raddr);
/* Calculate IP checksum. */