aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-04-08 23:47:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-09 13:12:23 -0400
commit617fe29d45bdfffba2739e6512c83e766e6ae72c (patch)
tree8eb3d331f1c042893a990af3ee48e2aab4061fef /net/ipv6
parentfc403832f7bd94014fe3d965e0652a857160f1c9 (diff)
net: ipv6: only invalidate previously tokenized addresses
Instead of invalidating all IPv6 addresses with global scope when one decides to use IPv6 tokens, we should only invalidate previous tokens and leave the rest intact until they expire eventually (or are intact forever). For doing this less greedy approach, we're adding a bool at the end of inet6_ifaddr structure instead, for two reasons: i) per-inet6_ifaddr flag space is already used up, making it wider might not be a good idea, since ii) also we do not necessarily need to export this information into user space. Suggested-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 713ebe303f61..28b61e89bbb8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -878,6 +878,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
878 ifa->prefix_len = pfxlen; 878 ifa->prefix_len = pfxlen;
879 ifa->flags = flags | IFA_F_TENTATIVE; 879 ifa->flags = flags | IFA_F_TENTATIVE;
880 ifa->cstamp = ifa->tstamp = jiffies; 880 ifa->cstamp = ifa->tstamp = jiffies;
881 ifa->tokenized = false;
881 882
882 ifa->rt = rt; 883 ifa->rt = rt;
883 884
@@ -2134,6 +2135,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2134 struct inet6_ifaddr *ifp; 2135 struct inet6_ifaddr *ifp;
2135 struct in6_addr addr; 2136 struct in6_addr addr;
2136 int create = 0, update_lft = 0; 2137 int create = 0, update_lft = 0;
2138 bool tokenized = false;
2137 2139
2138 if (pinfo->prefix_len == 64) { 2140 if (pinfo->prefix_len == 64) {
2139 memcpy(&addr, &pinfo->prefix, 8); 2141 memcpy(&addr, &pinfo->prefix, 8);
@@ -2143,6 +2145,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2143 memcpy(addr.s6_addr + 8, 2145 memcpy(addr.s6_addr + 8,
2144 in6_dev->token.s6_addr + 8, 8); 2146 in6_dev->token.s6_addr + 8, 8);
2145 read_unlock_bh(&in6_dev->lock); 2147 read_unlock_bh(&in6_dev->lock);
2148 tokenized = true;
2146 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) && 2149 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
2147 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) { 2150 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
2148 in6_dev_put(in6_dev); 2151 in6_dev_put(in6_dev);
@@ -2185,6 +2188,7 @@ ok:
2185 2188
2186 update_lft = create = 1; 2189 update_lft = create = 1;
2187 ifp->cstamp = jiffies; 2190 ifp->cstamp = jiffies;
2191 ifp->tokenized = tokenized;
2188 addrconf_dad_start(ifp); 2192 addrconf_dad_start(ifp);
2189 } 2193 }
2190 2194
@@ -4339,8 +4343,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
4339 /* Well, that's kinda nasty ... */ 4343 /* Well, that's kinda nasty ... */
4340 list_for_each_entry(ifp, &idev->addr_list, if_list) { 4344 list_for_each_entry(ifp, &idev->addr_list, if_list) {
4341 spin_lock(&ifp->lock); 4345 spin_lock(&ifp->lock);
4342 if (ipv6_addr_src_scope(&ifp->addr) == 4346 if (ifp->tokenized) {
4343 IPV6_ADDR_SCOPE_GLOBAL) {
4344 ifp->valid_lft = 0; 4347 ifp->valid_lft = 0;
4345 ifp->prefered_lft = 0; 4348 ifp->prefered_lft = 0;
4346 } 4349 }