diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index cbfa19fb44..df9ecefc22 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -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 /**************************************************************************** diff --git a/net/devif/devif_loopback.c b/net/devif/devif_loopback.c index a7379aa4e5..6fa8e89adc 100644 --- a/net/devif/devif_loopback.c +++ b/net/devif/devif_loopback.c @@ -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; } diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c index 4565261c5d..b29daea10d 100644 --- a/net/devif/ipv6_input.c +++ b/net/devif/ipv6_input.c @@ -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; diff --git a/net/icmpv6/icmpv6.h b/net/icmpv6/icmpv6.h index c90c3722b1..ec11dbb0bb 100644 --- a/net/icmpv6/icmpv6.h +++ b/net/icmpv6/icmpv6.h @@ -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); /**************************************************************************** diff --git a/net/icmpv6/icmpv6_advertise.c b/net/icmpv6/icmpv6_advertise.c index 583522ac1b..8b27a8f012 100644 --- a/net/icmpv6/icmpv6_advertise.c +++ b/net/icmpv6/icmpv6_advertise.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_autoconfig.c b/net/icmpv6/icmpv6_autoconfig.c index dfc87e6777..ec8adecaad 100644 --- a/net/icmpv6/icmpv6_autoconfig.c +++ b/net/icmpv6/icmpv6_autoconfig.c @@ -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 diff --git a/net/icmpv6/icmpv6_input.c b/net/icmpv6/icmpv6_input.c index f072e70d3d..79339b3e3a 100644 --- a/net/icmpv6/icmpv6_input.c +++ b/net/icmpv6/icmpv6_input.c @@ -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); diff --git a/net/icmpv6/icmpv6_neighbor.c b/net/icmpv6/icmpv6_neighbor.c index c7274d4fa8..ac2c7b4a94 100644 --- a/net/icmpv6/icmpv6_neighbor.c +++ b/net/icmpv6/icmpv6_neighbor.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_radvertise.c b/net/icmpv6/icmpv6_radvertise.c index f8926403f2..52cb4864ed 100644 --- a/net/icmpv6/icmpv6_radvertise.c +++ b/net/icmpv6/icmpv6_radvertise.c @@ -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; diff --git a/net/icmpv6/icmpv6_reply.c b/net/icmpv6/icmpv6_reply.c index 9aa0745983..726b499ca4 100644 --- a/net/icmpv6/icmpv6_reply.c +++ b/net/icmpv6/icmpv6_reply.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_rnotify.c b/net/icmpv6/icmpv6_rnotify.c index fca0317750..9ea4a1683f 100644 --- a/net/icmpv6/icmpv6_rnotify.c +++ b/net/icmpv6/icmpv6_rnotify.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_rsolicit.c b/net/icmpv6/icmpv6_rsolicit.c index 40f7f024b5..ea26f4ccc0 100644 --- a/net/icmpv6/icmpv6_rsolicit.c +++ b/net/icmpv6/icmpv6_rsolicit.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_sendmsg.c b/net/icmpv6/icmpv6_sendmsg.c index e238e82fcb..7a73cab173 100644 --- a/net/icmpv6/icmpv6_sendmsg.c +++ b/net/icmpv6/icmpv6_sendmsg.c @@ -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 diff --git a/net/icmpv6/icmpv6_solicit.c b/net/icmpv6/icmpv6_solicit.c index 8519abd933..3c85d443d8 100644 --- a/net/icmpv6/icmpv6_solicit.c +++ b/net/icmpv6/icmpv6_solicit.c @@ -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 */ diff --git a/net/inet/ipv6_getsockname.c b/net/inet/ipv6_getsockname.c index 771b0046e1..7ea4667e91 100644 --- a/net/inet/ipv6_getsockname.c +++ b/net/inet/ipv6_getsockname.c @@ -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(); diff --git a/net/mld/mld_query.c b/net/mld/mld_query.c index fd144a4032..4014ab875a 100644 --- a/net/mld/mld_query.c +++ b/net/mld/mld_query.c @@ -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); diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c index 541156de60..a291b85d1d 100644 --- a/net/mld/mld_send.c +++ b/net/mld/mld_send.c @@ -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. * diff --git a/net/neighbor/neighbor_ethernet_out.c b/net/neighbor/neighbor_ethernet_out.c index ba6e462cb9..00b641e63a 100644 --- a/net/neighbor/neighbor_ethernet_out.c +++ b/net/neighbor/neighbor_ethernet_out.c @@ -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 */ diff --git a/net/neighbor/neighbor_lookup.c b/net/neighbor/neighbor_lookup.c index f6f3ce9fc0..e1e194f546 100644 --- a/net/neighbor/neighbor_lookup.c +++ b/net/neighbor/neighbor_lookup.c @@ -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; } diff --git a/net/netdev/netdev_findbyaddr.c b/net/netdev/netdev_findbyaddr.c index c89488bf09..35cb6c7054 100644 --- a/net/netdev/netdev_findbyaddr.c +++ b/net/netdev/netdev_findbyaddr.c @@ -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 */ diff --git a/net/netdev/netdev_ifconf.c b/net/netdev/netdev_ifconf.c index 323cc0811f..1e30f3c208 100644 --- a/net/netdev/netdev_ifconf.c +++ b/net/netdev/netdev_ifconf.c @@ -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: diff --git a/net/netlink/netlink_route.c b/net/netlink/netlink_route.c index 4409016da9..82192203ef 100644 --- a/net/netlink/netlink_route.c +++ b/net/netlink/netlink_route.c @@ -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) diff --git a/net/route/netdev_router.c b/net/route/netdev_router.c index cffd847a08..348e702281 100644 --- a/net/route/netdev_router.c +++ b/net/route/netdev_router.c @@ -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 */ diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index 3fd90d4a5f..e8f534c700 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -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", diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index 203e4561df..c28174c3ae 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -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", diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index 0b49c2682b..a31efb8aa5 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -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; } diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index 566a7b16da..8b721a2edf 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -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; diff --git a/net/tcp/tcp_connect.c b/net/tcp/tcp_connect.c index 1a78134c8c..1cbe5910f2 100644 --- a/net/tcp/tcp_connect.c +++ b/net/tcp/tcp_connect.c @@ -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 */ diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c index 7651839a46..025994e731 100644 --- a/net/tcp/tcp_send.c +++ b/net/tcp/tcp_send.c @@ -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; diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c index 2bb4f64b22..49fa9c3f54 100644 --- a/net/udp/udp_conn.c +++ b/net/udp/udp_conn.c @@ -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; diff --git a/net/udp/udp_send.c b/net/udp/udp_send.c index c3d5228f2e..b9c6d4d7e8 100644 --- a/net/udp/udp_send.c +++ b/net/udp/udp_send.c @@ -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