diff options
| author | Steve French <sfrench@us.ibm.com> | 2005-12-31 13:27:22 -0500 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2005-12-31 13:27:22 -0500 |
| commit | eea60caef610c7a6c58c0de9c80ae1e438e01301 (patch) | |
| tree | 25e19289bba003fe085e589430d0d981fd6b73a7 /net/ipv6 | |
| parent | da8543ef125afc7bba4da526b61a1ae07dc25109 (diff) | |
| parent | 82c9df820112c6286a8e8fbe482e94b65b49062c (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 137 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 16 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 142 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Kconfig | 2 | ||||
| -rw-r--r-- | net/ipv6/route.c | 15 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_policy.c | 1 |
6 files changed, 254 insertions, 59 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 76ff9f4fe89d..a60585fd85ad 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -137,6 +137,7 @@ static int addrconf_ifdown(struct net_device *dev, int how); | |||
| 137 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 137 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
| 138 | static void addrconf_dad_timer(unsigned long data); | 138 | static void addrconf_dad_timer(unsigned long data); |
| 139 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | 139 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); |
| 140 | static void addrconf_dad_run(struct inet6_dev *idev); | ||
| 140 | static void addrconf_rs_timer(unsigned long data); | 141 | static void addrconf_rs_timer(unsigned long data); |
| 141 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 142 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); |
| 142 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 143 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); |
| @@ -379,8 +380,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 379 | dev->type == ARPHRD_NONE || | 380 | dev->type == ARPHRD_NONE || |
| 380 | dev->type == ARPHRD_SIT) { | 381 | dev->type == ARPHRD_SIT) { |
| 381 | printk(KERN_INFO | 382 | printk(KERN_INFO |
| 382 | "Disabled Privacy Extensions on device %p(%s)\n", | 383 | "%s: Disabled Privacy Extensions\n", |
| 383 | dev, dev->name); | 384 | dev->name); |
| 384 | ndev->cnf.use_tempaddr = -1; | 385 | ndev->cnf.use_tempaddr = -1; |
| 385 | } else { | 386 | } else { |
| 386 | in6_dev_hold(ndev); | 387 | in6_dev_hold(ndev); |
| @@ -388,6 +389,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 388 | } | 389 | } |
| 389 | #endif | 390 | #endif |
| 390 | 391 | ||
| 392 | if (netif_carrier_ok(dev)) | ||
| 393 | ndev->if_flags |= IF_READY; | ||
| 394 | |||
| 391 | write_lock_bh(&addrconf_lock); | 395 | write_lock_bh(&addrconf_lock); |
| 392 | dev->ip6_ptr = ndev; | 396 | dev->ip6_ptr = ndev; |
| 393 | write_unlock_bh(&addrconf_lock); | 397 | write_unlock_bh(&addrconf_lock); |
| @@ -415,6 +419,7 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
| 415 | if ((idev = ipv6_add_dev(dev)) == NULL) | 419 | if ((idev = ipv6_add_dev(dev)) == NULL) |
| 416 | return NULL; | 420 | return NULL; |
| 417 | } | 421 | } |
| 422 | |||
| 418 | if (dev->flags&IFF_UP) | 423 | if (dev->flags&IFF_UP) |
| 419 | ipv6_mc_up(idev); | 424 | ipv6_mc_up(idev); |
| 420 | return idev; | 425 | return idev; |
| @@ -634,8 +639,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 634 | } | 639 | } |
| 635 | #endif | 640 | #endif |
| 636 | 641 | ||
| 637 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL; | 642 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { |
| 638 | ifap = &ifa->if_next) { | ||
| 639 | if (ifa == ifp) { | 643 | if (ifa == ifp) { |
| 640 | *ifap = ifa->if_next; | 644 | *ifap = ifa->if_next; |
| 641 | __in6_ifa_put(ifp); | 645 | __in6_ifa_put(ifp); |
| @@ -643,6 +647,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 643 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 647 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
| 644 | break; | 648 | break; |
| 645 | deleted = 1; | 649 | deleted = 1; |
| 650 | continue; | ||
| 646 | } else if (ifp->flags & IFA_F_PERMANENT) { | 651 | } else if (ifp->flags & IFA_F_PERMANENT) { |
| 647 | if (ipv6_prefix_equal(&ifa->addr, &ifp->addr, | 652 | if (ipv6_prefix_equal(&ifa->addr, &ifp->addr, |
| 648 | ifp->prefix_len)) { | 653 | ifp->prefix_len)) { |
| @@ -666,6 +671,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 666 | } | 671 | } |
| 667 | } | 672 | } |
| 668 | } | 673 | } |
| 674 | ifap = &ifa->if_next; | ||
| 669 | } | 675 | } |
| 670 | write_unlock_bh(&idev->lock); | 676 | write_unlock_bh(&idev->lock); |
| 671 | 677 | ||
| @@ -903,11 +909,18 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 903 | 909 | ||
| 904 | score.addr_type = __ipv6_addr_type(&ifa->addr); | 910 | score.addr_type = __ipv6_addr_type(&ifa->addr); |
| 905 | 911 | ||
| 906 | /* Rule 0: Candidate Source Address (section 4) | 912 | /* Rule 0: |
| 913 | * - Tentative Address (RFC2462 section 5.4) | ||
| 914 | * - A tentative address is not considered | ||
| 915 | * "assigned to an interface" in the traditional | ||
| 916 | * sense. | ||
| 917 | * - Candidate Source Address (section 4) | ||
| 907 | * - In any case, anycast addresses, multicast | 918 | * - In any case, anycast addresses, multicast |
| 908 | * addresses, and the unspecified address MUST | 919 | * addresses, and the unspecified address MUST |
| 909 | * NOT be included in a candidate set. | 920 | * NOT be included in a candidate set. |
| 910 | */ | 921 | */ |
| 922 | if (ifa->flags & IFA_F_TENTATIVE) | ||
| 923 | continue; | ||
| 911 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 924 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || |
| 912 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 925 | score.addr_type & IPV6_ADDR_MULTICAST)) { |
| 913 | LIMIT_NETDEBUG(KERN_DEBUG | 926 | LIMIT_NETDEBUG(KERN_DEBUG |
| @@ -1215,10 +1228,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
| 1215 | 1228 | ||
| 1216 | /* Gets referenced address, destroys ifaddr */ | 1229 | /* Gets referenced address, destroys ifaddr */ |
| 1217 | 1230 | ||
| 1218 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1231 | void addrconf_dad_stop(struct inet6_ifaddr *ifp) |
| 1219 | { | 1232 | { |
| 1220 | if (net_ratelimit()) | ||
| 1221 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
| 1222 | if (ifp->flags&IFA_F_PERMANENT) { | 1233 | if (ifp->flags&IFA_F_PERMANENT) { |
| 1223 | spin_lock_bh(&ifp->lock); | 1234 | spin_lock_bh(&ifp->lock); |
| 1224 | addrconf_del_timer(ifp); | 1235 | addrconf_del_timer(ifp); |
| @@ -1244,6 +1255,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
| 1244 | ipv6_del_addr(ifp); | 1255 | ipv6_del_addr(ifp); |
| 1245 | } | 1256 | } |
| 1246 | 1257 | ||
| 1258 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | ||
| 1259 | { | ||
| 1260 | if (net_ratelimit()) | ||
| 1261 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
| 1262 | addrconf_dad_stop(ifp); | ||
| 1263 | } | ||
| 1247 | 1264 | ||
| 1248 | /* Join to solicited addr multicast group. */ | 1265 | /* Join to solicited addr multicast group. */ |
| 1249 | 1266 | ||
| @@ -1596,9 +1613,17 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1596 | not good. | 1613 | not good. |
| 1597 | */ | 1614 | */ |
| 1598 | if (valid_lft >= 0x7FFFFFFF/HZ) | 1615 | if (valid_lft >= 0x7FFFFFFF/HZ) |
| 1599 | rt_expires = 0; | 1616 | rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ); |
| 1600 | else | 1617 | else |
| 1601 | rt_expires = jiffies + valid_lft * HZ; | 1618 | rt_expires = valid_lft * HZ; |
| 1619 | |||
| 1620 | /* | ||
| 1621 | * We convert this (in jiffies) to clock_t later. | ||
| 1622 | * Avoid arithmetic overflow there as well. | ||
| 1623 | * Overflow can happen only if HZ < USER_HZ. | ||
| 1624 | */ | ||
| 1625 | if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ) | ||
| 1626 | rt_expires = 0x7FFFFFFF / USER_HZ; | ||
| 1602 | 1627 | ||
| 1603 | if (pinfo->onlink) { | 1628 | if (pinfo->onlink) { |
| 1604 | struct rt6_info *rt; | 1629 | struct rt6_info *rt; |
| @@ -1610,12 +1635,12 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1610 | ip6_del_rt(rt, NULL, NULL, NULL); | 1635 | ip6_del_rt(rt, NULL, NULL, NULL); |
| 1611 | rt = NULL; | 1636 | rt = NULL; |
| 1612 | } else { | 1637 | } else { |
| 1613 | rt->rt6i_expires = rt_expires; | 1638 | rt->rt6i_expires = jiffies + rt_expires; |
| 1614 | } | 1639 | } |
| 1615 | } | 1640 | } |
| 1616 | } else if (valid_lft) { | 1641 | } else if (valid_lft) { |
| 1617 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, | 1642 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, |
| 1618 | dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); | 1643 | dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); |
| 1619 | } | 1644 | } |
| 1620 | if (rt) | 1645 | if (rt) |
| 1621 | dst_release(&rt->u.dst); | 1646 | dst_release(&rt->u.dst); |
| @@ -2125,9 +2150,42 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2125 | { | 2150 | { |
| 2126 | struct net_device *dev = (struct net_device *) data; | 2151 | struct net_device *dev = (struct net_device *) data; |
| 2127 | struct inet6_dev *idev = __in6_dev_get(dev); | 2152 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 2153 | int run_pending = 0; | ||
| 2128 | 2154 | ||
| 2129 | switch(event) { | 2155 | switch(event) { |
| 2130 | case NETDEV_UP: | 2156 | case NETDEV_UP: |
| 2157 | case NETDEV_CHANGE: | ||
| 2158 | if (event == NETDEV_UP) { | ||
| 2159 | if (!netif_carrier_ok(dev)) { | ||
| 2160 | /* device is not ready yet. */ | ||
| 2161 | printk(KERN_INFO | ||
| 2162 | "ADDRCONF(NETDEV_UP): %s: " | ||
| 2163 | "link is not ready\n", | ||
| 2164 | dev->name); | ||
| 2165 | break; | ||
| 2166 | } | ||
| 2167 | } else { | ||
| 2168 | if (!netif_carrier_ok(dev)) { | ||
| 2169 | /* device is still not ready. */ | ||
| 2170 | break; | ||
| 2171 | } | ||
| 2172 | |||
| 2173 | if (idev) { | ||
| 2174 | if (idev->if_flags & IF_READY) { | ||
| 2175 | /* device is already configured. */ | ||
| 2176 | break; | ||
| 2177 | } | ||
| 2178 | idev->if_flags |= IF_READY; | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | printk(KERN_INFO | ||
| 2182 | "ADDRCONF(NETDEV_CHANGE): %s: " | ||
| 2183 | "link becomes ready\n", | ||
| 2184 | dev->name); | ||
| 2185 | |||
| 2186 | run_pending = 1; | ||
| 2187 | } | ||
| 2188 | |||
| 2131 | switch(dev->type) { | 2189 | switch(dev->type) { |
| 2132 | case ARPHRD_SIT: | 2190 | case ARPHRD_SIT: |
| 2133 | addrconf_sit_config(dev); | 2191 | addrconf_sit_config(dev); |
| @@ -2144,6 +2202,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2144 | break; | 2202 | break; |
| 2145 | }; | 2203 | }; |
| 2146 | if (idev) { | 2204 | if (idev) { |
| 2205 | if (run_pending) | ||
| 2206 | addrconf_dad_run(idev); | ||
| 2207 | |||
| 2147 | /* If the MTU changed during the interface down, when the | 2208 | /* If the MTU changed during the interface down, when the |
| 2148 | interface up, the changed MTU must be reflected in the | 2209 | interface up, the changed MTU must be reflected in the |
| 2149 | idev as well as routers. | 2210 | idev as well as routers. |
| @@ -2178,8 +2239,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2178 | */ | 2239 | */ |
| 2179 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2240 | addrconf_ifdown(dev, event != NETDEV_DOWN); |
| 2180 | break; | 2241 | break; |
| 2181 | case NETDEV_CHANGE: | 2242 | |
| 2182 | break; | ||
| 2183 | case NETDEV_CHANGENAME: | 2243 | case NETDEV_CHANGENAME: |
| 2184 | #ifdef CONFIG_SYSCTL | 2244 | #ifdef CONFIG_SYSCTL |
| 2185 | if (idev) { | 2245 | if (idev) { |
| @@ -2260,7 +2320,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2260 | 2320 | ||
| 2261 | /* Step 3: clear flags for stateless addrconf */ | 2321 | /* Step 3: clear flags for stateless addrconf */ |
| 2262 | if (how != 1) | 2322 | if (how != 1) |
| 2263 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD); | 2323 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
| 2264 | 2324 | ||
| 2265 | /* Step 4: clear address list */ | 2325 | /* Step 4: clear address list */ |
| 2266 | #ifdef CONFIG_IPV6_PRIVACY | 2326 | #ifdef CONFIG_IPV6_PRIVACY |
| @@ -2369,11 +2429,20 @@ out: | |||
| 2369 | /* | 2429 | /* |
| 2370 | * Duplicate Address Detection | 2430 | * Duplicate Address Detection |
| 2371 | */ | 2431 | */ |
| 2432 | static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | ||
| 2433 | { | ||
| 2434 | unsigned long rand_num; | ||
| 2435 | struct inet6_dev *idev = ifp->idev; | ||
| 2436 | |||
| 2437 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
| 2438 | ifp->probes = idev->cnf.dad_transmits; | ||
| 2439 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | ||
| 2440 | } | ||
| 2441 | |||
| 2372 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | 2442 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) |
| 2373 | { | 2443 | { |
| 2374 | struct inet6_dev *idev = ifp->idev; | 2444 | struct inet6_dev *idev = ifp->idev; |
| 2375 | struct net_device *dev = idev->dev; | 2445 | struct net_device *dev = idev->dev; |
| 2376 | unsigned long rand_num; | ||
| 2377 | 2446 | ||
| 2378 | addrconf_join_solict(dev, &ifp->addr); | 2447 | addrconf_join_solict(dev, &ifp->addr); |
| 2379 | 2448 | ||
| @@ -2382,7 +2451,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2382 | flags); | 2451 | flags); |
| 2383 | 2452 | ||
| 2384 | net_srandom(ifp->addr.s6_addr32[3]); | 2453 | net_srandom(ifp->addr.s6_addr32[3]); |
| 2385 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
| 2386 | 2454 | ||
| 2387 | read_lock_bh(&idev->lock); | 2455 | read_lock_bh(&idev->lock); |
| 2388 | if (ifp->dead) | 2456 | if (ifp->dead) |
| @@ -2399,9 +2467,19 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2399 | return; | 2467 | return; |
| 2400 | } | 2468 | } |
| 2401 | 2469 | ||
| 2402 | ifp->probes = idev->cnf.dad_transmits; | 2470 | if (!(idev->if_flags & IF_READY)) { |
| 2403 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | 2471 | spin_unlock_bh(&ifp->lock); |
| 2404 | 2472 | read_unlock_bh(&idev->lock); | |
| 2473 | /* | ||
| 2474 | * If the defice is not ready: | ||
| 2475 | * - keep it tentative if it is a permanent address. | ||
| 2476 | * - otherwise, kill it. | ||
| 2477 | */ | ||
| 2478 | in6_ifa_hold(ifp); | ||
| 2479 | addrconf_dad_stop(ifp); | ||
| 2480 | return; | ||
| 2481 | } | ||
| 2482 | addrconf_dad_kick(ifp); | ||
| 2405 | spin_unlock_bh(&ifp->lock); | 2483 | spin_unlock_bh(&ifp->lock); |
| 2406 | out: | 2484 | out: |
| 2407 | read_unlock_bh(&idev->lock); | 2485 | read_unlock_bh(&idev->lock); |
| @@ -2484,6 +2562,22 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
| 2484 | } | 2562 | } |
| 2485 | } | 2563 | } |
| 2486 | 2564 | ||
| 2565 | static void addrconf_dad_run(struct inet6_dev *idev) { | ||
| 2566 | struct inet6_ifaddr *ifp; | ||
| 2567 | |||
| 2568 | read_lock_bh(&idev->lock); | ||
| 2569 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | ||
| 2570 | spin_lock_bh(&ifp->lock); | ||
| 2571 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | ||
| 2572 | spin_unlock_bh(&ifp->lock); | ||
| 2573 | continue; | ||
| 2574 | } | ||
| 2575 | spin_unlock_bh(&ifp->lock); | ||
| 2576 | addrconf_dad_kick(ifp); | ||
| 2577 | } | ||
| 2578 | read_unlock_bh(&idev->lock); | ||
| 2579 | } | ||
| 2580 | |||
| 2487 | #ifdef CONFIG_PROC_FS | 2581 | #ifdef CONFIG_PROC_FS |
| 2488 | struct if6_iter_state { | 2582 | struct if6_iter_state { |
| 2489 | int bucket; | 2583 | int bucket; |
| @@ -2689,6 +2783,9 @@ restart: | |||
| 2689 | in6_ifa_hold(ifpub); | 2783 | in6_ifa_hold(ifpub); |
| 2690 | spin_unlock(&ifp->lock); | 2784 | spin_unlock(&ifp->lock); |
| 2691 | read_unlock(&addrconf_hash_lock); | 2785 | read_unlock(&addrconf_hash_lock); |
| 2786 | spin_lock(&ifpub->lock); | ||
| 2787 | ifpub->regen_count = 0; | ||
| 2788 | spin_unlock(&ifpub->lock); | ||
| 2692 | ipv6_create_tempaddr(ifpub, ifp); | 2789 | ipv6_create_tempaddr(ifpub, ifp); |
| 2693 | in6_ifa_put(ifpub); | 2790 | in6_ifa_put(ifpub); |
| 2694 | in6_ifa_put(ifp); | 2791 | in6_ifa_put(ifp); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 34a332225c17..6ec6a2b549bb 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -328,8 +328,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
| 328 | iif = skb->dev->ifindex; | 328 | iif = skb->dev->ifindex; |
| 329 | 329 | ||
| 330 | /* | 330 | /* |
| 331 | * Must not send if we know that source is Anycast also. | 331 | * Must not send error if the source does not uniquely |
| 332 | * for now we don't know that. | 332 | * identify a single node (RFC2463 Section 2.4). |
| 333 | * We check unspecified / multicast addresses here, | ||
| 334 | * and anycast addresses will be checked later. | ||
| 333 | */ | 335 | */ |
| 334 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { | 336 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { |
| 335 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); | 337 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); |
| @@ -373,6 +375,16 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
| 373 | err = ip6_dst_lookup(sk, &dst, &fl); | 375 | err = ip6_dst_lookup(sk, &dst, &fl); |
| 374 | if (err) | 376 | if (err) |
| 375 | goto out; | 377 | goto out; |
| 378 | |||
| 379 | /* | ||
| 380 | * We won't send icmp if the destination is known | ||
| 381 | * anycast. | ||
| 382 | */ | ||
| 383 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | ||
| 384 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | ||
| 385 | goto out_dst_release; | ||
| 386 | } | ||
| 387 | |||
| 376 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | 388 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
| 377 | goto out; | 389 | goto out; |
| 378 | 390 | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index fd939da090c4..f829a4ad3ccc 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -170,7 +170,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
| 170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) | 170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) |
| 171 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | 171 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) |
| 172 | 172 | ||
| 173 | #define IPV6_MLD_MAX_MSF 10 | 173 | #define IPV6_MLD_MAX_MSF 64 |
| 174 | 174 | ||
| 175 | int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF; | 175 | int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF; |
| 176 | 176 | ||
| @@ -224,6 +224,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
| 224 | 224 | ||
| 225 | mc_lst->ifindex = dev->ifindex; | 225 | mc_lst->ifindex = dev->ifindex; |
| 226 | mc_lst->sfmode = MCAST_EXCLUDE; | 226 | mc_lst->sfmode = MCAST_EXCLUDE; |
| 227 | mc_lst->sflock = RW_LOCK_UNLOCKED; | ||
| 227 | mc_lst->sflist = NULL; | 228 | mc_lst->sflist = NULL; |
| 228 | 229 | ||
| 229 | /* | 230 | /* |
| @@ -360,6 +361,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 360 | struct ip6_sf_socklist *psl; | 361 | struct ip6_sf_socklist *psl; |
| 361 | int i, j, rv; | 362 | int i, j, rv; |
| 362 | int leavegroup = 0; | 363 | int leavegroup = 0; |
| 364 | int pmclocked = 0; | ||
| 363 | int err; | 365 | int err; |
| 364 | 366 | ||
| 365 | if (pgsr->gsr_group.ss_family != AF_INET6 || | 367 | if (pgsr->gsr_group.ss_family != AF_INET6 || |
| @@ -403,6 +405,9 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 403 | pmc->sfmode = omode; | 405 | pmc->sfmode = omode; |
| 404 | } | 406 | } |
| 405 | 407 | ||
| 408 | write_lock_bh(&pmc->sflock); | ||
| 409 | pmclocked = 1; | ||
| 410 | |||
| 406 | psl = pmc->sflist; | 411 | psl = pmc->sflist; |
| 407 | if (!add) { | 412 | if (!add) { |
| 408 | if (!psl) | 413 | if (!psl) |
| @@ -475,6 +480,8 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 475 | /* update the interface list */ | 480 | /* update the interface list */ |
| 476 | ip6_mc_add_src(idev, group, omode, 1, source, 1); | 481 | ip6_mc_add_src(idev, group, omode, 1, source, 1); |
| 477 | done: | 482 | done: |
| 483 | if (pmclocked) | ||
| 484 | write_unlock_bh(&pmc->sflock); | ||
| 478 | read_unlock_bh(&ipv6_sk_mc_lock); | 485 | read_unlock_bh(&ipv6_sk_mc_lock); |
| 479 | read_unlock_bh(&idev->lock); | 486 | read_unlock_bh(&idev->lock); |
| 480 | in6_dev_put(idev); | 487 | in6_dev_put(idev); |
| @@ -510,6 +517,8 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 510 | dev = idev->dev; | 517 | dev = idev->dev; |
| 511 | 518 | ||
| 512 | err = 0; | 519 | err = 0; |
| 520 | read_lock_bh(&ipv6_sk_mc_lock); | ||
| 521 | |||
| 513 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { | 522 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { |
| 514 | leavegroup = 1; | 523 | leavegroup = 1; |
| 515 | goto done; | 524 | goto done; |
| @@ -549,6 +558,8 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 549 | newpsl = NULL; | 558 | newpsl = NULL; |
| 550 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); | 559 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); |
| 551 | } | 560 | } |
| 561 | |||
| 562 | write_lock_bh(&pmc->sflock); | ||
| 552 | psl = pmc->sflist; | 563 | psl = pmc->sflist; |
| 553 | if (psl) { | 564 | if (psl) { |
| 554 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, | 565 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, |
| @@ -558,8 +569,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 558 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); | 569 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); |
| 559 | pmc->sflist = newpsl; | 570 | pmc->sflist = newpsl; |
| 560 | pmc->sfmode = gsf->gf_fmode; | 571 | pmc->sfmode = gsf->gf_fmode; |
| 572 | write_unlock_bh(&pmc->sflock); | ||
| 561 | err = 0; | 573 | err = 0; |
| 562 | done: | 574 | done: |
| 575 | read_unlock_bh(&ipv6_sk_mc_lock); | ||
| 563 | read_unlock_bh(&idev->lock); | 576 | read_unlock_bh(&idev->lock); |
| 564 | in6_dev_put(idev); | 577 | in6_dev_put(idev); |
| 565 | dev_put(dev); | 578 | dev_put(dev); |
| @@ -592,6 +605,11 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
| 592 | dev = idev->dev; | 605 | dev = idev->dev; |
| 593 | 606 | ||
| 594 | err = -EADDRNOTAVAIL; | 607 | err = -EADDRNOTAVAIL; |
| 608 | /* | ||
| 609 | * changes to the ipv6_mc_list require the socket lock and | ||
| 610 | * a read lock on ip6_sk_mc_lock. We have the socket lock, | ||
| 611 | * so reading the list is safe. | ||
| 612 | */ | ||
| 595 | 613 | ||
| 596 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | 614 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { |
| 597 | if (pmc->ifindex != gsf->gf_interface) | 615 | if (pmc->ifindex != gsf->gf_interface) |
| @@ -614,6 +632,10 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
| 614 | copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) { | 632 | copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) { |
| 615 | return -EFAULT; | 633 | return -EFAULT; |
| 616 | } | 634 | } |
| 635 | /* changes to psl require the socket lock, a read lock on | ||
| 636 | * on ipv6_sk_mc_lock and a write lock on pmc->sflock. We | ||
| 637 | * have the socket lock, so reading here is safe. | ||
| 638 | */ | ||
| 617 | for (i=0; i<copycount; i++) { | 639 | for (i=0; i<copycount; i++) { |
| 618 | struct sockaddr_in6 *psin6; | 640 | struct sockaddr_in6 *psin6; |
| 619 | struct sockaddr_storage ss; | 641 | struct sockaddr_storage ss; |
| @@ -650,6 +672,7 @@ int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | |||
| 650 | read_unlock(&ipv6_sk_mc_lock); | 672 | read_unlock(&ipv6_sk_mc_lock); |
| 651 | return 1; | 673 | return 1; |
| 652 | } | 674 | } |
| 675 | read_lock(&mc->sflock); | ||
| 653 | psl = mc->sflist; | 676 | psl = mc->sflist; |
| 654 | if (!psl) { | 677 | if (!psl) { |
| 655 | rv = mc->sfmode == MCAST_EXCLUDE; | 678 | rv = mc->sfmode == MCAST_EXCLUDE; |
| @@ -665,6 +688,7 @@ int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | |||
| 665 | if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) | 688 | if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) |
| 666 | rv = 0; | 689 | rv = 0; |
| 667 | } | 690 | } |
| 691 | read_unlock(&mc->sflock); | ||
| 668 | read_unlock(&ipv6_sk_mc_lock); | 692 | read_unlock(&ipv6_sk_mc_lock); |
| 669 | 693 | ||
| 670 | return rv; | 694 | return rv; |
| @@ -1068,7 +1092,8 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime) | |||
| 1068 | ma->mca_flags |= MAF_TIMER_RUNNING; | 1092 | ma->mca_flags |= MAF_TIMER_RUNNING; |
| 1069 | } | 1093 | } |
| 1070 | 1094 | ||
| 1071 | static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | 1095 | /* mark EXCLUDE-mode sources */ |
| 1096 | static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | ||
| 1072 | struct in6_addr *srcs) | 1097 | struct in6_addr *srcs) |
| 1073 | { | 1098 | { |
| 1074 | struct ip6_sf_list *psf; | 1099 | struct ip6_sf_list *psf; |
| @@ -1078,13 +1103,53 @@ static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
| 1078 | for (psf=pmc->mca_sources; psf; psf=psf->sf_next) { | 1103 | for (psf=pmc->mca_sources; psf; psf=psf->sf_next) { |
| 1079 | if (scount == nsrcs) | 1104 | if (scount == nsrcs) |
| 1080 | break; | 1105 | break; |
| 1081 | for (i=0; i<nsrcs; i++) | 1106 | for (i=0; i<nsrcs; i++) { |
| 1107 | /* skip inactive filters */ | ||
| 1108 | if (pmc->mca_sfcount[MCAST_INCLUDE] || | ||
| 1109 | pmc->mca_sfcount[MCAST_EXCLUDE] != | ||
| 1110 | psf->sf_count[MCAST_EXCLUDE]) | ||
| 1111 | continue; | ||
| 1112 | if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { | ||
| 1113 | scount++; | ||
| 1114 | break; | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | } | ||
| 1118 | pmc->mca_flags &= ~MAF_GSQUERY; | ||
| 1119 | if (scount == nsrcs) /* all sources excluded */ | ||
| 1120 | return 0; | ||
| 1121 | return 1; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | ||
| 1125 | struct in6_addr *srcs) | ||
| 1126 | { | ||
| 1127 | struct ip6_sf_list *psf; | ||
| 1128 | int i, scount; | ||
| 1129 | |||
| 1130 | if (pmc->mca_sfmode == MCAST_EXCLUDE) | ||
| 1131 | return mld_xmarksources(pmc, nsrcs, srcs); | ||
| 1132 | |||
| 1133 | /* mark INCLUDE-mode sources */ | ||
| 1134 | |||
| 1135 | scount = 0; | ||
| 1136 | for (psf=pmc->mca_sources; psf; psf=psf->sf_next) { | ||
| 1137 | if (scount == nsrcs) | ||
| 1138 | break; | ||
| 1139 | for (i=0; i<nsrcs; i++) { | ||
| 1082 | if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { | 1140 | if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { |
| 1083 | psf->sf_gsresp = 1; | 1141 | psf->sf_gsresp = 1; |
| 1084 | scount++; | 1142 | scount++; |
| 1085 | break; | 1143 | break; |
| 1086 | } | 1144 | } |
| 1145 | } | ||
| 1146 | } | ||
| 1147 | if (!scount) { | ||
| 1148 | pmc->mca_flags &= ~MAF_GSQUERY; | ||
| 1149 | return 0; | ||
| 1087 | } | 1150 | } |
| 1151 | pmc->mca_flags |= MAF_GSQUERY; | ||
| 1152 | return 1; | ||
| 1088 | } | 1153 | } |
| 1089 | 1154 | ||
| 1090 | int igmp6_event_query(struct sk_buff *skb) | 1155 | int igmp6_event_query(struct sk_buff *skb) |
| @@ -1167,7 +1232,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1167 | /* mark sources to include, if group & source-specific */ | 1232 | /* mark sources to include, if group & source-specific */ |
| 1168 | if (mlh2->nsrcs != 0) { | 1233 | if (mlh2->nsrcs != 0) { |
| 1169 | if (!pskb_may_pull(skb, srcs_offset + | 1234 | if (!pskb_may_pull(skb, srcs_offset + |
| 1170 | mlh2->nsrcs * sizeof(struct in6_addr))) { | 1235 | ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { |
| 1171 | in6_dev_put(idev); | 1236 | in6_dev_put(idev); |
| 1172 | return -EINVAL; | 1237 | return -EINVAL; |
| 1173 | } | 1238 | } |
| @@ -1203,10 +1268,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1203 | else | 1268 | else |
| 1204 | ma->mca_flags &= ~MAF_GSQUERY; | 1269 | ma->mca_flags &= ~MAF_GSQUERY; |
| 1205 | } | 1270 | } |
| 1206 | if (ma->mca_flags & MAF_GSQUERY) | 1271 | if (!(ma->mca_flags & MAF_GSQUERY) || |
| 1207 | mld_marksources(ma, ntohs(mlh2->nsrcs), | 1272 | mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) |
| 1208 | mlh2->srcs); | 1273 | igmp6_group_queried(ma, max_delay); |
| 1209 | igmp6_group_queried(ma, max_delay); | ||
| 1210 | spin_unlock_bh(&ma->mca_lock); | 1274 | spin_unlock_bh(&ma->mca_lock); |
| 1211 | if (group_type != IPV6_ADDR_ANY) | 1275 | if (group_type != IPV6_ADDR_ANY) |
| 1212 | break; | 1276 | break; |
| @@ -1281,7 +1345,18 @@ static int is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type, | |||
| 1281 | case MLD2_MODE_IS_EXCLUDE: | 1345 | case MLD2_MODE_IS_EXCLUDE: |
| 1282 | if (gdeleted || sdeleted) | 1346 | if (gdeleted || sdeleted) |
| 1283 | return 0; | 1347 | return 0; |
| 1284 | return !((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp); | 1348 | if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) { |
| 1349 | if (pmc->mca_sfmode == MCAST_INCLUDE) | ||
| 1350 | return 1; | ||
| 1351 | /* don't include if this source is excluded | ||
| 1352 | * in all filters | ||
| 1353 | */ | ||
| 1354 | if (psf->sf_count[MCAST_INCLUDE]) | ||
| 1355 | return 0; | ||
| 1356 | return pmc->mca_sfcount[MCAST_EXCLUDE] == | ||
| 1357 | psf->sf_count[MCAST_EXCLUDE]; | ||
| 1358 | } | ||
| 1359 | return 0; | ||
| 1285 | case MLD2_CHANGE_TO_INCLUDE: | 1360 | case MLD2_CHANGE_TO_INCLUDE: |
| 1286 | if (gdeleted || sdeleted) | 1361 | if (gdeleted || sdeleted) |
| 1287 | return 0; | 1362 | return 0; |
| @@ -1450,7 +1525,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1450 | struct mld2_report *pmr; | 1525 | struct mld2_report *pmr; |
| 1451 | struct mld2_grec *pgr = NULL; | 1526 | struct mld2_grec *pgr = NULL; |
| 1452 | struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; | 1527 | struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; |
| 1453 | int scount, first, isquery, truncate; | 1528 | int scount, stotal, first, isquery, truncate; |
| 1454 | 1529 | ||
| 1455 | if (pmc->mca_flags & MAF_NOREPORT) | 1530 | if (pmc->mca_flags & MAF_NOREPORT) |
| 1456 | return skb; | 1531 | return skb; |
| @@ -1460,25 +1535,13 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1460 | truncate = type == MLD2_MODE_IS_EXCLUDE || | 1535 | truncate = type == MLD2_MODE_IS_EXCLUDE || |
| 1461 | type == MLD2_CHANGE_TO_EXCLUDE; | 1536 | type == MLD2_CHANGE_TO_EXCLUDE; |
| 1462 | 1537 | ||
| 1538 | stotal = scount = 0; | ||
| 1539 | |||
| 1463 | psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources; | 1540 | psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources; |
| 1464 | 1541 | ||
| 1465 | if (!*psf_list) { | 1542 | if (!*psf_list) |
| 1466 | if (type == MLD2_ALLOW_NEW_SOURCES || | 1543 | goto empty_source; |
| 1467 | type == MLD2_BLOCK_OLD_SOURCES) | 1544 | |
| 1468 | return skb; | ||
| 1469 | if (pmc->mca_crcount || isquery) { | ||
| 1470 | /* make sure we have room for group header and at | ||
| 1471 | * least one source. | ||
| 1472 | */ | ||
| 1473 | if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)+ | ||
| 1474 | sizeof(struct in6_addr)) { | ||
| 1475 | mld_sendpack(skb); | ||
| 1476 | skb = NULL; /* add_grhead will get a new one */ | ||
| 1477 | } | ||
| 1478 | skb = add_grhead(skb, pmc, type, &pgr); | ||
| 1479 | } | ||
| 1480 | return skb; | ||
| 1481 | } | ||
| 1482 | pmr = skb ? (struct mld2_report *)skb->h.raw : NULL; | 1545 | pmr = skb ? (struct mld2_report *)skb->h.raw : NULL; |
| 1483 | 1546 | ||
| 1484 | /* EX and TO_EX get a fresh packet, if needed */ | 1547 | /* EX and TO_EX get a fresh packet, if needed */ |
| @@ -1491,7 +1554,6 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1491 | } | 1554 | } |
| 1492 | } | 1555 | } |
| 1493 | first = 1; | 1556 | first = 1; |
| 1494 | scount = 0; | ||
| 1495 | psf_prev = NULL; | 1557 | psf_prev = NULL; |
| 1496 | for (psf=*psf_list; psf; psf=psf_next) { | 1558 | for (psf=*psf_list; psf; psf=psf_next) { |
| 1497 | struct in6_addr *psrc; | 1559 | struct in6_addr *psrc; |
| @@ -1525,7 +1587,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1525 | } | 1587 | } |
| 1526 | psrc = (struct in6_addr *)skb_put(skb, sizeof(*psrc)); | 1588 | psrc = (struct in6_addr *)skb_put(skb, sizeof(*psrc)); |
| 1527 | *psrc = psf->sf_addr; | 1589 | *psrc = psf->sf_addr; |
| 1528 | scount++; | 1590 | scount++; stotal++; |
| 1529 | if ((type == MLD2_ALLOW_NEW_SOURCES || | 1591 | if ((type == MLD2_ALLOW_NEW_SOURCES || |
| 1530 | type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) { | 1592 | type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) { |
| 1531 | psf->sf_crcount--; | 1593 | psf->sf_crcount--; |
| @@ -1540,6 +1602,21 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1540 | } | 1602 | } |
| 1541 | psf_prev = psf; | 1603 | psf_prev = psf; |
| 1542 | } | 1604 | } |
| 1605 | |||
| 1606 | empty_source: | ||
| 1607 | if (!stotal) { | ||
| 1608 | if (type == MLD2_ALLOW_NEW_SOURCES || | ||
| 1609 | type == MLD2_BLOCK_OLD_SOURCES) | ||
| 1610 | return skb; | ||
| 1611 | if (pmc->mca_crcount || isquery) { | ||
| 1612 | /* make sure we have room for group header */ | ||
| 1613 | if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)) { | ||
| 1614 | mld_sendpack(skb); | ||
| 1615 | skb = NULL; /* add_grhead will get a new one */ | ||
| 1616 | } | ||
| 1617 | skb = add_grhead(skb, pmc, type, &pgr); | ||
| 1618 | } | ||
| 1619 | } | ||
| 1543 | if (pgr) | 1620 | if (pgr) |
| 1544 | pgr->grec_nsrcs = htons(scount); | 1621 | pgr->grec_nsrcs = htons(scount); |
| 1545 | 1622 | ||
| @@ -1621,11 +1698,11 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
| 1621 | skb = add_grec(skb, pmc, dtype, 1, 1); | 1698 | skb = add_grec(skb, pmc, dtype, 1, 1); |
| 1622 | } | 1699 | } |
| 1623 | if (pmc->mca_crcount) { | 1700 | if (pmc->mca_crcount) { |
| 1624 | pmc->mca_crcount--; | ||
| 1625 | if (pmc->mca_sfmode == MCAST_EXCLUDE) { | 1701 | if (pmc->mca_sfmode == MCAST_EXCLUDE) { |
| 1626 | type = MLD2_CHANGE_TO_INCLUDE; | 1702 | type = MLD2_CHANGE_TO_INCLUDE; |
| 1627 | skb = add_grec(skb, pmc, type, 1, 0); | 1703 | skb = add_grec(skb, pmc, type, 1, 0); |
| 1628 | } | 1704 | } |
| 1705 | pmc->mca_crcount--; | ||
| 1629 | if (pmc->mca_crcount == 0) { | 1706 | if (pmc->mca_crcount == 0) { |
| 1630 | mld_clear_zeros(&pmc->mca_tomb); | 1707 | mld_clear_zeros(&pmc->mca_tomb); |
| 1631 | mld_clear_zeros(&pmc->mca_sources); | 1708 | mld_clear_zeros(&pmc->mca_sources); |
| @@ -1659,12 +1736,12 @@ static void mld_send_cr(struct inet6_dev *idev) | |||
| 1659 | 1736 | ||
| 1660 | /* filter mode changes */ | 1737 | /* filter mode changes */ |
| 1661 | if (pmc->mca_crcount) { | 1738 | if (pmc->mca_crcount) { |
| 1662 | pmc->mca_crcount--; | ||
| 1663 | if (pmc->mca_sfmode == MCAST_EXCLUDE) | 1739 | if (pmc->mca_sfmode == MCAST_EXCLUDE) |
| 1664 | type = MLD2_CHANGE_TO_EXCLUDE; | 1740 | type = MLD2_CHANGE_TO_EXCLUDE; |
| 1665 | else | 1741 | else |
| 1666 | type = MLD2_CHANGE_TO_INCLUDE; | 1742 | type = MLD2_CHANGE_TO_INCLUDE; |
| 1667 | skb = add_grec(skb, pmc, type, 0, 0); | 1743 | skb = add_grec(skb, pmc, type, 0, 0); |
| 1744 | pmc->mca_crcount--; | ||
| 1668 | } | 1745 | } |
| 1669 | spin_unlock_bh(&pmc->mca_lock); | 1746 | spin_unlock_bh(&pmc->mca_lock); |
| 1670 | } | 1747 | } |
| @@ -2023,6 +2100,9 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
| 2023 | { | 2100 | { |
| 2024 | int err; | 2101 | int err; |
| 2025 | 2102 | ||
| 2103 | /* callers have the socket lock and a write lock on ipv6_sk_mc_lock, | ||
| 2104 | * so no other readers or writers of iml or its sflist | ||
| 2105 | */ | ||
| 2026 | if (iml->sflist == 0) { | 2106 | if (iml->sflist == 0) { |
| 2027 | /* any-source empty exclude case */ | 2107 | /* any-source empty exclude case */ |
| 2028 | return ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0); | 2108 | return ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 060d61202412..04912f9b35c3 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -211,7 +211,7 @@ config IP6_NF_TARGET_REJECT | |||
| 211 | 211 | ||
| 212 | config IP6_NF_TARGET_NFQUEUE | 212 | config IP6_NF_TARGET_NFQUEUE |
| 213 | tristate "NFQUEUE Target Support" | 213 | tristate "NFQUEUE Target Support" |
| 214 | depends on IP_NF_IPTABLES | 214 | depends on IP6_NF_IPTABLES |
| 215 | help | 215 | help |
| 216 | This Target replaced the old obsolete QUEUE target. | 216 | This Target replaced the old obsolete QUEUE target. |
| 217 | 217 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a7a537b50595..66140f13d119 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -413,11 +413,14 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, | |||
| 413 | rt = ip6_rt_copy(ort); | 413 | rt = ip6_rt_copy(ort); |
| 414 | 414 | ||
| 415 | if (rt) { | 415 | if (rt) { |
| 416 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 416 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { |
| 417 | 417 | if (rt->rt6i_dst.plen != 128 && | |
| 418 | if (!(rt->rt6i_flags&RTF_GATEWAY)) | 418 | ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) |
| 419 | rt->rt6i_flags |= RTF_ANYCAST; | ||
| 419 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 420 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
| 421 | } | ||
| 420 | 422 | ||
| 423 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | ||
| 421 | rt->rt6i_dst.plen = 128; | 424 | rt->rt6i_dst.plen = 128; |
| 422 | rt->rt6i_flags |= RTF_CACHE; | 425 | rt->rt6i_flags |= RTF_CACHE; |
| 423 | rt->u.dst.flags |= DST_HOST; | 426 | rt->u.dst.flags |= DST_HOST; |
| @@ -829,7 +832,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, | |||
| 829 | } | 832 | } |
| 830 | 833 | ||
| 831 | rt->u.dst.obsolete = -1; | 834 | rt->u.dst.obsolete = -1; |
| 832 | rt->rt6i_expires = clock_t_to_jiffies(rtmsg->rtmsg_info); | 835 | rt->rt6i_expires = jiffies + clock_t_to_jiffies(rtmsg->rtmsg_info); |
| 833 | if (nlh && (r = NLMSG_DATA(nlh))) { | 836 | if (nlh && (r = NLMSG_DATA(nlh))) { |
| 834 | rt->rt6i_protocol = r->rtm_protocol; | 837 | rt->rt6i_protocol = r->rtm_protocol; |
| 835 | } else { | 838 | } else { |
| @@ -1413,7 +1416,9 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1413 | rt->u.dst.obsolete = -1; | 1416 | rt->u.dst.obsolete = -1; |
| 1414 | 1417 | ||
| 1415 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 1418 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
| 1416 | if (!anycast) | 1419 | if (anycast) |
| 1420 | rt->rt6i_flags |= RTF_ANYCAST; | ||
| 1421 | else | ||
| 1417 | rt->rt6i_flags |= RTF_LOCAL; | 1422 | rt->rt6i_flags |= RTF_LOCAL; |
| 1418 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1423 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
| 1419 | if (rt->rt6i_nexthop == NULL) { | 1424 | if (rt->rt6i_nexthop == NULL) { |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index cf1d91e74c82..69bd957380e7 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -214,6 +214,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
| 214 | case IPPROTO_UDP: | 214 | case IPPROTO_UDP: |
| 215 | case IPPROTO_TCP: | 215 | case IPPROTO_TCP: |
| 216 | case IPPROTO_SCTP: | 216 | case IPPROTO_SCTP: |
| 217 | case IPPROTO_DCCP: | ||
| 217 | if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { | 218 | if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { |
| 218 | u16 *ports = (u16 *)exthdr; | 219 | u16 *ports = (u16 *)exthdr; |
| 219 | 220 | ||
