diff options
Diffstat (limited to 'net/ipv6/addrlabel.c')
-rw-r--r-- | net/ipv6/addrlabel.c | 48 |
1 files changed, 23 insertions, 25 deletions
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index f083a583a05c..b30ad3741b46 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -251,38 +251,36 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net, | |||
251 | /* add a label */ | 251 | /* add a label */ |
252 | static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | 252 | static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) |
253 | { | 253 | { |
254 | struct hlist_node *n; | ||
255 | struct ip6addrlbl_entry *last = NULL, *p = NULL; | ||
254 | int ret = 0; | 256 | int ret = 0; |
255 | 257 | ||
256 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", | 258 | ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp, |
257 | __func__, | 259 | replace); |
258 | newp, replace); | ||
259 | 260 | ||
260 | if (hlist_empty(&ip6addrlbl_table.head)) { | 261 | hlist_for_each_entry_safe(p, n, &ip6addrlbl_table.head, list) { |
261 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | 262 | if (p->prefixlen == newp->prefixlen && |
262 | } else { | 263 | net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && |
263 | struct hlist_node *n; | 264 | p->ifindex == newp->ifindex && |
264 | struct ip6addrlbl_entry *p = NULL; | 265 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { |
265 | hlist_for_each_entry_safe(p, n, | 266 | if (!replace) { |
266 | &ip6addrlbl_table.head, list) { | 267 | ret = -EEXIST; |
267 | if (p->prefixlen == newp->prefixlen && | ||
268 | net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && | ||
269 | p->ifindex == newp->ifindex && | ||
270 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { | ||
271 | if (!replace) { | ||
272 | ret = -EEXIST; | ||
273 | goto out; | ||
274 | } | ||
275 | hlist_replace_rcu(&p->list, &newp->list); | ||
276 | ip6addrlbl_put(p); | ||
277 | goto out; | ||
278 | } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || | ||
279 | (p->prefixlen < newp->prefixlen)) { | ||
280 | hlist_add_before_rcu(&newp->list, &p->list); | ||
281 | goto out; | 268 | goto out; |
282 | } | 269 | } |
270 | hlist_replace_rcu(&p->list, &newp->list); | ||
271 | ip6addrlbl_put(p); | ||
272 | goto out; | ||
273 | } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || | ||
274 | (p->prefixlen < newp->prefixlen)) { | ||
275 | hlist_add_before_rcu(&newp->list, &p->list); | ||
276 | goto out; | ||
283 | } | 277 | } |
284 | hlist_add_after_rcu(&p->list, &newp->list); | 278 | last = p; |
285 | } | 279 | } |
280 | if (last) | ||
281 | hlist_add_after_rcu(&last->list, &newp->list); | ||
282 | else | ||
283 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | ||
286 | out: | 284 | out: |
287 | if (!ret) | 285 | if (!ret) |
288 | ip6addrlbl_table.seq++; | 286 | ip6addrlbl_table.seq++; |