ipv6: Fix source address with many addresses in same network
Previously ipv6 multi-address support decided packet source address based on its destination. This doesn't work if NuttX device has multiple addresses within same subnet. Instead when a packet is a response to existing connection, the source address should be based on the destination address used in the received packet.
This commit is contained in:
parent
73ceb049af
commit
c3a234fe99
|
@ -1062,11 +1062,19 @@ int netdev_ipv6_del(FAR struct net_driver_s *dev, const net_ipv6addr_t addr,
|
|||
* Name: netdev_ipv6_srcaddr/srcifaddr
|
||||
*
|
||||
* Description:
|
||||
* Get the source IPv6 address (RFC6724).
|
||||
* Get the source IPv6 address (RFC6724) to use for transmitted packets.
|
||||
* If we are responding to a received packet, use the destination address
|
||||
* from that packet. If we are initiating communication, pick a local
|
||||
* address that best matches the destination address.
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - Network device that packet is being transmitted from
|
||||
* dst - Address to compare against when choosing local address.
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the IPv6 address is returned on success. It will never be
|
||||
* NULL, but can be an address containing g_ipv6_unspecaddr.
|
||||
* A pointer to a net_ipv6addr_t contained in net_driver_s is returned on
|
||||
* success. It will never be NULL, but can be an address containing
|
||||
* g_ipv6_unspecaddr.
|
||||
*
|
||||
* Assumptions:
|
||||
* The caller has locked the network.
|
||||
|
|
|
@ -543,11 +543,13 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
|||
* ICMPv6 checksum before we return the packet.
|
||||
*/
|
||||
|
||||
FAR const uint16_t *srcaddr;
|
||||
|
||||
icmpv6->type = ICMPv6_ECHO_REPLY;
|
||||
|
||||
srcaddr = netdev_ipv6_srcaddr(dev, ipv6->destipaddr);
|
||||
net_ipv6addr_copy(ipv6->destipaddr, ipv6->srcipaddr);
|
||||
net_ipv6addr_copy(ipv6->srcipaddr,
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr));
|
||||
net_ipv6addr_copy(ipv6->srcipaddr, srcaddr);
|
||||
|
||||
icmpv6->chksum = 0;
|
||||
icmpv6->chksum = ~icmpv6_chksum(dev, iplen);
|
||||
|
|
|
@ -172,7 +172,7 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data)
|
|||
dev->d_len = ipicmplen + datalen;
|
||||
|
||||
ipv6_build_header(IPv6BUF, dev->d_len - IPv6_HDRLEN, IP_PROTO_ICMP6,
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr),
|
||||
netdev_ipv6_srcaddr(dev, ipv6->destipaddr),
|
||||
ipv6->srcipaddr, 255, 0);
|
||||
|
||||
/* Initialize the ICMPv6 header */
|
||||
|
|
|
@ -151,7 +151,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
|||
|
||||
outaddr->sin6_family = AF_INET6;
|
||||
net_ipv6addr_copy(outaddr->sin6_addr.in6_u.u6_addr8,
|
||||
netdev_ipv6_srcaddr(dev, *ripaddr));
|
||||
netdev_ipv6_srcaddr(dev, *lipaddr));
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
|
||||
net_unlock();
|
||||
|
|
|
@ -220,11 +220,19 @@ int netdev_ipv6_del(FAR struct net_driver_s *dev, const net_ipv6addr_t addr,
|
|||
* Name: netdev_ipv6_srcaddr/srcifaddr
|
||||
*
|
||||
* Description:
|
||||
* Get the source IPv6 address (RFC6724).
|
||||
* Get the source IPv6 address (RFC6724) to use for transmitted packets.
|
||||
* If we are responding to a received packet, use the destination address
|
||||
* from that packet. If we are initiating communication, pick a local
|
||||
* address that best matches the destination address.
|
||||
*
|
||||
* Input parameters:
|
||||
* dev - Network device that packet is being transmitted from
|
||||
* dst - Address to compare against when choosing local address.
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the IPv6 address is returned on success. It will never be
|
||||
* NULL, but can be an address containing g_ipv6_unspecaddr.
|
||||
* A pointer to a net_ipv6addr_t contained in net_driver_s is returned on
|
||||
* success. It will never be NULL, but can be an address containing
|
||||
* g_ipv6_unspecaddr.
|
||||
*
|
||||
* Assumptions:
|
||||
* The caller has locked the network.
|
||||
|
|
|
@ -182,7 +182,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
|
|||
ninfo("do IPv6 IP header build!\n");
|
||||
ipv6_build_header(IPv6BUF, dev->d_len - IPv6_HDRLEN,
|
||||
IP_PROTO_TCP,
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.raddr),
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.laddr),
|
||||
conn->u.ipv6.raddr,
|
||||
conn->sconn.ttl, conn->sconn.s_tclass);
|
||||
|
||||
|
@ -479,7 +479,7 @@ void tcp_reset(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
|
|||
|
||||
ipv6_build_header(ipv6, dev->d_len - IPv6_HDRLEN,
|
||||
IP_PROTO_TCP,
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr),
|
||||
netdev_ipv6_srcaddr(dev, ipv6->destipaddr),
|
||||
ipv6->srcipaddr,
|
||||
conn ? conn->sconn.ttl : IP_TTL_DEFAULT,
|
||||
conn ? conn->sconn.s_tos : 0);
|
||||
|
|
|
@ -149,7 +149,7 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
|
|||
dev->d_len = dev->d_sndlen + UDP_HDRLEN;
|
||||
|
||||
ipv6_build_header(IPv6BUF, dev->d_len, IP_PROTO_UDP,
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.raddr),
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.laddr),
|
||||
conn->u.ipv6.raddr,
|
||||
conn->sconn.ttl, conn->sconn.s_tclass);
|
||||
|
||||
|
|
Loading…
Reference in New Issue