net: Support multiple IPv6 address per netdev
Note that user-space related code, like procfs and lifreq related ioctl commands, are not touched in this commit. Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
96233e0c42
commit
2b9633e652
@ -172,6 +172,13 @@
|
||||
# ifndef CONFIG_NETDEV_MAX_IPv6_ADDR
|
||||
# define CONFIG_NETDEV_MAX_IPv6_ADDR 1
|
||||
# endif
|
||||
# define NETDEV_HAS_V6ADDR(dev) \
|
||||
(!net_ipv6addr_cmp(netdev_ipv6_srcaddr(dev, g_ipv6_unspecaddr), \
|
||||
g_ipv6_unspecaddr))
|
||||
# define NETDEV_IS_MY_V6ADDR(dev,addr) \
|
||||
(netdev_ipv6_lookup(dev, addr, false) != NULL)
|
||||
# define NETDEV_V6ADDR_ONLINK(dev,addr) \
|
||||
(netdev_ipv6_lookup(dev, addr, true) != NULL)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -62,7 +62,7 @@ bool devif_is_loopback(FAR struct net_driver_s *dev)
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if ((IPv6BUF->vtc & IP_VERSION_MASK) == IPv6_VERSION &&
|
||||
net_ipv6addr_hdrcmp(IPv6BUF->destipaddr, dev->d_ipv6addr))
|
||||
NETDEV_IS_MY_V6ADDR(dev, IPv6BUF->destipaddr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ static int check_dev_destipaddr(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
* to this device.
|
||||
*/
|
||||
|
||||
if (net_ipv6addr_cmp(ipv6->destipaddr, dev->d_ipv6addr))
|
||||
if (NETDEV_IS_MY_V6ADDR(dev, ipv6->destipaddr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -389,7 +389,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
|
||||
* (the all zero address is the "unspecified" address.
|
||||
*/
|
||||
|
||||
if (net_ipv6addr_cmp(dev->d_ipv6addr, g_ipv6_unspecaddr))
|
||||
if (!NETDEV_HAS_V6ADDR(dev))
|
||||
{
|
||||
nwarn("WARNING: No IP address assigned\n");
|
||||
goto drop;
|
||||
|
@ -313,6 +313,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev);
|
||||
****************************************************************************/
|
||||
|
||||
void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t tgtaddr,
|
||||
const net_ipv6addr_t destipaddr);
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -65,6 +65,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t tgtaddr,
|
||||
const net_ipv6addr_t destipaddr)
|
||||
{
|
||||
FAR struct icmpv6_neighbor_advertise_s *adv;
|
||||
@ -77,7 +78,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
l3size = SIZEOF_ICMPV6_NEIGHBOR_ADVERTISE_S(lladdrsize);
|
||||
|
||||
ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6,
|
||||
dev->d_ipv6addr, destipaddr, 255, 0);
|
||||
tgtaddr, destipaddr, 255, 0);
|
||||
|
||||
/* Set up the ICMPv6 Neighbor Advertise response */
|
||||
|
||||
@ -92,7 +93,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Copy the target address into the Neighbor Advertisement message */
|
||||
|
||||
net_ipv6addr_copy(adv->tgtaddr, dev->d_ipv6addr);
|
||||
net_ipv6addr_copy(adv->tgtaddr, tgtaddr);
|
||||
|
||||
/* Set up the options */
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "netdev/netdev.h"
|
||||
#include "inet/inet.h"
|
||||
#include "icmpv6/icmpv6.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#ifdef CONFIG_NET_ICMPv6_AUTOCONF
|
||||
|
||||
@ -139,9 +140,11 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
|
||||
|
||||
if (state->snd_advertise)
|
||||
{
|
||||
/* Send the ICMPv6 Neighbor Advertisement message */
|
||||
/* Send the ICMPv6 Neighbor Advertisement message, we should
|
||||
* already have link-local address by previous logic.
|
||||
*/
|
||||
|
||||
icmpv6_advertise(dev, g_ipv6_allnodes);
|
||||
icmpv6_advertise(dev, netdev_ipv6_lladdr(dev), g_ipv6_allnodes);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -311,6 +314,11 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
|
||||
* will be derived from the link layer (MAC) address.
|
||||
*/
|
||||
|
||||
if (netdev_ipv6_lladdr(dev) != NULL)
|
||||
{
|
||||
goto got_lladdr;
|
||||
}
|
||||
|
||||
icmpv6_linkipaddr(dev, lladdr);
|
||||
|
||||
ninfo("lladdr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
@ -352,8 +360,13 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
|
||||
* on the wider Internet (since link-local addresses are not routed).
|
||||
*/
|
||||
|
||||
net_ipv6addr_copy(dev->d_ipv6addr, lladdr);
|
||||
ret = netdev_ipv6_add(dev, lladdr, net_ipv6_mask2pref(g_ipv6_llnetmask));
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
got_lladdr:
|
||||
/* 4. Router Contact: The node next attempts to contact a local router for
|
||||
* more information on continuing the configuration. This is done either
|
||||
* by listening for Router Advertisement messages sent periodically by
|
||||
@ -416,10 +429,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
|
||||
/* No off-link communications; No router address. */
|
||||
|
||||
net_ipv6addr_copy(dev->d_ipv6draddr, g_ipv6_unspecaddr);
|
||||
|
||||
/* Set a netmask for the local link address */
|
||||
|
||||
net_ipv6addr_copy(dev->d_ipv6netmask, g_ipv6_llnetmask);
|
||||
}
|
||||
|
||||
/* 5. Router Direction: The router provides direction to the node on how
|
||||
|
@ -299,7 +299,7 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
/* Check if we are the target of the solicitation */
|
||||
|
||||
sol = ICMPv6SOLICIT;
|
||||
if (net_ipv6addr_cmp(sol->tgtaddr, dev->d_ipv6addr))
|
||||
if (NETDEV_IS_MY_V6ADDR(dev, sol->tgtaddr))
|
||||
{
|
||||
if (sol->opttype == ICMPv6_OPT_SRCLLADDR)
|
||||
{
|
||||
@ -312,7 +312,7 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
* solicitation came from.
|
||||
*/
|
||||
|
||||
icmpv6_advertise(dev, ipv6->srcipaddr);
|
||||
icmpv6_advertise(dev, sol->tgtaddr, ipv6->srcipaddr);
|
||||
|
||||
/* All statistics have been updated. Nothing to do but exit. */
|
||||
|
||||
@ -341,7 +341,7 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
*/
|
||||
|
||||
adv = ICMPv6ADVERTISE;
|
||||
if (net_ipv6addr_cmp(ipv6->destipaddr, dev->d_ipv6addr))
|
||||
if (NETDEV_IS_MY_V6ADDR(dev, ipv6->destipaddr))
|
||||
{
|
||||
/* This message is required to support the Target link-layer
|
||||
* address option.
|
||||
@ -544,7 +544,8 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
icmpv6->type = ICMPv6_ECHO_REPLY;
|
||||
|
||||
net_ipv6addr_copy(ipv6->destipaddr, ipv6->srcipaddr);
|
||||
net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr);
|
||||
net_ipv6addr_copy(ipv6->srcipaddr,
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr));
|
||||
|
||||
icmpv6->chksum = 0;
|
||||
icmpv6->chksum = ~icmpv6_chksum(dev, iplen);
|
||||
|
@ -218,8 +218,7 @@ int icmpv6_neighbor(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Check if the destination address is on the local network. */
|
||||
|
||||
if (net_ipv6addr_maskcmp(ipaddr, dev->d_ipv6addr, dev->d_ipv6netmask) ||
|
||||
net_is_addr_linklocal(ipaddr))
|
||||
if (NETDEV_V6ADDR_ONLINK(dev, ipaddr) || net_is_addr_linklocal(ipaddr))
|
||||
{
|
||||
/* Yes.. use the input address for the lookup */
|
||||
|
||||
|
@ -170,6 +170,9 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
|
||||
FAR struct icmpv6_srclladdr_s *srcaddr;
|
||||
FAR struct icmpv6_mtu_s *mtu;
|
||||
FAR struct icmpv6_prefixinfo_s *prefix;
|
||||
#ifndef CONFIG_NET_ICMPv6_ROUTER_MANUAL
|
||||
FAR const struct netdev_ifaddr6_s *ifaddr;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_ICMPv6_ROUTER_RDNSS
|
||||
FAR struct icmpv6_rdnss_s *rdnss;
|
||||
struct rdnss_add_dns_nameserver_s rndss_context;
|
||||
@ -183,12 +186,18 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
|
||||
lladdrsize = netdev_lladdrsize(dev);
|
||||
l3size = sizeof(struct icmpv6_router_advertise_s) +
|
||||
SIZEOF_ICMPV6_SRCLLADDR_S(lladdrsize) +
|
||||
sizeof(struct icmpv6_mtu_s) +
|
||||
sizeof(struct icmpv6_prefixinfo_s);
|
||||
sizeof(struct icmpv6_mtu_s);
|
||||
|
||||
/* Source IP address must be set to link-local IP */
|
||||
|
||||
icmpv6_linkipaddr(dev, srcv6addr);
|
||||
if (netdev_ipv6_lladdr(dev) == NULL)
|
||||
{
|
||||
icmpv6_linkipaddr(dev, srcv6addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
net_ipv6addr_copy(srcv6addr, netdev_ipv6_lladdr(dev));
|
||||
}
|
||||
|
||||
/* Set up the ICMPv6 Router Advertise response */
|
||||
|
||||
@ -224,6 +233,16 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
|
||||
mtu->mtu[0] = 0;
|
||||
mtu->mtu[1] = HTONS(dev->d_pktsize - dev->d_llhdrlen);
|
||||
|
||||
#ifndef CONFIG_NET_ICMPv6_ROUTER_MANUAL
|
||||
/* We only anounce a prefix when we have one. */
|
||||
|
||||
ifaddr = netdev_ipv6_srcifaddr(dev, g_ipv6_unspecaddr);
|
||||
if (net_ipv6addr_cmp(ifaddr->addr, g_ipv6_unspecaddr))
|
||||
{
|
||||
goto skip_prefix;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set up the prefix option */
|
||||
|
||||
prefix = (FAR struct icmpv6_prefixinfo_s *)
|
||||
@ -238,6 +257,8 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
|
||||
prefix->reserved[0] = 0;
|
||||
prefix->reserved[1] = 0;
|
||||
|
||||
l3size += sizeof(struct icmpv6_prefixinfo_s);
|
||||
|
||||
#ifdef CONFIG_NET_ICMPv6_ROUTER_MANUAL
|
||||
/* Copy the configured prefex */
|
||||
|
||||
@ -246,14 +267,14 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
|
||||
#else
|
||||
/* Set the prefix and prefix length based on net driver IP and netmask */
|
||||
|
||||
prefix->preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
||||
ipv6addr_mask(prefix->prefix, dev->d_ipv6addr, dev->d_ipv6netmask);
|
||||
prefix->preflen = net_ipv6_mask2pref(ifaddr->mask);
|
||||
ipv6addr_mask(prefix->prefix, ifaddr->addr, ifaddr->mask);
|
||||
skip_prefix:
|
||||
#endif /* CONFIG_NET_ICMPv6_ROUTER_MANUAL */
|
||||
|
||||
#ifdef CONFIG_NET_ICMPv6_ROUTER_RDNSS
|
||||
rdnss = (FAR struct icmpv6_rdnss_s *)
|
||||
((FAR uint8_t *)prefix +
|
||||
sizeof(struct icmpv6_prefixinfo_s));
|
||||
((FAR uint8_t *)adv + l3size);
|
||||
rndss_context.rdnss = rdnss;
|
||||
rndss_context.nservers = 0;
|
||||
|
||||
|
@ -172,7 +172,8 @@ 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,
|
||||
dev->d_ipv6addr, ipv6->srcipaddr, 255, 0);
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr),
|
||||
ipv6->srcipaddr, 255, 0);
|
||||
|
||||
/* Initialize the ICMPv6 header */
|
||||
|
||||
|
@ -75,6 +75,9 @@ void icmpv6_setaddresses(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t prefix,
|
||||
unsigned int preflen)
|
||||
{
|
||||
FAR const uint16_t *curaddr;
|
||||
net_ipv6addr_t addr;
|
||||
net_ipv6addr_t mask;
|
||||
unsigned int i;
|
||||
|
||||
/* Lock the network.
|
||||
@ -100,20 +103,28 @@ void icmpv6_setaddresses(FAR struct net_driver_s *dev,
|
||||
preflen = 128;
|
||||
}
|
||||
|
||||
net_ipv6_pref2mask(preflen, dev->d_ipv6netmask);
|
||||
net_ipv6_pref2mask(preflen, mask);
|
||||
|
||||
ninfo("preflen=%d netmask=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
preflen, NTOHS(dev->d_ipv6netmask[0]), NTOHS(dev->d_ipv6netmask[1]),
|
||||
NTOHS(dev->d_ipv6netmask[2]), NTOHS(dev->d_ipv6netmask[3]),
|
||||
NTOHS(dev->d_ipv6netmask[4]), NTOHS(dev->d_ipv6netmask[5]),
|
||||
NTOHS(dev->d_ipv6netmask[6]), NTOHS(dev->d_ipv6netmask[7]));
|
||||
preflen,
|
||||
NTOHS(mask[0]), NTOHS(mask[1]), NTOHS(mask[2]), NTOHS(mask[3]),
|
||||
NTOHS(mask[4]), NTOHS(mask[5]), NTOHS(mask[6]), NTOHS(mask[7]));
|
||||
|
||||
/* Copy prefix to the current IPv6 address, applying the mask */
|
||||
/* Copy prefix to the current link local address, applying the mask.
|
||||
* According to RFC4862, Section 5.5.3, Page 18, global address is formed
|
||||
* by prefix + IID, and the IID is normally the link-local suffix.
|
||||
*/
|
||||
|
||||
curaddr = netdev_ipv6_lladdr(dev);
|
||||
if (curaddr == NULL)
|
||||
{
|
||||
icmpv6_linkipaddr(dev, addr);
|
||||
curaddr = addr;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
dev->d_ipv6addr[i] = (dev->d_ipv6addr[i] & ~dev->d_ipv6netmask[i]) |
|
||||
(prefix[i] & dev->d_ipv6netmask[i]);
|
||||
addr[i] = (curaddr[i] & ~mask[i]) | (prefix[i] & mask[i]);
|
||||
}
|
||||
|
||||
ninfo("prefix=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
@ -121,10 +132,10 @@ void icmpv6_setaddresses(FAR struct net_driver_s *dev,
|
||||
NTOHS(prefix[3]), NTOHS(prefix[4]), NTOHS(prefix[5]),
|
||||
NTOHS(prefix[6]), NTOHS(prefix[7]));
|
||||
ninfo("IP address=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
||||
NTOHS(dev->d_ipv6addr[0]), NTOHS(dev->d_ipv6addr[1]),
|
||||
NTOHS(dev->d_ipv6addr[2]), NTOHS(dev->d_ipv6addr[3]),
|
||||
NTOHS(dev->d_ipv6addr[4]), NTOHS(dev->d_ipv6addr[5]),
|
||||
NTOHS(dev->d_ipv6addr[6]), NTOHS(dev->d_ipv6addr[7]));
|
||||
NTOHS(addr[0]), NTOHS(addr[1]), NTOHS(addr[2]), NTOHS(addr[3]),
|
||||
NTOHS(addr[4]), NTOHS(addr[5]), NTOHS(addr[6]), NTOHS(addr[7]));
|
||||
|
||||
netdev_ipv6_add(dev, addr, preflen);
|
||||
|
||||
/* Finally, copy the router address */
|
||||
|
||||
|
@ -76,7 +76,8 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
|
||||
l3size = SIZEOF_ICMPV6_ROUTER_SOLICIT_S(lladdrsize);
|
||||
|
||||
ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6,
|
||||
dev->d_ipv6addr, g_ipv6_allrouters, 255, 0);
|
||||
netdev_ipv6_srcaddr(dev, g_ipv6_allrouters),
|
||||
g_ipv6_allrouters, 255, 0);
|
||||
|
||||
/* Set up the ICMPv6 Router Solicitation message */
|
||||
|
||||
|
@ -115,7 +115,8 @@ static void sendto_request(FAR struct net_driver_s *dev,
|
||||
dev->d_len = IPv6_HDRLEN + pstate->snd_buflen;
|
||||
|
||||
ipv6_build_header(IPv6BUF, pstate->snd_buflen, IP_PROTO_ICMP6,
|
||||
dev->d_ipv6addr, pstate->snd_toaddr.s6_addr16, 255, 0);
|
||||
netdev_ipv6_srcaddr(dev, pstate->snd_toaddr.s6_addr16),
|
||||
pstate->snd_toaddr.s6_addr16, 255, 0);
|
||||
|
||||
/* Copy the ICMPv6 request and payload into place after the IPv6 header */
|
||||
|
||||
@ -405,8 +406,7 @@ ssize_t icmpv6_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
|
||||
* destination device.
|
||||
*/
|
||||
|
||||
if (!net_ipv6addr_maskcmp(state.snd_toaddr.s6_addr16,
|
||||
dev->d_ipv6addr, dev->d_ipv6netmask))
|
||||
if (!NETDEV_V6ADDR_ONLINK(dev, state.snd_toaddr.s6_addr16))
|
||||
{
|
||||
/* Destination address was not on the local network served
|
||||
* by this device. If a timeout occurs, then the most
|
||||
|
@ -95,7 +95,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
|
||||
dstaddr[7] = ipaddr[7];
|
||||
|
||||
ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6,
|
||||
dev->d_ipv6addr, dstaddr, 255, 0);
|
||||
netdev_ipv6_srcaddr(dev, ipaddr), dstaddr, 255, 0);
|
||||
|
||||
/* Set up the ICMPv6 Neighbor Solicitation message */
|
||||
|
||||
|
@ -150,7 +150,8 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
||||
/* Set the address family and the IP address */
|
||||
|
||||
outaddr->sin6_family = AF_INET6;
|
||||
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipv6addr, 16);
|
||||
net_ipv6addr_copy(outaddr->sin6_addr.in6_u.u6_addr8,
|
||||
netdev_ipv6_srcaddr(dev, *ripaddr));
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
|
||||
net_unlock();
|
||||
|
@ -139,11 +139,21 @@ static clock_t mld_mrc2mrd(uint16_t mrc)
|
||||
static bool mld_cmpaddr(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t srcaddr)
|
||||
{
|
||||
FAR const uint16_t *lladdr = netdev_ipv6_lladdr(dev);
|
||||
int i;
|
||||
|
||||
if (lladdr == NULL)
|
||||
{
|
||||
/* If no link-local address presents, regard address as ::, then nobody
|
||||
* can be less than it.
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (srcaddr[i] < dev->d_ipv6addr[i])
|
||||
if (srcaddr[i] < lladdr[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -439,7 +449,7 @@ int mld_query(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Not sent to all systems. Check for Unicast General Query */
|
||||
|
||||
else if (net_ipv6addr_cmp(ipv6->destipaddr, dev->d_ipv6addr))
|
||||
else if (NETDEV_IS_MY_V6ADDR(dev, ipv6->destipaddr))
|
||||
{
|
||||
mldinfo("Unicast query\n");
|
||||
MLD_STATINCR(g_netstats.mld.ucast_query_received);
|
||||
|
@ -89,6 +89,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
||||
{
|
||||
FAR struct ipv6_router_alert_s *ra;
|
||||
FAR const uint16_t *destipaddr;
|
||||
FAR const uint16_t *srcipaddr;
|
||||
unsigned int mldsize;
|
||||
|
||||
/* Only a general query message can have a NULL group */
|
||||
@ -210,8 +211,18 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
||||
NTOHS(destipaddr[3]), NTOHS(destipaddr[4]), NTOHS(destipaddr[5]),
|
||||
NTOHS(destipaddr[6]), NTOHS(destipaddr[7]));
|
||||
|
||||
srcipaddr = netdev_ipv6_lladdr(dev);
|
||||
if (srcipaddr == NULL)
|
||||
{
|
||||
/* Unspecified address is used when link-local address is not
|
||||
* available, as described in RFC 3590, Section 4, Page 2.
|
||||
*/
|
||||
|
||||
srcipaddr = g_ipv6_unspecaddr;
|
||||
}
|
||||
|
||||
ipv6_build_header(IPv6BUF, dev->d_sndlen, NEXT_HOPBYBOT_EH,
|
||||
dev->d_ipv6addr, destipaddr, MLD_TTL, 0);
|
||||
srcipaddr, destipaddr, MLD_TTL, 0);
|
||||
|
||||
/* Add the router alert IP header option.
|
||||
*
|
||||
|
@ -126,8 +126,7 @@ void neighbor_ethernet_out(FAR struct net_driver_s *dev)
|
||||
|
||||
/* Check if the destination address is on the local network. */
|
||||
|
||||
if (!net_ipv6addr_maskcmp(ip->destipaddr, dev->d_ipv6addr,
|
||||
dev->d_ipv6netmask))
|
||||
if (!NETDEV_V6ADDR_ONLINK(dev, ip->destipaddr))
|
||||
{
|
||||
/* Destination address is not on the local network */
|
||||
|
||||
|
@ -66,7 +66,7 @@ static int neighbor_match(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
* lookup.
|
||||
*/
|
||||
|
||||
if (!net_ipv6addr_cmp(dev->d_ipv6addr, info->ni_ipaddr))
|
||||
if (!NETDEV_IS_MY_V6ADDR(dev, info->ni_ipaddr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,13 +126,11 @@ FAR struct net_driver_s *netdev_findby_lipv6addr(
|
||||
{
|
||||
/* Is the interface in the "up" state? */
|
||||
|
||||
if ((dev->d_flags & IFF_UP) != 0 &&
|
||||
!net_ipv6addr_cmp(dev->d_ipv6addr, g_ipv6_unspecaddr))
|
||||
if ((dev->d_flags & IFF_UP) != 0 && NETDEV_HAS_V6ADDR(dev))
|
||||
{
|
||||
/* Yes.. check for an address match (under the netmask) */
|
||||
|
||||
if (net_ipv6addr_maskcmp(dev->d_ipv6addr, lipaddr,
|
||||
dev->d_ipv6netmask))
|
||||
if (NETDEV_V6ADDR_ONLINK(dev, lipaddr))
|
||||
{
|
||||
/* Its a match */
|
||||
|
||||
|
@ -169,8 +169,7 @@ static int ifconf_ipv6_callback(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
* state.
|
||||
*/
|
||||
|
||||
if (!net_ipv6addr_cmp(dev->d_ipv6addr, g_ipv6_unspecaddr) &&
|
||||
(dev->d_flags & IFF_UP) != 0)
|
||||
if (NETDEV_HAS_V6ADDR(dev) && IFF_IS_UP(dev->d_flags))
|
||||
{
|
||||
/* Check if we would exceed the buffer space provided by the caller.
|
||||
* NOTE: A common usage model is:
|
||||
|
@ -989,14 +989,16 @@ static int netlink_new_ipv6addr(NETLINK_HANDLE handle,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memcpy(dev->d_ipv6addr, nla_data(tb[IFA_LOCAL]), 16);
|
||||
net_ipv6_pref2mask(ifm->ifa_prefixlen, dev->d_ipv6netmask);
|
||||
ret = netdev_ipv6_add(dev, nla_data(tb[IFA_LOCAL]), ifm->ifa_prefixlen);
|
||||
if (ret == OK)
|
||||
{
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6,
|
||||
nla_data(tb[IFA_LOCAL]), ifm->ifa_prefixlen);
|
||||
}
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_NEWADDR, AF_INET6, dev->d_ipv6addr,
|
||||
ifm->ifa_prefixlen);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1075,6 +1077,11 @@ static int netlink_del_ipv6addr(NETLINK_HANDLE handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!tb[IFA_LOCAL] || ifm->ifa_prefixlen > 128)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
net_lock();
|
||||
dev = netdev_findbyindex(ifm->ifa_index);
|
||||
|
||||
@ -1084,20 +1091,22 @@ static int netlink_del_ipv6addr(NETLINK_HANDLE handle,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (tb[IFA_LOCAL] && !net_ipv6addr_cmp(dev->d_ipv6addr,
|
||||
nla_data(tb[IFA_LOCAL])))
|
||||
if (!NETDEV_IS_MY_V6ADDR(dev, nla_data(tb[IFA_LOCAL])))
|
||||
{
|
||||
net_unlock();
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6, dev->d_ipv6addr,
|
||||
net_ipv6_mask2pref(dev->d_ipv6netmask));
|
||||
memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
|
||||
ret = netdev_ipv6_del(dev, nla_data(tb[IFA_LOCAL]), ifm->ifa_prefixlen);
|
||||
if (ret == OK)
|
||||
{
|
||||
netlink_device_notify_ipaddr(dev, RTM_DELADDR, AF_INET6,
|
||||
nla_data(tb[IFA_LOCAL]), ifm->ifa_prefixlen);
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1110,36 +1119,16 @@ static int netlink_del_ipv6addr(NETLINK_HANDLE handle,
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NETLINK_DISABLE_GETADDR
|
||||
static int netlink_addr_callback(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static int netlink_ipv6_addr_callback(FAR struct net_driver_s *dev,
|
||||
FAR struct netdev_ifaddr6_s *addr,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct nlroute_info_s *info = arg;
|
||||
FAR struct netlink_response_s *resp;
|
||||
FAR void *addr = NULL;
|
||||
uint8_t preflen;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (info->req->gen.rtgen_family == AF_INET)
|
||||
{
|
||||
addr = &dev->d_ipaddr;
|
||||
preflen = net_ipv4_mask2pref(dev->d_netmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (info->req->gen.rtgen_family == AF_INET6)
|
||||
{
|
||||
addr = &dev->d_ipv6addr;
|
||||
preflen = net_ipv6_mask2pref(dev->d_ipv6netmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
resp = netlink_get_ifaddr(dev, info->req->gen.rtgen_family, RTM_NEWADDR,
|
||||
addr, preflen, info->req);
|
||||
resp = netlink_get_ifaddr(dev, AF_INET6, RTM_NEWADDR, addr->addr,
|
||||
net_ipv6_mask2pref(addr->mask), info->req);
|
||||
if (resp == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
@ -1148,6 +1137,37 @@ static int netlink_addr_callback(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
netlink_add_response(info->handle, resp);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int netlink_addr_callback(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
{
|
||||
FAR struct nlroute_info_s *info = arg;
|
||||
FAR struct netlink_response_s *resp;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (info->req->gen.rtgen_family == AF_INET)
|
||||
{
|
||||
resp = netlink_get_ifaddr(dev, AF_INET, RTM_NEWADDR, &dev->d_ipaddr,
|
||||
net_ipv4_mask2pref(dev->d_netmask),
|
||||
info->req);
|
||||
if (resp == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
netlink_add_response(info->handle, resp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (info->req->gen.rtgen_family == AF_INET6)
|
||||
{
|
||||
return netdev_ipv6_foreach(dev, netlink_ipv6_addr_callback, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int netlink_get_addr(NETLINK_HANDLE handle,
|
||||
FAR const struct nlroute_sendto_request_s *req)
|
||||
|
@ -167,8 +167,7 @@ static int net_ipv6_devmatch(FAR struct net_route_ipv6_s *route,
|
||||
*/
|
||||
|
||||
if (net_ipv6addr_maskcmp(route->target, match->target, route->netmask) &&
|
||||
net_ipv6addr_maskcmp(route->router, dev->d_ipv6addr,
|
||||
dev->d_ipv6netmask))
|
||||
NETDEV_V6ADDR_ONLINK(dev, route->router))
|
||||
{
|
||||
#ifdef CONFIG_ROUTE_IPv6_CACHEROUTE
|
||||
/* They match.. Copy the entire routing table entry */
|
||||
|
@ -213,7 +213,8 @@ static int sixlowpan_tcp_header(FAR struct tcp_conn_s *conn,
|
||||
}
|
||||
else
|
||||
{
|
||||
net_ipv6addr_hdrcopy(ipv6tcp->ipv6.srcipaddr, dev->d_ipv6addr);
|
||||
net_ipv6addr_hdrcopy(ipv6tcp->ipv6.srcipaddr,
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.raddr));
|
||||
}
|
||||
|
||||
ninfo("IPv6 length: %d\n",
|
||||
|
@ -247,7 +247,8 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
|
||||
}
|
||||
else
|
||||
{
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr, dev->d_ipv6addr);
|
||||
net_ipv6addr_hdrcopy(ipv6udp.ipv6.srcipaddr,
|
||||
netdev_ipv6_srcaddr(dev, ipv6udp.ipv6.destipaddr));
|
||||
}
|
||||
|
||||
ninfo("IPv6 length: %d\n",
|
||||
|
@ -319,8 +319,7 @@ int sixlowpan_destaddrfromip(FAR struct radio_driver_s *radio,
|
||||
*/
|
||||
|
||||
if (!sixlowpan_islinklocal(ipaddr) &&
|
||||
!net_ipv6addr_maskcmp(radio->r_dev.d_ipv6addr, ipaddr,
|
||||
radio->r_dev.d_ipv6netmask))
|
||||
!NETDEV_V6ADDR_ONLINK(&radio->r_dev, ipaddr))
|
||||
{
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
@ -440,8 +440,7 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn,
|
||||
|
||||
for (dev = g_netdevices; dev; dev = dev->flink)
|
||||
{
|
||||
if (net_ipv6addr_cmp(addr->sin6_addr.in6_u.u6_addr16,
|
||||
dev->d_ipv6addr))
|
||||
if (NETDEV_IS_MY_V6ADDR(dev, addr->sin6_addr.in6_u.u6_addr16))
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -322,7 +322,8 @@ int psock_tcp_connect(FAR struct socket *psock,
|
||||
#endif
|
||||
if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
|
||||
{
|
||||
net_ipv6addr_copy(conn->u.ipv6.laddr, conn->dev->d_ipv6addr);
|
||||
net_ipv6addr_copy(conn->u.ipv6.laddr,
|
||||
netdev_ipv6_srcaddr(conn->dev, conn->u.ipv6.raddr));
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
|
@ -181,7 +181,9 @@ 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, dev->d_ipv6addr, conn->u.ipv6.raddr,
|
||||
IP_PROTO_TCP,
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.raddr),
|
||||
conn->u.ipv6.raddr,
|
||||
conn->sconn.ttl, conn->sconn.s_tclass);
|
||||
|
||||
/* Calculate TCP checksum. */
|
||||
@ -476,7 +478,9 @@ void tcp_reset(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
|
||||
ipv6_build_header(ipv6, dev->d_len - IPv6_HDRLEN,
|
||||
IP_PROTO_TCP, dev->d_ipv6addr, ipv6->srcipaddr,
|
||||
IP_PROTO_TCP,
|
||||
netdev_ipv6_srcaddr(dev, ipv6->srcipaddr),
|
||||
ipv6->srcipaddr,
|
||||
conn ? conn->sconn.ttl : IP_TTL_DEFAULT,
|
||||
conn ? conn->sconn.s_tos : 0);
|
||||
tcp->tcpchksum = 0;
|
||||
|
@ -882,8 +882,8 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
|
||||
for (dev = g_netdevices; dev; dev = dev->flink)
|
||||
{
|
||||
if (net_ipv6addr_cmp(inaddr->sin6_addr.in6_u.u6_addr16,
|
||||
dev->d_ipv6addr))
|
||||
if (NETDEV_IS_MY_V6ADDR(dev,
|
||||
inaddr->sin6_addr.in6_u.u6_addr16))
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -149,7 +149,8 @@ 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,
|
||||
dev->d_ipv6addr, conn->u.ipv6.raddr,
|
||||
netdev_ipv6_srcaddr(dev, conn->u.ipv6.raddr),
|
||||
conn->u.ipv6.raddr,
|
||||
conn->sconn.ttl, conn->sconn.s_tclass);
|
||||
|
||||
/* The total length to send is the size of the application data
|
||||
|
Loading…
Reference in New Issue
Block a user