diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/Makefile | 2 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 304 | ||||
-rw-r--r-- | net/ipv6/addrconf_core.c | 1 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 12 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 27 | ||||
-rw-r--r-- | net/ipv6/exthdrs_core.c | 2 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 23 | ||||
-rw-r--r-- | net/ipv6/ip6_offload.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 16 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 75 | ||||
-rw-r--r-- | net/ipv6/mip6.c | 6 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 11 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_MASQUERADE.c | 6 | ||||
-rw-r--r-- | net/ipv6/output_core.c | 3 | ||||
-rw-r--r-- | net/ipv6/ping.c | 277 | ||||
-rw-r--r-- | net/ipv6/raw.c | 48 | ||||
-rw-r--r-- | net/ipv6/route.c | 24 | ||||
-rw-r--r-- | net/ipv6/sit.c | 211 | ||||
-rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 4 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
-rw-r--r-- | net/ipv6/udp.c | 62 | ||||
-rw-r--r-- | net/ipv6/udp_offload.c | 3 |
23 files changed, 835 insertions, 287 deletions
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 9af088d2cdaa..470a9c008e9b 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o | |||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ | 7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ |
8 | addrlabel.o \ | 8 | addrlabel.o \ |
9 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ | 9 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ |
10 | raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 10 | raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ |
11 | exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o | 11 | exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o |
12 | 12 | ||
13 | ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o | 13 | ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ab4c38958c6..cfdcf7b2daf6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -253,37 +253,32 @@ static inline bool addrconf_qdisc_ok(const struct net_device *dev) | |||
253 | return !qdisc_tx_is_noop(dev); | 253 | return !qdisc_tx_is_noop(dev); |
254 | } | 254 | } |
255 | 255 | ||
256 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 256 | static void addrconf_del_rs_timer(struct inet6_dev *idev) |
257 | { | 257 | { |
258 | if (del_timer(&ifp->timer)) | 258 | if (del_timer(&idev->rs_timer)) |
259 | __in6_dev_put(idev); | ||
260 | } | ||
261 | |||
262 | static void addrconf_del_dad_timer(struct inet6_ifaddr *ifp) | ||
263 | { | ||
264 | if (del_timer(&ifp->dad_timer)) | ||
259 | __in6_ifa_put(ifp); | 265 | __in6_ifa_put(ifp); |
260 | } | 266 | } |
261 | 267 | ||
262 | enum addrconf_timer_t { | 268 | static void addrconf_mod_rs_timer(struct inet6_dev *idev, |
263 | AC_NONE, | 269 | unsigned long when) |
264 | AC_DAD, | 270 | { |
265 | AC_RS, | 271 | if (!timer_pending(&idev->rs_timer)) |
266 | }; | 272 | in6_dev_hold(idev); |
273 | mod_timer(&idev->rs_timer, jiffies + when); | ||
274 | } | ||
267 | 275 | ||
268 | static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | 276 | static void addrconf_mod_dad_timer(struct inet6_ifaddr *ifp, |
269 | enum addrconf_timer_t what, | 277 | unsigned long when) |
270 | unsigned long when) | ||
271 | { | 278 | { |
272 | if (!del_timer(&ifp->timer)) | 279 | if (!timer_pending(&ifp->dad_timer)) |
273 | in6_ifa_hold(ifp); | 280 | in6_ifa_hold(ifp); |
274 | 281 | mod_timer(&ifp->dad_timer, jiffies + when); | |
275 | switch (what) { | ||
276 | case AC_DAD: | ||
277 | ifp->timer.function = addrconf_dad_timer; | ||
278 | break; | ||
279 | case AC_RS: | ||
280 | ifp->timer.function = addrconf_rs_timer; | ||
281 | break; | ||
282 | default: | ||
283 | break; | ||
284 | } | ||
285 | ifp->timer.expires = jiffies + when; | ||
286 | add_timer(&ifp->timer); | ||
287 | } | 282 | } |
288 | 283 | ||
289 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 284 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
@@ -326,6 +321,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
326 | 321 | ||
327 | WARN_ON(!list_empty(&idev->addr_list)); | 322 | WARN_ON(!list_empty(&idev->addr_list)); |
328 | WARN_ON(idev->mc_list != NULL); | 323 | WARN_ON(idev->mc_list != NULL); |
324 | WARN_ON(timer_pending(&idev->rs_timer)); | ||
329 | 325 | ||
330 | #ifdef NET_REFCNT_DEBUG | 326 | #ifdef NET_REFCNT_DEBUG |
331 | pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL"); | 327 | pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL"); |
@@ -357,7 +353,8 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
357 | rwlock_init(&ndev->lock); | 353 | rwlock_init(&ndev->lock); |
358 | ndev->dev = dev; | 354 | ndev->dev = dev; |
359 | INIT_LIST_HEAD(&ndev->addr_list); | 355 | INIT_LIST_HEAD(&ndev->addr_list); |
360 | 356 | setup_timer(&ndev->rs_timer, addrconf_rs_timer, | |
357 | (unsigned long)ndev); | ||
361 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 358 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
362 | ndev->cnf.mtu6 = dev->mtu; | 359 | ndev->cnf.mtu6 = dev->mtu; |
363 | ndev->cnf.sysctl = NULL; | 360 | ndev->cnf.sysctl = NULL; |
@@ -776,7 +773,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
776 | 773 | ||
777 | in6_dev_put(ifp->idev); | 774 | in6_dev_put(ifp->idev); |
778 | 775 | ||
779 | if (del_timer(&ifp->timer)) | 776 | if (del_timer(&ifp->dad_timer)) |
780 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); | 777 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
781 | 778 | ||
782 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { | 779 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
@@ -869,9 +866,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
869 | 866 | ||
870 | spin_lock_init(&ifa->lock); | 867 | spin_lock_init(&ifa->lock); |
871 | spin_lock_init(&ifa->state_lock); | 868 | spin_lock_init(&ifa->state_lock); |
872 | init_timer(&ifa->timer); | 869 | setup_timer(&ifa->dad_timer, addrconf_dad_timer, |
870 | (unsigned long)ifa); | ||
873 | INIT_HLIST_NODE(&ifa->addr_lst); | 871 | INIT_HLIST_NODE(&ifa->addr_lst); |
874 | ifa->timer.data = (unsigned long) ifa; | ||
875 | ifa->scope = scope; | 872 | ifa->scope = scope; |
876 | ifa->prefix_len = pfxlen; | 873 | ifa->prefix_len = pfxlen; |
877 | ifa->flags = flags | IFA_F_TENTATIVE; | 874 | ifa->flags = flags | IFA_F_TENTATIVE; |
@@ -994,7 +991,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
994 | } | 991 | } |
995 | write_unlock_bh(&idev->lock); | 992 | write_unlock_bh(&idev->lock); |
996 | 993 | ||
997 | addrconf_del_timer(ifp); | 994 | addrconf_del_dad_timer(ifp); |
998 | 995 | ||
999 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 996 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
1000 | 997 | ||
@@ -1126,8 +1123,7 @@ retry: | |||
1126 | 1123 | ||
1127 | ift = !max_addresses || | 1124 | ift = !max_addresses || |
1128 | ipv6_count_addresses(idev) < max_addresses ? | 1125 | ipv6_count_addresses(idev) < max_addresses ? |
1129 | ipv6_add_addr(idev, &addr, tmp_plen, | 1126 | ipv6_add_addr(idev, &addr, tmp_plen, ipv6_addr_scope(&addr), |
1130 | ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, | ||
1131 | addr_flags) : NULL; | 1127 | addr_flags) : NULL; |
1132 | if (IS_ERR_OR_NULL(ift)) { | 1128 | if (IS_ERR_OR_NULL(ift)) { |
1133 | in6_ifa_put(ifp); | 1129 | in6_ifa_put(ifp); |
@@ -1448,6 +1444,23 @@ try_nextdev: | |||
1448 | } | 1444 | } |
1449 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1445 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
1450 | 1446 | ||
1447 | int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, | ||
1448 | unsigned char banned_flags) | ||
1449 | { | ||
1450 | struct inet6_ifaddr *ifp; | ||
1451 | int err = -EADDRNOTAVAIL; | ||
1452 | |||
1453 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | ||
1454 | if (ifp->scope == IFA_LINK && | ||
1455 | !(ifp->flags & banned_flags)) { | ||
1456 | *addr = ifp->addr; | ||
1457 | err = 0; | ||
1458 | break; | ||
1459 | } | ||
1460 | } | ||
1461 | return err; | ||
1462 | } | ||
1463 | |||
1451 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1464 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1452 | unsigned char banned_flags) | 1465 | unsigned char banned_flags) |
1453 | { | 1466 | { |
@@ -1457,17 +1470,8 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1457 | rcu_read_lock(); | 1470 | rcu_read_lock(); |
1458 | idev = __in6_dev_get(dev); | 1471 | idev = __in6_dev_get(dev); |
1459 | if (idev) { | 1472 | if (idev) { |
1460 | struct inet6_ifaddr *ifp; | ||
1461 | |||
1462 | read_lock_bh(&idev->lock); | 1473 | read_lock_bh(&idev->lock); |
1463 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | 1474 | err = __ipv6_get_lladdr(idev, addr, banned_flags); |
1464 | if (ifp->scope == IFA_LINK && | ||
1465 | !(ifp->flags & banned_flags)) { | ||
1466 | *addr = ifp->addr; | ||
1467 | err = 0; | ||
1468 | break; | ||
1469 | } | ||
1470 | } | ||
1471 | read_unlock_bh(&idev->lock); | 1475 | read_unlock_bh(&idev->lock); |
1472 | } | 1476 | } |
1473 | rcu_read_unlock(); | 1477 | rcu_read_unlock(); |
@@ -1581,7 +1585,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1581 | { | 1585 | { |
1582 | if (ifp->flags&IFA_F_PERMANENT) { | 1586 | if (ifp->flags&IFA_F_PERMANENT) { |
1583 | spin_lock_bh(&ifp->lock); | 1587 | spin_lock_bh(&ifp->lock); |
1584 | addrconf_del_timer(ifp); | 1588 | addrconf_del_dad_timer(ifp); |
1585 | ifp->flags |= IFA_F_TENTATIVE; | 1589 | ifp->flags |= IFA_F_TENTATIVE; |
1586 | if (dad_failed) | 1590 | if (dad_failed) |
1587 | ifp->flags |= IFA_F_DADFAILED; | 1591 | ifp->flags |= IFA_F_DADFAILED; |
@@ -2402,6 +2406,7 @@ err_exit: | |||
2402 | * Manual configuration of address on an interface | 2406 | * Manual configuration of address on an interface |
2403 | */ | 2407 | */ |
2404 | static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, | 2408 | static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, |
2409 | const struct in6_addr *peer_pfx, | ||
2405 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, | 2410 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, |
2406 | __u32 valid_lft) | 2411 | __u32 valid_lft) |
2407 | { | 2412 | { |
@@ -2457,6 +2462,8 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p | |||
2457 | ifp->valid_lft = valid_lft; | 2462 | ifp->valid_lft = valid_lft; |
2458 | ifp->prefered_lft = prefered_lft; | 2463 | ifp->prefered_lft = prefered_lft; |
2459 | ifp->tstamp = jiffies; | 2464 | ifp->tstamp = jiffies; |
2465 | if (peer_pfx) | ||
2466 | ifp->peer_addr = *peer_pfx; | ||
2460 | spin_unlock_bh(&ifp->lock); | 2467 | spin_unlock_bh(&ifp->lock); |
2461 | 2468 | ||
2462 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, | 2469 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, |
@@ -2500,12 +2507,6 @@ static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *p | |||
2500 | read_unlock_bh(&idev->lock); | 2507 | read_unlock_bh(&idev->lock); |
2501 | 2508 | ||
2502 | ipv6_del_addr(ifp); | 2509 | ipv6_del_addr(ifp); |
2503 | |||
2504 | /* If the last address is deleted administratively, | ||
2505 | disable IPv6 on this interface. | ||
2506 | */ | ||
2507 | if (list_empty(&idev->addr_list)) | ||
2508 | addrconf_ifdown(idev->dev, 1); | ||
2509 | return 0; | 2510 | return 0; |
2510 | } | 2511 | } |
2511 | } | 2512 | } |
@@ -2526,7 +2527,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg) | |||
2526 | return -EFAULT; | 2527 | return -EFAULT; |
2527 | 2528 | ||
2528 | rtnl_lock(); | 2529 | rtnl_lock(); |
2529 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, | 2530 | err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL, |
2530 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, | 2531 | ireq.ifr6_prefixlen, IFA_F_PERMANENT, |
2531 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); | 2532 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); |
2532 | rtnl_unlock(); | 2533 | rtnl_unlock(); |
@@ -2761,8 +2762,6 @@ static void addrconf_gre_config(struct net_device *dev) | |||
2761 | struct inet6_dev *idev; | 2762 | struct inet6_dev *idev; |
2762 | struct in6_addr addr; | 2763 | struct in6_addr addr; |
2763 | 2764 | ||
2764 | pr_info("%s(%s)\n", __func__, dev->name); | ||
2765 | |||
2766 | ASSERT_RTNL(); | 2765 | ASSERT_RTNL(); |
2767 | 2766 | ||
2768 | if ((idev = ipv6_find_idev(dev)) == NULL) { | 2767 | if ((idev = ipv6_find_idev(dev)) == NULL) { |
@@ -2829,9 +2828,9 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2829 | } | 2828 | } |
2830 | 2829 | ||
2831 | static int addrconf_notify(struct notifier_block *this, unsigned long event, | 2830 | static int addrconf_notify(struct notifier_block *this, unsigned long event, |
2832 | void *data) | 2831 | void *ptr) |
2833 | { | 2832 | { |
2834 | struct net_device *dev = (struct net_device *) data; | 2833 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
2835 | struct inet6_dev *idev = __in6_dev_get(dev); | 2834 | struct inet6_dev *idev = __in6_dev_get(dev); |
2836 | int run_pending = 0; | 2835 | int run_pending = 0; |
2837 | int err; | 2836 | int err; |
@@ -3039,7 +3038,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3039 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { | 3038 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { |
3040 | if (ifa->idev == idev) { | 3039 | if (ifa->idev == idev) { |
3041 | hlist_del_init_rcu(&ifa->addr_lst); | 3040 | hlist_del_init_rcu(&ifa->addr_lst); |
3042 | addrconf_del_timer(ifa); | 3041 | addrconf_del_dad_timer(ifa); |
3043 | goto restart; | 3042 | goto restart; |
3044 | } | 3043 | } |
3045 | } | 3044 | } |
@@ -3048,6 +3047,8 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3048 | 3047 | ||
3049 | write_lock_bh(&idev->lock); | 3048 | write_lock_bh(&idev->lock); |
3050 | 3049 | ||
3050 | addrconf_del_rs_timer(idev); | ||
3051 | |||
3051 | /* Step 2: clear flags for stateless addrconf */ | 3052 | /* Step 2: clear flags for stateless addrconf */ |
3052 | if (!how) | 3053 | if (!how) |
3053 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 3054 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
@@ -3077,7 +3078,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3077 | while (!list_empty(&idev->addr_list)) { | 3078 | while (!list_empty(&idev->addr_list)) { |
3078 | ifa = list_first_entry(&idev->addr_list, | 3079 | ifa = list_first_entry(&idev->addr_list, |
3079 | struct inet6_ifaddr, if_list); | 3080 | struct inet6_ifaddr, if_list); |
3080 | addrconf_del_timer(ifa); | 3081 | addrconf_del_dad_timer(ifa); |
3081 | 3082 | ||
3082 | list_del(&ifa->if_list); | 3083 | list_del(&ifa->if_list); |
3083 | 3084 | ||
@@ -3119,10 +3120,10 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3119 | 3120 | ||
3120 | static void addrconf_rs_timer(unsigned long data) | 3121 | static void addrconf_rs_timer(unsigned long data) |
3121 | { | 3122 | { |
3122 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 3123 | struct inet6_dev *idev = (struct inet6_dev *)data; |
3123 | struct inet6_dev *idev = ifp->idev; | 3124 | struct in6_addr lladdr; |
3124 | 3125 | ||
3125 | read_lock(&idev->lock); | 3126 | write_lock(&idev->lock); |
3126 | if (idev->dead || !(idev->if_flags & IF_READY)) | 3127 | if (idev->dead || !(idev->if_flags & IF_READY)) |
3127 | goto out; | 3128 | goto out; |
3128 | 3129 | ||
@@ -3133,18 +3134,19 @@ static void addrconf_rs_timer(unsigned long data) | |||
3133 | if (idev->if_flags & IF_RA_RCVD) | 3134 | if (idev->if_flags & IF_RA_RCVD) |
3134 | goto out; | 3135 | goto out; |
3135 | 3136 | ||
3136 | spin_lock(&ifp->lock); | 3137 | if (idev->rs_probes++ < idev->cnf.rtr_solicits) { |
3137 | if (ifp->probes++ < idev->cnf.rtr_solicits) { | 3138 | if (!__ipv6_get_lladdr(idev, &lladdr, IFA_F_TENTATIVE)) |
3138 | /* The wait after the last probe can be shorter */ | 3139 | ndisc_send_rs(idev->dev, &lladdr, |
3139 | addrconf_mod_timer(ifp, AC_RS, | 3140 | &in6addr_linklocal_allrouters); |
3140 | (ifp->probes == idev->cnf.rtr_solicits) ? | 3141 | else |
3141 | idev->cnf.rtr_solicit_delay : | 3142 | goto out; |
3142 | idev->cnf.rtr_solicit_interval); | ||
3143 | spin_unlock(&ifp->lock); | ||
3144 | 3143 | ||
3145 | ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 3144 | /* The wait after the last probe can be shorter */ |
3145 | addrconf_mod_rs_timer(idev, (idev->rs_probes == | ||
3146 | idev->cnf.rtr_solicits) ? | ||
3147 | idev->cnf.rtr_solicit_delay : | ||
3148 | idev->cnf.rtr_solicit_interval); | ||
3146 | } else { | 3149 | } else { |
3147 | spin_unlock(&ifp->lock); | ||
3148 | /* | 3150 | /* |
3149 | * Note: we do not support deprecated "all on-link" | 3151 | * Note: we do not support deprecated "all on-link" |
3150 | * assumption any longer. | 3152 | * assumption any longer. |
@@ -3153,8 +3155,8 @@ static void addrconf_rs_timer(unsigned long data) | |||
3153 | } | 3155 | } |
3154 | 3156 | ||
3155 | out: | 3157 | out: |
3156 | read_unlock(&idev->lock); | 3158 | write_unlock(&idev->lock); |
3157 | in6_ifa_put(ifp); | 3159 | in6_dev_put(idev); |
3158 | } | 3160 | } |
3159 | 3161 | ||
3160 | /* | 3162 | /* |
@@ -3170,8 +3172,8 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | |||
3170 | else | 3172 | else |
3171 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | 3173 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); |
3172 | 3174 | ||
3173 | ifp->probes = idev->cnf.dad_transmits; | 3175 | ifp->dad_probes = idev->cnf.dad_transmits; |
3174 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | 3176 | addrconf_mod_dad_timer(ifp, rand_num); |
3175 | } | 3177 | } |
3176 | 3178 | ||
3177 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) | 3179 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) |
@@ -3232,40 +3234,40 @@ static void addrconf_dad_timer(unsigned long data) | |||
3232 | struct inet6_dev *idev = ifp->idev; | 3234 | struct inet6_dev *idev = ifp->idev; |
3233 | struct in6_addr mcaddr; | 3235 | struct in6_addr mcaddr; |
3234 | 3236 | ||
3235 | if (!ifp->probes && addrconf_dad_end(ifp)) | 3237 | if (!ifp->dad_probes && addrconf_dad_end(ifp)) |
3236 | goto out; | 3238 | goto out; |
3237 | 3239 | ||
3238 | read_lock(&idev->lock); | 3240 | write_lock(&idev->lock); |
3239 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 3241 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
3240 | read_unlock(&idev->lock); | 3242 | write_unlock(&idev->lock); |
3241 | goto out; | 3243 | goto out; |
3242 | } | 3244 | } |
3243 | 3245 | ||
3244 | spin_lock(&ifp->lock); | 3246 | spin_lock(&ifp->lock); |
3245 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | 3247 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { |
3246 | spin_unlock(&ifp->lock); | 3248 | spin_unlock(&ifp->lock); |
3247 | read_unlock(&idev->lock); | 3249 | write_unlock(&idev->lock); |
3248 | goto out; | 3250 | goto out; |
3249 | } | 3251 | } |
3250 | 3252 | ||
3251 | if (ifp->probes == 0) { | 3253 | if (ifp->dad_probes == 0) { |
3252 | /* | 3254 | /* |
3253 | * DAD was successful | 3255 | * DAD was successful |
3254 | */ | 3256 | */ |
3255 | 3257 | ||
3256 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 3258 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
3257 | spin_unlock(&ifp->lock); | 3259 | spin_unlock(&ifp->lock); |
3258 | read_unlock(&idev->lock); | 3260 | write_unlock(&idev->lock); |
3259 | 3261 | ||
3260 | addrconf_dad_completed(ifp); | 3262 | addrconf_dad_completed(ifp); |
3261 | 3263 | ||
3262 | goto out; | 3264 | goto out; |
3263 | } | 3265 | } |
3264 | 3266 | ||
3265 | ifp->probes--; | 3267 | ifp->dad_probes--; |
3266 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 3268 | addrconf_mod_dad_timer(ifp, ifp->idev->nd_parms->retrans_time); |
3267 | spin_unlock(&ifp->lock); | 3269 | spin_unlock(&ifp->lock); |
3268 | read_unlock(&idev->lock); | 3270 | write_unlock(&idev->lock); |
3269 | 3271 | ||
3270 | /* send a neighbour solicitation for our addr */ | 3272 | /* send a neighbour solicitation for our addr */ |
3271 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 3273 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
@@ -3277,6 +3279,10 @@ out: | |||
3277 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 3279 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
3278 | { | 3280 | { |
3279 | struct net_device *dev = ifp->idev->dev; | 3281 | struct net_device *dev = ifp->idev->dev; |
3282 | struct in6_addr lladdr; | ||
3283 | bool send_rs, send_mld; | ||
3284 | |||
3285 | addrconf_del_dad_timer(ifp); | ||
3280 | 3286 | ||
3281 | /* | 3287 | /* |
3282 | * Configure the address for reception. Now it is valid. | 3288 | * Configure the address for reception. Now it is valid. |
@@ -3288,22 +3294,41 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
3288 | router advertisements, start sending router solicitations. | 3294 | router advertisements, start sending router solicitations. |
3289 | */ | 3295 | */ |
3290 | 3296 | ||
3291 | if (ipv6_accept_ra(ifp->idev) && | 3297 | read_lock_bh(&ifp->idev->lock); |
3292 | ifp->idev->cnf.rtr_solicits > 0 && | 3298 | spin_lock(&ifp->lock); |
3293 | (dev->flags&IFF_LOOPBACK) == 0 && | 3299 | send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL && |
3294 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { | 3300 | ifp->idev->valid_ll_addr_cnt == 1; |
3301 | send_rs = send_mld && | ||
3302 | ipv6_accept_ra(ifp->idev) && | ||
3303 | ifp->idev->cnf.rtr_solicits > 0 && | ||
3304 | (dev->flags&IFF_LOOPBACK) == 0; | ||
3305 | spin_unlock(&ifp->lock); | ||
3306 | read_unlock_bh(&ifp->idev->lock); | ||
3307 | |||
3308 | /* While dad is in progress mld report's source address is in6_addrany. | ||
3309 | * Resend with proper ll now. | ||
3310 | */ | ||
3311 | if (send_mld) | ||
3312 | ipv6_mc_dad_complete(ifp->idev); | ||
3313 | |||
3314 | if (send_rs) { | ||
3295 | /* | 3315 | /* |
3296 | * If a host as already performed a random delay | 3316 | * If a host as already performed a random delay |
3297 | * [...] as part of DAD [...] there is no need | 3317 | * [...] as part of DAD [...] there is no need |
3298 | * to delay again before sending the first RS | 3318 | * to delay again before sending the first RS |
3299 | */ | 3319 | */ |
3300 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 3320 | if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE)) |
3321 | return; | ||
3322 | ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters); | ||
3301 | 3323 | ||
3302 | spin_lock_bh(&ifp->lock); | 3324 | write_lock_bh(&ifp->idev->lock); |
3303 | ifp->probes = 1; | 3325 | spin_lock(&ifp->lock); |
3326 | ifp->idev->rs_probes = 1; | ||
3304 | ifp->idev->if_flags |= IF_RS_SENT; | 3327 | ifp->idev->if_flags |= IF_RS_SENT; |
3305 | addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval); | 3328 | addrconf_mod_rs_timer(ifp->idev, |
3306 | spin_unlock_bh(&ifp->lock); | 3329 | ifp->idev->cnf.rtr_solicit_interval); |
3330 | spin_unlock(&ifp->lock); | ||
3331 | write_unlock_bh(&ifp->idev->lock); | ||
3307 | } | 3332 | } |
3308 | } | 3333 | } |
3309 | 3334 | ||
@@ -3615,18 +3640,20 @@ restart: | |||
3615 | rcu_read_unlock_bh(); | 3640 | rcu_read_unlock_bh(); |
3616 | } | 3641 | } |
3617 | 3642 | ||
3618 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3643 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, |
3644 | struct in6_addr **peer_pfx) | ||
3619 | { | 3645 | { |
3620 | struct in6_addr *pfx = NULL; | 3646 | struct in6_addr *pfx = NULL; |
3621 | 3647 | ||
3648 | *peer_pfx = NULL; | ||
3649 | |||
3622 | if (addr) | 3650 | if (addr) |
3623 | pfx = nla_data(addr); | 3651 | pfx = nla_data(addr); |
3624 | 3652 | ||
3625 | if (local) { | 3653 | if (local) { |
3626 | if (pfx && nla_memcmp(local, pfx, sizeof(*pfx))) | 3654 | if (pfx && nla_memcmp(local, pfx, sizeof(*pfx))) |
3627 | pfx = NULL; | 3655 | *peer_pfx = pfx; |
3628 | else | 3656 | pfx = nla_data(local); |
3629 | pfx = nla_data(local); | ||
3630 | } | 3657 | } |
3631 | 3658 | ||
3632 | return pfx; | 3659 | return pfx; |
@@ -3644,7 +3671,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3644 | struct net *net = sock_net(skb->sk); | 3671 | struct net *net = sock_net(skb->sk); |
3645 | struct ifaddrmsg *ifm; | 3672 | struct ifaddrmsg *ifm; |
3646 | struct nlattr *tb[IFA_MAX+1]; | 3673 | struct nlattr *tb[IFA_MAX+1]; |
3647 | struct in6_addr *pfx; | 3674 | struct in6_addr *pfx, *peer_pfx; |
3648 | int err; | 3675 | int err; |
3649 | 3676 | ||
3650 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); | 3677 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); |
@@ -3652,7 +3679,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3652 | return err; | 3679 | return err; |
3653 | 3680 | ||
3654 | ifm = nlmsg_data(nlh); | 3681 | ifm = nlmsg_data(nlh); |
3655 | pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); | 3682 | pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx); |
3656 | if (pfx == NULL) | 3683 | if (pfx == NULL) |
3657 | return -EINVAL; | 3684 | return -EINVAL; |
3658 | 3685 | ||
@@ -3710,7 +3737,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3710 | struct net *net = sock_net(skb->sk); | 3737 | struct net *net = sock_net(skb->sk); |
3711 | struct ifaddrmsg *ifm; | 3738 | struct ifaddrmsg *ifm; |
3712 | struct nlattr *tb[IFA_MAX+1]; | 3739 | struct nlattr *tb[IFA_MAX+1]; |
3713 | struct in6_addr *pfx; | 3740 | struct in6_addr *pfx, *peer_pfx; |
3714 | struct inet6_ifaddr *ifa; | 3741 | struct inet6_ifaddr *ifa; |
3715 | struct net_device *dev; | 3742 | struct net_device *dev; |
3716 | u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME; | 3743 | u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME; |
@@ -3722,7 +3749,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3722 | return err; | 3749 | return err; |
3723 | 3750 | ||
3724 | ifm = nlmsg_data(nlh); | 3751 | ifm = nlmsg_data(nlh); |
3725 | pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); | 3752 | pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx); |
3726 | if (pfx == NULL) | 3753 | if (pfx == NULL) |
3727 | return -EINVAL; | 3754 | return -EINVAL; |
3728 | 3755 | ||
@@ -3750,7 +3777,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3750 | * It would be best to check for !NLM_F_CREATE here but | 3777 | * It would be best to check for !NLM_F_CREATE here but |
3751 | * userspace alreay relies on not having to provide this. | 3778 | * userspace alreay relies on not having to provide this. |
3752 | */ | 3779 | */ |
3753 | return inet6_addr_add(net, ifm->ifa_index, pfx, | 3780 | return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx, |
3754 | ifm->ifa_prefixlen, ifa_flags, | 3781 | ifm->ifa_prefixlen, ifa_flags, |
3755 | preferred_lft, valid_lft); | 3782 | preferred_lft, valid_lft); |
3756 | } | 3783 | } |
@@ -3807,6 +3834,7 @@ static inline int rt_scope(int ifa_scope) | |||
3807 | static inline int inet6_ifaddr_msgsize(void) | 3834 | static inline int inet6_ifaddr_msgsize(void) |
3808 | { | 3835 | { |
3809 | return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) | 3836 | return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) |
3837 | + nla_total_size(16) /* IFA_LOCAL */ | ||
3810 | + nla_total_size(16) /* IFA_ADDRESS */ | 3838 | + nla_total_size(16) /* IFA_ADDRESS */ |
3811 | + nla_total_size(sizeof(struct ifa_cacheinfo)); | 3839 | + nla_total_size(sizeof(struct ifa_cacheinfo)); |
3812 | } | 3840 | } |
@@ -3845,13 +3873,22 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3845 | valid = INFINITY_LIFE_TIME; | 3873 | valid = INFINITY_LIFE_TIME; |
3846 | } | 3874 | } |
3847 | 3875 | ||
3848 | if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 || | 3876 | if (!ipv6_addr_any(&ifa->peer_addr)) { |
3849 | put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) { | 3877 | if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 || |
3850 | nlmsg_cancel(skb, nlh); | 3878 | nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0) |
3851 | return -EMSGSIZE; | 3879 | goto error; |
3852 | } | 3880 | } else |
3881 | if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0) | ||
3882 | goto error; | ||
3883 | |||
3884 | if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) | ||
3885 | goto error; | ||
3853 | 3886 | ||
3854 | return nlmsg_end(skb, nlh); | 3887 | return nlmsg_end(skb, nlh); |
3888 | |||
3889 | error: | ||
3890 | nlmsg_cancel(skb, nlh); | ||
3891 | return -EMSGSIZE; | ||
3855 | } | 3892 | } |
3856 | 3893 | ||
3857 | static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, | 3894 | static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, |
@@ -4051,7 +4088,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh) | |||
4051 | struct net *net = sock_net(in_skb->sk); | 4088 | struct net *net = sock_net(in_skb->sk); |
4052 | struct ifaddrmsg *ifm; | 4089 | struct ifaddrmsg *ifm; |
4053 | struct nlattr *tb[IFA_MAX+1]; | 4090 | struct nlattr *tb[IFA_MAX+1]; |
4054 | struct in6_addr *addr = NULL; | 4091 | struct in6_addr *addr = NULL, *peer; |
4055 | struct net_device *dev = NULL; | 4092 | struct net_device *dev = NULL; |
4056 | struct inet6_ifaddr *ifa; | 4093 | struct inet6_ifaddr *ifa; |
4057 | struct sk_buff *skb; | 4094 | struct sk_buff *skb; |
@@ -4061,7 +4098,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh) | |||
4061 | if (err < 0) | 4098 | if (err < 0) |
4062 | goto errout; | 4099 | goto errout; |
4063 | 4100 | ||
4064 | addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); | 4101 | addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer); |
4065 | if (addr == NULL) { | 4102 | if (addr == NULL) { |
4066 | err = -EINVAL; | 4103 | err = -EINVAL; |
4067 | goto errout; | 4104 | goto errout; |
@@ -4339,8 +4376,11 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4339 | 4376 | ||
4340 | write_lock_bh(&idev->lock); | 4377 | write_lock_bh(&idev->lock); |
4341 | 4378 | ||
4342 | if (update_rs) | 4379 | if (update_rs) { |
4343 | idev->if_flags |= IF_RS_SENT; | 4380 | idev->if_flags |= IF_RS_SENT; |
4381 | idev->rs_probes = 1; | ||
4382 | addrconf_mod_rs_timer(idev, idev->cnf.rtr_solicit_interval); | ||
4383 | } | ||
4344 | 4384 | ||
4345 | /* Well, that's kinda nasty ... */ | 4385 | /* Well, that's kinda nasty ... */ |
4346 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | 4386 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
@@ -4353,6 +4393,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4353 | } | 4393 | } |
4354 | 4394 | ||
4355 | write_unlock_bh(&idev->lock); | 4395 | write_unlock_bh(&idev->lock); |
4396 | addrconf_verify(0); | ||
4356 | return 0; | 4397 | return 0; |
4357 | } | 4398 | } |
4358 | 4399 | ||
@@ -4550,6 +4591,19 @@ errout: | |||
4550 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); | 4591 | rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); |
4551 | } | 4592 | } |
4552 | 4593 | ||
4594 | static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count) | ||
4595 | { | ||
4596 | write_lock_bh(&ifp->idev->lock); | ||
4597 | spin_lock(&ifp->lock); | ||
4598 | if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC| | ||
4599 | IFA_F_DADFAILED)) == IFA_F_PERMANENT) && | ||
4600 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) | ||
4601 | ifp->idev->valid_ll_addr_cnt += count; | ||
4602 | WARN_ON(ifp->idev->valid_ll_addr_cnt < 0); | ||
4603 | spin_unlock(&ifp->lock); | ||
4604 | write_unlock_bh(&ifp->idev->lock); | ||
4605 | } | ||
4606 | |||
4553 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4607 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
4554 | { | 4608 | { |
4555 | struct net *net = dev_net(ifp->idev->dev); | 4609 | struct net *net = dev_net(ifp->idev->dev); |
@@ -4558,6 +4612,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4558 | 4612 | ||
4559 | switch (event) { | 4613 | switch (event) { |
4560 | case RTM_NEWADDR: | 4614 | case RTM_NEWADDR: |
4615 | update_valid_ll_addr_cnt(ifp, 1); | ||
4616 | |||
4561 | /* | 4617 | /* |
4562 | * If the address was optimistic | 4618 | * If the address was optimistic |
4563 | * we inserted the route at the start of | 4619 | * we inserted the route at the start of |
@@ -4568,11 +4624,28 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4568 | ip6_ins_rt(ifp->rt); | 4624 | ip6_ins_rt(ifp->rt); |
4569 | if (ifp->idev->cnf.forwarding) | 4625 | if (ifp->idev->cnf.forwarding) |
4570 | addrconf_join_anycast(ifp); | 4626 | addrconf_join_anycast(ifp); |
4627 | if (!ipv6_addr_any(&ifp->peer_addr)) | ||
4628 | addrconf_prefix_route(&ifp->peer_addr, 128, | ||
4629 | ifp->idev->dev, 0, 0); | ||
4571 | break; | 4630 | break; |
4572 | case RTM_DELADDR: | 4631 | case RTM_DELADDR: |
4632 | update_valid_ll_addr_cnt(ifp, -1); | ||
4633 | |||
4573 | if (ifp->idev->cnf.forwarding) | 4634 | if (ifp->idev->cnf.forwarding) |
4574 | addrconf_leave_anycast(ifp); | 4635 | addrconf_leave_anycast(ifp); |
4575 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4636 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4637 | if (!ipv6_addr_any(&ifp->peer_addr)) { | ||
4638 | struct rt6_info *rt; | ||
4639 | struct net_device *dev = ifp->idev->dev; | ||
4640 | |||
4641 | rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL, | ||
4642 | dev->ifindex, 1); | ||
4643 | if (rt) { | ||
4644 | dst_hold(&rt->dst); | ||
4645 | if (ip6_del_rt(rt)) | ||
4646 | dst_free(&rt->dst); | ||
4647 | } | ||
4648 | } | ||
4576 | dst_hold(&ifp->rt->dst); | 4649 | dst_hold(&ifp->rt->dst); |
4577 | 4650 | ||
4578 | if (ip6_del_rt(ifp->rt)) | 4651 | if (ip6_del_rt(ifp->rt)) |
@@ -4593,13 +4666,13 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4593 | #ifdef CONFIG_SYSCTL | 4666 | #ifdef CONFIG_SYSCTL |
4594 | 4667 | ||
4595 | static | 4668 | static |
4596 | int addrconf_sysctl_forward(ctl_table *ctl, int write, | 4669 | int addrconf_sysctl_forward(struct ctl_table *ctl, int write, |
4597 | void __user *buffer, size_t *lenp, loff_t *ppos) | 4670 | void __user *buffer, size_t *lenp, loff_t *ppos) |
4598 | { | 4671 | { |
4599 | int *valp = ctl->data; | 4672 | int *valp = ctl->data; |
4600 | int val = *valp; | 4673 | int val = *valp; |
4601 | loff_t pos = *ppos; | 4674 | loff_t pos = *ppos; |
4602 | ctl_table lctl; | 4675 | struct ctl_table lctl; |
4603 | int ret; | 4676 | int ret; |
4604 | 4677 | ||
4605 | /* | 4678 | /* |
@@ -4620,13 +4693,16 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, | |||
4620 | 4693 | ||
4621 | static void dev_disable_change(struct inet6_dev *idev) | 4694 | static void dev_disable_change(struct inet6_dev *idev) |
4622 | { | 4695 | { |
4696 | struct netdev_notifier_info info; | ||
4697 | |||
4623 | if (!idev || !idev->dev) | 4698 | if (!idev || !idev->dev) |
4624 | return; | 4699 | return; |
4625 | 4700 | ||
4701 | netdev_notifier_info_init(&info, idev->dev); | ||
4626 | if (idev->cnf.disable_ipv6) | 4702 | if (idev->cnf.disable_ipv6) |
4627 | addrconf_notify(NULL, NETDEV_DOWN, idev->dev); | 4703 | addrconf_notify(NULL, NETDEV_DOWN, &info); |
4628 | else | 4704 | else |
4629 | addrconf_notify(NULL, NETDEV_UP, idev->dev); | 4705 | addrconf_notify(NULL, NETDEV_UP, &info); |
4630 | } | 4706 | } |
4631 | 4707 | ||
4632 | static void addrconf_disable_change(struct net *net, __s32 newf) | 4708 | static void addrconf_disable_change(struct net *net, __s32 newf) |
@@ -4675,13 +4751,13 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) | |||
4675 | } | 4751 | } |
4676 | 4752 | ||
4677 | static | 4753 | static |
4678 | int addrconf_sysctl_disable(ctl_table *ctl, int write, | 4754 | int addrconf_sysctl_disable(struct ctl_table *ctl, int write, |
4679 | void __user *buffer, size_t *lenp, loff_t *ppos) | 4755 | void __user *buffer, size_t *lenp, loff_t *ppos) |
4680 | { | 4756 | { |
4681 | int *valp = ctl->data; | 4757 | int *valp = ctl->data; |
4682 | int val = *valp; | 4758 | int val = *valp; |
4683 | loff_t pos = *ppos; | 4759 | loff_t pos = *ppos; |
4684 | ctl_table lctl; | 4760 | struct ctl_table lctl; |
4685 | int ret; | 4761 | int ret; |
4686 | 4762 | ||
4687 | /* | 4763 | /* |
@@ -4703,7 +4779,7 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, | |||
4703 | static struct addrconf_sysctl_table | 4779 | static struct addrconf_sysctl_table |
4704 | { | 4780 | { |
4705 | struct ctl_table_header *sysctl_header; | 4781 | struct ctl_table_header *sysctl_header; |
4706 | ctl_table addrconf_vars[DEVCONF_MAX+1]; | 4782 | struct ctl_table addrconf_vars[DEVCONF_MAX+1]; |
4707 | } addrconf_sysctl __read_mostly = { | 4783 | } addrconf_sysctl __read_mostly = { |
4708 | .sysctl_header = NULL, | 4784 | .sysctl_header = NULL, |
4709 | .addrconf_vars = { | 4785 | .addrconf_vars = { |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 72104562c864..d2f87427244b 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include <linux/export.h> | 6 | #include <linux/export.h> |
7 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
8 | #include <net/addrconf.h> | ||
8 | 9 | ||
9 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) | 10 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
10 | 11 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index ab5c7ad482cd..a5ac969aeefe 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <net/udp.h> | 49 | #include <net/udp.h> |
50 | #include <net/udplite.h> | 50 | #include <net/udplite.h> |
51 | #include <net/tcp.h> | 51 | #include <net/tcp.h> |
52 | #include <net/ping.h> | ||
52 | #include <net/protocol.h> | 53 | #include <net/protocol.h> |
53 | #include <net/inet_common.h> | 54 | #include <net/inet_common.h> |
54 | #include <net/route.h> | 55 | #include <net/route.h> |
@@ -840,6 +841,9 @@ static int __init inet6_init(void) | |||
840 | if (err) | 841 | if (err) |
841 | goto out_unregister_udplite_proto; | 842 | goto out_unregister_udplite_proto; |
842 | 843 | ||
844 | err = proto_register(&pingv6_prot, 1); | ||
845 | if (err) | ||
846 | goto out_unregister_ping_proto; | ||
843 | 847 | ||
844 | /* We MUST register RAW sockets before we create the ICMP6, | 848 | /* We MUST register RAW sockets before we create the ICMP6, |
845 | * IGMP6, or NDISC control sockets. | 849 | * IGMP6, or NDISC control sockets. |
@@ -930,6 +934,10 @@ static int __init inet6_init(void) | |||
930 | if (err) | 934 | if (err) |
931 | goto ipv6_packet_fail; | 935 | goto ipv6_packet_fail; |
932 | 936 | ||
937 | err = pingv6_init(); | ||
938 | if (err) | ||
939 | goto pingv6_fail; | ||
940 | |||
933 | #ifdef CONFIG_SYSCTL | 941 | #ifdef CONFIG_SYSCTL |
934 | err = ipv6_sysctl_register(); | 942 | err = ipv6_sysctl_register(); |
935 | if (err) | 943 | if (err) |
@@ -942,6 +950,8 @@ out: | |||
942 | sysctl_fail: | 950 | sysctl_fail: |
943 | ipv6_packet_cleanup(); | 951 | ipv6_packet_cleanup(); |
944 | #endif | 952 | #endif |
953 | pingv6_fail: | ||
954 | pingv6_exit(); | ||
945 | ipv6_packet_fail: | 955 | ipv6_packet_fail: |
946 | tcpv6_exit(); | 956 | tcpv6_exit(); |
947 | tcpv6_fail: | 957 | tcpv6_fail: |
@@ -985,6 +995,8 @@ register_pernet_fail: | |||
985 | rtnl_unregister_all(PF_INET6); | 995 | rtnl_unregister_all(PF_INET6); |
986 | out_sock_register_fail: | 996 | out_sock_register_fail: |
987 | rawv6_exit(); | 997 | rawv6_exit(); |
998 | out_unregister_ping_proto: | ||
999 | proto_unregister(&pingv6_prot); | ||
988 | out_unregister_raw_proto: | 1000 | out_unregister_raw_proto: |
989 | proto_unregister(&rawv6_prot); | 1001 | proto_unregister(&rawv6_prot); |
990 | out_unregister_udplite_proto: | 1002 | out_unregister_udplite_proto: |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 4b56cbbc7890..197e6f4a2b74 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -879,3 +879,30 @@ exit_f: | |||
879 | return err; | 879 | return err; |
880 | } | 880 | } |
881 | EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); | 881 | EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); |
882 | |||
883 | void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, | ||
884 | __u16 srcp, __u16 destp, int bucket) | ||
885 | { | ||
886 | struct ipv6_pinfo *np = inet6_sk(sp); | ||
887 | const struct in6_addr *dest, *src; | ||
888 | |||
889 | dest = &np->daddr; | ||
890 | src = &np->rcv_saddr; | ||
891 | seq_printf(seq, | ||
892 | "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | ||
893 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", | ||
894 | bucket, | ||
895 | src->s6_addr32[0], src->s6_addr32[1], | ||
896 | src->s6_addr32[2], src->s6_addr32[3], srcp, | ||
897 | dest->s6_addr32[0], dest->s6_addr32[1], | ||
898 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | ||
899 | sp->sk_state, | ||
900 | sk_wmem_alloc_get(sp), | ||
901 | sk_rmem_alloc_get(sp), | ||
902 | 0, 0L, 0, | ||
903 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | ||
904 | 0, | ||
905 | sock_i_ino(sp), | ||
906 | atomic_read(&sp->sk_refcnt), sp, | ||
907 | atomic_read(&sp->sk_drops)); | ||
908 | } | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index c5e83fae4df4..140748debc4a 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
@@ -115,7 +115,7 @@ EXPORT_SYMBOL(ipv6_skip_exthdr); | |||
115 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | 115 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) |
116 | { | 116 | { |
117 | const unsigned char *nh = skb_network_header(skb); | 117 | const unsigned char *nh = skb_network_header(skb); |
118 | int packet_len = skb->tail - skb->network_header; | 118 | int packet_len = skb_tail_pointer(skb) - skb_network_header(skb); |
119 | struct ipv6_opt_hdr *hdr; | 119 | struct ipv6_opt_hdr *hdr; |
120 | int len; | 120 | int len; |
121 | 121 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4ff0a42b8c7..7cfc8d284870 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -57,6 +57,7 @@ | |||
57 | 57 | ||
58 | #include <net/ipv6.h> | 58 | #include <net/ipv6.h> |
59 | #include <net/ip6_checksum.h> | 59 | #include <net/ip6_checksum.h> |
60 | #include <net/ping.h> | ||
60 | #include <net/protocol.h> | 61 | #include <net/protocol.h> |
61 | #include <net/raw.h> | 62 | #include <net/raw.h> |
62 | #include <net/rawv6.h> | 63 | #include <net/rawv6.h> |
@@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net) | |||
84 | static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 85 | static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
85 | u8 type, u8 code, int offset, __be32 info) | 86 | u8 type, u8 code, int offset, __be32 info) |
86 | { | 87 | { |
88 | /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ | ||
89 | struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); | ||
87 | struct net *net = dev_net(skb->dev); | 90 | struct net *net = dev_net(skb->dev); |
88 | 91 | ||
89 | if (type == ICMPV6_PKT_TOOBIG) | 92 | if (type == ICMPV6_PKT_TOOBIG) |
90 | ip6_update_pmtu(skb, net, info, 0, 0); | 93 | ip6_update_pmtu(skb, net, info, 0, 0); |
91 | else if (type == NDISC_REDIRECT) | 94 | else if (type == NDISC_REDIRECT) |
92 | ip6_redirect(skb, net, 0, 0); | 95 | ip6_redirect(skb, net, 0, 0); |
96 | |||
97 | if (!(type & ICMPV6_INFOMSG_MASK)) | ||
98 | if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) | ||
99 | ping_err(skb, offset, info); | ||
93 | } | 100 | } |
94 | 101 | ||
95 | static int icmpv6_rcv(struct sk_buff *skb); | 102 | static int icmpv6_rcv(struct sk_buff *skb); |
@@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset) | |||
224 | return (*op & 0xC0) == 0x80; | 231 | return (*op & 0xC0) == 0x80; |
225 | } | 232 | } |
226 | 233 | ||
227 | static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) | 234 | int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, |
235 | struct icmp6hdr *thdr, int len) | ||
228 | { | 236 | { |
229 | struct sk_buff *skb; | 237 | struct sk_buff *skb; |
230 | struct icmp6hdr *icmp6h; | 238 | struct icmp6hdr *icmp6h; |
@@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
307 | static inline void mip6_addr_swap(struct sk_buff *skb) {} | 315 | static inline void mip6_addr_swap(struct sk_buff *skb) {} |
308 | #endif | 316 | #endif |
309 | 317 | ||
310 | static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, | 318 | struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, |
311 | struct sock *sk, struct flowi6 *fl6) | 319 | struct sock *sk, struct flowi6 *fl6) |
312 | { | 320 | { |
313 | struct dst_entry *dst, *dst2; | 321 | struct dst_entry *dst, *dst2; |
314 | struct flowi6 fl2; | 322 | struct flowi6 fl2; |
@@ -391,7 +399,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
391 | int err = 0; | 399 | int err = 0; |
392 | 400 | ||
393 | if ((u8 *)hdr < skb->head || | 401 | if ((u8 *)hdr < skb->head || |
394 | (skb->network_header + sizeof(*hdr)) > skb->tail) | 402 | (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb)) |
395 | return; | 403 | return; |
396 | 404 | ||
397 | /* | 405 | /* |
@@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
697 | skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, | 705 | skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, |
698 | IPPROTO_ICMPV6, 0)); | 706 | IPPROTO_ICMPV6, 0)); |
699 | if (__skb_checksum_complete(skb)) { | 707 | if (__skb_checksum_complete(skb)) { |
700 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", | 708 | LIMIT_NETDEBUG(KERN_DEBUG |
709 | "ICMPv6 checksum failed [%pI6c > %pI6c]\n", | ||
701 | saddr, daddr); | 710 | saddr, daddr); |
702 | goto csum_error; | 711 | goto csum_error; |
703 | } | 712 | } |
@@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
718 | break; | 727 | break; |
719 | 728 | ||
720 | case ICMPV6_ECHO_REPLY: | 729 | case ICMPV6_ECHO_REPLY: |
721 | /* we couldn't care less */ | 730 | ping_rcv(skb); |
722 | break; | 731 | break; |
723 | 732 | ||
724 | case ICMPV6_PKT_TOOBIG: | 733 | case ICMPV6_PKT_TOOBIG: |
@@ -967,7 +976,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err) | |||
967 | EXPORT_SYMBOL(icmpv6_err_convert); | 976 | EXPORT_SYMBOL(icmpv6_err_convert); |
968 | 977 | ||
969 | #ifdef CONFIG_SYSCTL | 978 | #ifdef CONFIG_SYSCTL |
970 | ctl_table ipv6_icmp_table_template[] = { | 979 | struct ctl_table ipv6_icmp_table_template[] = { |
971 | { | 980 | { |
972 | .procname = "ratelimit", | 981 | .procname = "ratelimit", |
973 | .data = &init_net.ipv6.sysctl.icmpv6_time, | 982 | .data = &init_net.ipv6.sysctl.icmpv6_time, |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 71b766ee821d..a263b990ee11 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -98,6 +98,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
98 | SKB_GSO_TCP_ECN | | 98 | SKB_GSO_TCP_ECN | |
99 | SKB_GSO_GRE | | 99 | SKB_GSO_GRE | |
100 | SKB_GSO_UDP_TUNNEL | | 100 | SKB_GSO_UDP_TUNNEL | |
101 | SKB_GSO_MPLS | | ||
101 | SKB_GSO_TCPV6 | | 102 | SKB_GSO_TCPV6 | |
102 | 0))) | 103 | 0))) |
103 | goto out; | 104 | goto out; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d5d20cde8d92..6e3ddf806ec2 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1098,11 +1098,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | |||
1098 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | 1098 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | static void ip6_append_data_mtu(int *mtu, | 1101 | static void ip6_append_data_mtu(unsigned int *mtu, |
1102 | int *maxfraglen, | 1102 | int *maxfraglen, |
1103 | unsigned int fragheaderlen, | 1103 | unsigned int fragheaderlen, |
1104 | struct sk_buff *skb, | 1104 | struct sk_buff *skb, |
1105 | struct rt6_info *rt) | 1105 | struct rt6_info *rt, |
1106 | bool pmtuprobe) | ||
1106 | { | 1107 | { |
1107 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { | 1108 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { |
1108 | if (skb == NULL) { | 1109 | if (skb == NULL) { |
@@ -1114,7 +1115,9 @@ static void ip6_append_data_mtu(int *mtu, | |||
1114 | * this fragment is not first, the headers | 1115 | * this fragment is not first, the headers |
1115 | * space is regarded as data space. | 1116 | * space is regarded as data space. |
1116 | */ | 1117 | */ |
1117 | *mtu = dst_mtu(rt->dst.path); | 1118 | *mtu = min(*mtu, pmtuprobe ? |
1119 | rt->dst.dev->mtu : | ||
1120 | dst_mtu(rt->dst.path)); | ||
1118 | } | 1121 | } |
1119 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) | 1122 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) |
1120 | + fragheaderlen - sizeof(struct frag_hdr); | 1123 | + fragheaderlen - sizeof(struct frag_hdr); |
@@ -1131,11 +1134,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1131 | struct ipv6_pinfo *np = inet6_sk(sk); | 1134 | struct ipv6_pinfo *np = inet6_sk(sk); |
1132 | struct inet_cork *cork; | 1135 | struct inet_cork *cork; |
1133 | struct sk_buff *skb, *skb_prev = NULL; | 1136 | struct sk_buff *skb, *skb_prev = NULL; |
1134 | unsigned int maxfraglen, fragheaderlen; | 1137 | unsigned int maxfraglen, fragheaderlen, mtu; |
1135 | int exthdrlen; | 1138 | int exthdrlen; |
1136 | int dst_exthdrlen; | 1139 | int dst_exthdrlen; |
1137 | int hh_len; | 1140 | int hh_len; |
1138 | int mtu; | ||
1139 | int copy; | 1141 | int copy; |
1140 | int err; | 1142 | int err; |
1141 | int offset = 0; | 1143 | int offset = 0; |
@@ -1292,7 +1294,9 @@ alloc_new_skb: | |||
1292 | /* update mtu and maxfraglen if necessary */ | 1294 | /* update mtu and maxfraglen if necessary */ |
1293 | if (skb == NULL || skb_prev == NULL) | 1295 | if (skb == NULL || skb_prev == NULL) |
1294 | ip6_append_data_mtu(&mtu, &maxfraglen, | 1296 | ip6_append_data_mtu(&mtu, &maxfraglen, |
1295 | fragheaderlen, skb, rt); | 1297 | fragheaderlen, skb, rt, |
1298 | np->pmtudisc == | ||
1299 | IPV6_PMTUDISC_PROBE); | ||
1296 | 1300 | ||
1297 | skb_prev = skb; | 1301 | skb_prev = skb; |
1298 | 1302 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 241fb8ad9fcf..583e8d435f9a 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1319,7 +1319,7 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc, | |||
1319 | static int ip6mr_device_event(struct notifier_block *this, | 1319 | static int ip6mr_device_event(struct notifier_block *this, |
1320 | unsigned long event, void *ptr) | 1320 | unsigned long event, void *ptr) |
1321 | { | 1321 | { |
1322 | struct net_device *dev = ptr; | 1322 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
1323 | struct net *net = dev_net(dev); | 1323 | struct net *net = dev_net(dev); |
1324 | struct mr6_table *mrt; | 1324 | struct mr6_table *mrt; |
1325 | struct mif_device *v; | 1325 | struct mif_device *v; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index bfa6cc36ef2a..99cd65c715cd 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -999,6 +999,14 @@ static void mld_ifc_start_timer(struct inet6_dev *idev, int delay) | |||
999 | in6_dev_hold(idev); | 999 | in6_dev_hold(idev); |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | static void mld_dad_start_timer(struct inet6_dev *idev, int delay) | ||
1003 | { | ||
1004 | int tv = net_random() % delay; | ||
1005 | |||
1006 | if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2)) | ||
1007 | in6_dev_hold(idev); | ||
1008 | } | ||
1009 | |||
1002 | /* | 1010 | /* |
1003 | * IGMP handling (alias multicast ICMPv6 messages) | 1011 | * IGMP handling (alias multicast ICMPv6 messages) |
1004 | */ | 1012 | */ |
@@ -1343,8 +1351,9 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb, | |||
1343 | hdr->daddr = *daddr; | 1351 | hdr->daddr = *daddr; |
1344 | } | 1352 | } |
1345 | 1353 | ||
1346 | static struct sk_buff *mld_newpack(struct net_device *dev, int size) | 1354 | static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) |
1347 | { | 1355 | { |
1356 | struct net_device *dev = idev->dev; | ||
1348 | struct net *net = dev_net(dev); | 1357 | struct net *net = dev_net(dev); |
1349 | struct sock *sk = net->ipv6.igmp_sk; | 1358 | struct sock *sk = net->ipv6.igmp_sk; |
1350 | struct sk_buff *skb; | 1359 | struct sk_buff *skb; |
@@ -1369,7 +1378,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1369 | 1378 | ||
1370 | skb_reserve(skb, hlen); | 1379 | skb_reserve(skb, hlen); |
1371 | 1380 | ||
1372 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { | 1381 | if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { |
1373 | /* <draft-ietf-magma-mld-source-05.txt>: | 1382 | /* <draft-ietf-magma-mld-source-05.txt>: |
1374 | * use unspecified address as the source address | 1383 | * use unspecified address as the source address |
1375 | * when a valid link-local address is not available. | 1384 | * when a valid link-local address is not available. |
@@ -1409,8 +1418,9 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1409 | idev = __in6_dev_get(skb->dev); | 1418 | idev = __in6_dev_get(skb->dev); |
1410 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1419 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
1411 | 1420 | ||
1412 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); | 1421 | payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) - |
1413 | mldlen = skb->tail - skb->transport_header; | 1422 | sizeof(*pip6); |
1423 | mldlen = skb_tail_pointer(skb) - skb_transport_header(skb); | ||
1414 | pip6->payload_len = htons(payload_len); | 1424 | pip6->payload_len = htons(payload_len); |
1415 | 1425 | ||
1416 | pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1426 | pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
@@ -1465,7 +1475,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1465 | struct mld2_grec *pgr; | 1475 | struct mld2_grec *pgr; |
1466 | 1476 | ||
1467 | if (!skb) | 1477 | if (!skb) |
1468 | skb = mld_newpack(dev, dev->mtu); | 1478 | skb = mld_newpack(pmc->idev, dev->mtu); |
1469 | if (!skb) | 1479 | if (!skb) |
1470 | return NULL; | 1480 | return NULL; |
1471 | pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec)); | 1481 | pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec)); |
@@ -1485,7 +1495,8 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1485 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | 1495 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, |
1486 | int type, int gdeleted, int sdeleted) | 1496 | int type, int gdeleted, int sdeleted) |
1487 | { | 1497 | { |
1488 | struct net_device *dev = pmc->idev->dev; | 1498 | struct inet6_dev *idev = pmc->idev; |
1499 | struct net_device *dev = idev->dev; | ||
1489 | struct mld2_report *pmr; | 1500 | struct mld2_report *pmr; |
1490 | struct mld2_grec *pgr = NULL; | 1501 | struct mld2_grec *pgr = NULL; |
1491 | struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; | 1502 | struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; |
@@ -1514,7 +1525,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1514 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { | 1525 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { |
1515 | if (skb) | 1526 | if (skb) |
1516 | mld_sendpack(skb); | 1527 | mld_sendpack(skb); |
1517 | skb = mld_newpack(dev, dev->mtu); | 1528 | skb = mld_newpack(idev, dev->mtu); |
1518 | } | 1529 | } |
1519 | } | 1530 | } |
1520 | first = 1; | 1531 | first = 1; |
@@ -1541,7 +1552,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1541 | pgr->grec_nsrcs = htons(scount); | 1552 | pgr->grec_nsrcs = htons(scount); |
1542 | if (skb) | 1553 | if (skb) |
1543 | mld_sendpack(skb); | 1554 | mld_sendpack(skb); |
1544 | skb = mld_newpack(dev, dev->mtu); | 1555 | skb = mld_newpack(idev, dev->mtu); |
1545 | first = 1; | 1556 | first = 1; |
1546 | scount = 0; | 1557 | scount = 0; |
1547 | } | 1558 | } |
@@ -1596,8 +1607,8 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) | |||
1596 | struct sk_buff *skb = NULL; | 1607 | struct sk_buff *skb = NULL; |
1597 | int type; | 1608 | int type; |
1598 | 1609 | ||
1610 | read_lock_bh(&idev->lock); | ||
1599 | if (!pmc) { | 1611 | if (!pmc) { |
1600 | read_lock_bh(&idev->lock); | ||
1601 | for (pmc=idev->mc_list; pmc; pmc=pmc->next) { | 1612 | for (pmc=idev->mc_list; pmc; pmc=pmc->next) { |
1602 | if (pmc->mca_flags & MAF_NOREPORT) | 1613 | if (pmc->mca_flags & MAF_NOREPORT) |
1603 | continue; | 1614 | continue; |
@@ -1609,7 +1620,6 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) | |||
1609 | skb = add_grec(skb, pmc, type, 0, 0); | 1620 | skb = add_grec(skb, pmc, type, 0, 0); |
1610 | spin_unlock_bh(&pmc->mca_lock); | 1621 | spin_unlock_bh(&pmc->mca_lock); |
1611 | } | 1622 | } |
1612 | read_unlock_bh(&idev->lock); | ||
1613 | } else { | 1623 | } else { |
1614 | spin_lock_bh(&pmc->mca_lock); | 1624 | spin_lock_bh(&pmc->mca_lock); |
1615 | if (pmc->mca_sfcount[MCAST_EXCLUDE]) | 1625 | if (pmc->mca_sfcount[MCAST_EXCLUDE]) |
@@ -1619,6 +1629,7 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) | |||
1619 | skb = add_grec(skb, pmc, type, 0, 0); | 1629 | skb = add_grec(skb, pmc, type, 0, 0); |
1620 | spin_unlock_bh(&pmc->mca_lock); | 1630 | spin_unlock_bh(&pmc->mca_lock); |
1621 | } | 1631 | } |
1632 | read_unlock_bh(&idev->lock); | ||
1622 | if (skb) | 1633 | if (skb) |
1623 | mld_sendpack(skb); | 1634 | mld_sendpack(skb); |
1624 | } | 1635 | } |
@@ -1814,6 +1825,46 @@ err_out: | |||
1814 | goto out; | 1825 | goto out; |
1815 | } | 1826 | } |
1816 | 1827 | ||
1828 | static void mld_resend_report(struct inet6_dev *idev) | ||
1829 | { | ||
1830 | if (MLD_V1_SEEN(idev)) { | ||
1831 | struct ifmcaddr6 *mcaddr; | ||
1832 | read_lock_bh(&idev->lock); | ||
1833 | for (mcaddr = idev->mc_list; mcaddr; mcaddr = mcaddr->next) { | ||
1834 | if (!(mcaddr->mca_flags & MAF_NOREPORT)) | ||
1835 | igmp6_send(&mcaddr->mca_addr, idev->dev, | ||
1836 | ICMPV6_MGM_REPORT); | ||
1837 | } | ||
1838 | read_unlock_bh(&idev->lock); | ||
1839 | } else { | ||
1840 | mld_send_report(idev, NULL); | ||
1841 | } | ||
1842 | } | ||
1843 | |||
1844 | void ipv6_mc_dad_complete(struct inet6_dev *idev) | ||
1845 | { | ||
1846 | idev->mc_dad_count = idev->mc_qrv; | ||
1847 | if (idev->mc_dad_count) { | ||
1848 | mld_resend_report(idev); | ||
1849 | idev->mc_dad_count--; | ||
1850 | if (idev->mc_dad_count) | ||
1851 | mld_dad_start_timer(idev, idev->mc_maxdelay); | ||
1852 | } | ||
1853 | } | ||
1854 | |||
1855 | static void mld_dad_timer_expire(unsigned long data) | ||
1856 | { | ||
1857 | struct inet6_dev *idev = (struct inet6_dev *)data; | ||
1858 | |||
1859 | mld_resend_report(idev); | ||
1860 | if (idev->mc_dad_count) { | ||
1861 | idev->mc_dad_count--; | ||
1862 | if (idev->mc_dad_count) | ||
1863 | mld_dad_start_timer(idev, idev->mc_maxdelay); | ||
1864 | } | ||
1865 | __in6_dev_put(idev); | ||
1866 | } | ||
1867 | |||
1817 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | 1868 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, |
1818 | const struct in6_addr *psfsrc) | 1869 | const struct in6_addr *psfsrc) |
1819 | { | 1870 | { |
@@ -2231,6 +2282,8 @@ void ipv6_mc_down(struct inet6_dev *idev) | |||
2231 | idev->mc_gq_running = 0; | 2282 | idev->mc_gq_running = 0; |
2232 | if (del_timer(&idev->mc_gq_timer)) | 2283 | if (del_timer(&idev->mc_gq_timer)) |
2233 | __in6_dev_put(idev); | 2284 | __in6_dev_put(idev); |
2285 | if (del_timer(&idev->mc_dad_timer)) | ||
2286 | __in6_dev_put(idev); | ||
2234 | 2287 | ||
2235 | for (i = idev->mc_list; i; i=i->next) | 2288 | for (i = idev->mc_list; i; i=i->next) |
2236 | igmp6_group_dropped(i); | 2289 | igmp6_group_dropped(i); |
@@ -2267,6 +2320,8 @@ void ipv6_mc_init_dev(struct inet6_dev *idev) | |||
2267 | idev->mc_ifc_count = 0; | 2320 | idev->mc_ifc_count = 0; |
2268 | setup_timer(&idev->mc_ifc_timer, mld_ifc_timer_expire, | 2321 | setup_timer(&idev->mc_ifc_timer, mld_ifc_timer_expire, |
2269 | (unsigned long)idev); | 2322 | (unsigned long)idev); |
2323 | setup_timer(&idev->mc_dad_timer, mld_dad_timer_expire, | ||
2324 | (unsigned long)idev); | ||
2270 | idev->mc_qrv = MLD_QRV_DEFAULT; | 2325 | idev->mc_qrv = MLD_QRV_DEFAULT; |
2271 | idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL; | 2326 | idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL; |
2272 | idev->mc_v1_seen = 0; | 2327 | idev->mc_v1_seen = 0; |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 0f9bdc5ee9f3..9ac01dc9402e 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -268,7 +268,8 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
268 | struct ipv6_opt_hdr *exthdr = | 268 | struct ipv6_opt_hdr *exthdr = |
269 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); | 269 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
270 | const unsigned char *nh = skb_network_header(skb); | 270 | const unsigned char *nh = skb_network_header(skb); |
271 | unsigned int packet_len = skb->tail - skb->network_header; | 271 | unsigned int packet_len = skb_tail_pointer(skb) - |
272 | skb_network_header(skb); | ||
272 | int found_rhdr = 0; | 273 | int found_rhdr = 0; |
273 | 274 | ||
274 | *nexthdr = &ipv6_hdr(skb)->nexthdr; | 275 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
@@ -404,7 +405,8 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
404 | struct ipv6_opt_hdr *exthdr = | 405 | struct ipv6_opt_hdr *exthdr = |
405 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); | 406 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
406 | const unsigned char *nh = skb_network_header(skb); | 407 | const unsigned char *nh = skb_network_header(skb); |
407 | unsigned int packet_len = skb->tail - skb->network_header; | 408 | unsigned int packet_len = skb_tail_pointer(skb) - |
409 | skb_network_header(skb); | ||
408 | int found_rhdr = 0; | 410 | int found_rhdr = 0; |
409 | 411 | ||
410 | *nexthdr = &ipv6_hdr(skb)->nexthdr; | 412 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ca4ffcc287f1..b3b5730b48c5 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -693,7 +693,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
693 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 693 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
694 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; | 694 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
695 | u8 *lladdr = NULL; | 695 | u8 *lladdr = NULL; |
696 | u32 ndoptlen = skb->tail - (skb->transport_header + | 696 | u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + |
697 | offsetof(struct nd_msg, opt)); | 697 | offsetof(struct nd_msg, opt)); |
698 | struct ndisc_options ndopts; | 698 | struct ndisc_options ndopts; |
699 | struct net_device *dev = skb->dev; | 699 | struct net_device *dev = skb->dev; |
@@ -853,7 +853,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
853 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 853 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
854 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; | 854 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
855 | u8 *lladdr = NULL; | 855 | u8 *lladdr = NULL; |
856 | u32 ndoptlen = skb->tail - (skb->transport_header + | 856 | u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + |
857 | offsetof(struct nd_msg, opt)); | 857 | offsetof(struct nd_msg, opt)); |
858 | struct ndisc_options ndopts; | 858 | struct ndisc_options ndopts; |
859 | struct net_device *dev = skb->dev; | 859 | struct net_device *dev = skb->dev; |
@@ -1069,7 +1069,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1069 | 1069 | ||
1070 | __u8 * opt = (__u8 *)(ra_msg + 1); | 1070 | __u8 * opt = (__u8 *)(ra_msg + 1); |
1071 | 1071 | ||
1072 | optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg); | 1072 | optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - |
1073 | sizeof(struct ra_msg); | ||
1073 | 1074 | ||
1074 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1075 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
1075 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); | 1076 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); |
@@ -1346,7 +1347,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1346 | u8 *hdr; | 1347 | u8 *hdr; |
1347 | struct ndisc_options ndopts; | 1348 | struct ndisc_options ndopts; |
1348 | struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb); | 1349 | struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb); |
1349 | u32 ndoptlen = skb->tail - (skb->transport_header + | 1350 | u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + |
1350 | offsetof(struct rd_msg, opt)); | 1351 | offsetof(struct rd_msg, opt)); |
1351 | 1352 | ||
1352 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1353 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
@@ -1568,7 +1569,7 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1568 | 1569 | ||
1569 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1570 | static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1570 | { | 1571 | { |
1571 | struct net_device *dev = ptr; | 1572 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
1572 | struct net *net = dev_net(dev); | 1573 | struct net *net = dev_net(dev); |
1573 | struct inet6_dev *idev; | 1574 | struct inet6_dev *idev; |
1574 | 1575 | ||
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c index 60e9053bab05..47bff6107519 100644 --- a/net/ipv6/netfilter/ip6t_MASQUERADE.c +++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c | |||
@@ -71,7 +71,7 @@ static int device_cmp(struct nf_conn *ct, void *ifindex) | |||
71 | static int masq_device_event(struct notifier_block *this, | 71 | static int masq_device_event(struct notifier_block *this, |
72 | unsigned long event, void *ptr) | 72 | unsigned long event, void *ptr) |
73 | { | 73 | { |
74 | const struct net_device *dev = ptr; | 74 | const struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
75 | struct net *net = dev_net(dev); | 75 | struct net *net = dev_net(dev); |
76 | 76 | ||
77 | if (event == NETDEV_DOWN) | 77 | if (event == NETDEV_DOWN) |
@@ -89,8 +89,10 @@ static int masq_inet_event(struct notifier_block *this, | |||
89 | unsigned long event, void *ptr) | 89 | unsigned long event, void *ptr) |
90 | { | 90 | { |
91 | struct inet6_ifaddr *ifa = ptr; | 91 | struct inet6_ifaddr *ifa = ptr; |
92 | struct netdev_notifier_info info; | ||
92 | 93 | ||
93 | return masq_device_event(this, event, ifa->idev->dev); | 94 | netdev_notifier_info_init(&info, ifa->idev->dev); |
95 | return masq_device_event(this, event, &info); | ||
94 | } | 96 | } |
95 | 97 | ||
96 | static struct notifier_block masq_inet_notifier = { | 98 | static struct notifier_block masq_inet_notifier = { |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index c2e73e647e44..ab92a3673fbb 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
@@ -40,7 +40,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
40 | u16 offset = sizeof(struct ipv6hdr); | 40 | u16 offset = sizeof(struct ipv6hdr); |
41 | struct ipv6_opt_hdr *exthdr = | 41 | struct ipv6_opt_hdr *exthdr = |
42 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); | 42 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
43 | unsigned int packet_len = skb->tail - skb->network_header; | 43 | unsigned int packet_len = skb_tail_pointer(skb) - |
44 | skb_network_header(skb); | ||
44 | int found_rhdr = 0; | 45 | int found_rhdr = 0; |
45 | *nexthdr = &ipv6_hdr(skb)->nexthdr; | 46 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
46 | 47 | ||
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c new file mode 100644 index 000000000000..18f19df4189f --- /dev/null +++ b/net/ipv6/ping.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * "Ping" sockets | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * Based on ipv4/ping.c code. | ||
14 | * | ||
15 | * Authors: Lorenzo Colitti (IPv6 support) | ||
16 | * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6), | ||
17 | * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32) | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <net/addrconf.h> | ||
22 | #include <net/ipv6.h> | ||
23 | #include <net/ip6_route.h> | ||
24 | #include <net/protocol.h> | ||
25 | #include <net/udp.h> | ||
26 | #include <net/transp_v6.h> | ||
27 | #include <net/ping.h> | ||
28 | |||
29 | struct proto pingv6_prot = { | ||
30 | .name = "PINGv6", | ||
31 | .owner = THIS_MODULE, | ||
32 | .init = ping_init_sock, | ||
33 | .close = ping_close, | ||
34 | .connect = ip6_datagram_connect, | ||
35 | .disconnect = udp_disconnect, | ||
36 | .setsockopt = ipv6_setsockopt, | ||
37 | .getsockopt = ipv6_getsockopt, | ||
38 | .sendmsg = ping_v6_sendmsg, | ||
39 | .recvmsg = ping_recvmsg, | ||
40 | .bind = ping_bind, | ||
41 | .backlog_rcv = ping_queue_rcv_skb, | ||
42 | .hash = ping_hash, | ||
43 | .unhash = ping_unhash, | ||
44 | .get_port = ping_get_port, | ||
45 | .obj_size = sizeof(struct raw6_sock), | ||
46 | }; | ||
47 | EXPORT_SYMBOL_GPL(pingv6_prot); | ||
48 | |||
49 | static struct inet_protosw pingv6_protosw = { | ||
50 | .type = SOCK_DGRAM, | ||
51 | .protocol = IPPROTO_ICMPV6, | ||
52 | .prot = &pingv6_prot, | ||
53 | .ops = &inet6_dgram_ops, | ||
54 | .no_check = UDP_CSUM_DEFAULT, | ||
55 | .flags = INET_PROTOSW_REUSE, | ||
56 | }; | ||
57 | |||
58 | |||
59 | /* Compatibility glue so we can support IPv6 when it's compiled as a module */ | ||
60 | static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | ||
61 | { | ||
62 | return -EAFNOSUPPORT; | ||
63 | } | ||
64 | static int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, | ||
65 | struct sk_buff *skb) | ||
66 | { | ||
67 | return -EAFNOSUPPORT; | ||
68 | } | ||
69 | static int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) | ||
70 | { | ||
71 | return -EAFNOSUPPORT; | ||
72 | } | ||
73 | static void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | ||
74 | __be16 port, u32 info, u8 *payload) {} | ||
75 | static int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, | ||
76 | const struct net_device *dev, int strict) | ||
77 | { | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
82 | size_t len) | ||
83 | { | ||
84 | struct inet_sock *inet = inet_sk(sk); | ||
85 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
86 | struct icmp6hdr user_icmph; | ||
87 | int addr_type; | ||
88 | struct in6_addr *daddr; | ||
89 | int iif = 0; | ||
90 | struct flowi6 fl6; | ||
91 | int err; | ||
92 | int hlimit; | ||
93 | struct dst_entry *dst; | ||
94 | struct rt6_info *rt; | ||
95 | struct pingfakehdr pfh; | ||
96 | |||
97 | pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); | ||
98 | |||
99 | err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph, | ||
100 | sizeof(user_icmph)); | ||
101 | if (err) | ||
102 | return err; | ||
103 | |||
104 | if (msg->msg_name) { | ||
105 | struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; | ||
106 | if (msg->msg_namelen < sizeof(struct sockaddr_in6) || | ||
107 | u->sin6_family != AF_INET6) { | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | if (sk->sk_bound_dev_if && | ||
111 | sk->sk_bound_dev_if != u->sin6_scope_id) { | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | daddr = &(u->sin6_addr); | ||
115 | iif = u->sin6_scope_id; | ||
116 | } else { | ||
117 | if (sk->sk_state != TCP_ESTABLISHED) | ||
118 | return -EDESTADDRREQ; | ||
119 | daddr = &np->daddr; | ||
120 | } | ||
121 | |||
122 | if (!iif) | ||
123 | iif = sk->sk_bound_dev_if; | ||
124 | |||
125 | addr_type = ipv6_addr_type(daddr); | ||
126 | if (__ipv6_addr_needs_scope_id(addr_type) && !iif) | ||
127 | return -EINVAL; | ||
128 | if (addr_type & IPV6_ADDR_MAPPED) | ||
129 | return -EINVAL; | ||
130 | |||
131 | /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ | ||
132 | |||
133 | memset(&fl6, 0, sizeof(fl6)); | ||
134 | |||
135 | fl6.flowi6_proto = IPPROTO_ICMPV6; | ||
136 | fl6.saddr = np->saddr; | ||
137 | fl6.daddr = *daddr; | ||
138 | fl6.fl6_icmp_type = user_icmph.icmp6_type; | ||
139 | fl6.fl6_icmp_code = user_icmph.icmp6_code; | ||
140 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | ||
141 | |||
142 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | ||
143 | fl6.flowi6_oif = np->mcast_oif; | ||
144 | else if (!fl6.flowi6_oif) | ||
145 | fl6.flowi6_oif = np->ucast_oif; | ||
146 | |||
147 | dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 1); | ||
148 | if (IS_ERR(dst)) | ||
149 | return PTR_ERR(dst); | ||
150 | rt = (struct rt6_info *) dst; | ||
151 | |||
152 | np = inet6_sk(sk); | ||
153 | if (!np) | ||
154 | return -EBADF; | ||
155 | |||
156 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) | ||
157 | fl6.flowi6_oif = np->mcast_oif; | ||
158 | else if (!fl6.flowi6_oif) | ||
159 | fl6.flowi6_oif = np->ucast_oif; | ||
160 | |||
161 | pfh.icmph.type = user_icmph.icmp6_type; | ||
162 | pfh.icmph.code = user_icmph.icmp6_code; | ||
163 | pfh.icmph.checksum = 0; | ||
164 | pfh.icmph.un.echo.id = inet->inet_sport; | ||
165 | pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; | ||
166 | pfh.iov = msg->msg_iov; | ||
167 | pfh.wcheck = 0; | ||
168 | pfh.family = AF_INET6; | ||
169 | |||
170 | if (ipv6_addr_is_multicast(&fl6.daddr)) | ||
171 | hlimit = np->mcast_hops; | ||
172 | else | ||
173 | hlimit = np->hop_limit; | ||
174 | if (hlimit < 0) | ||
175 | hlimit = ip6_dst_hoplimit(dst); | ||
176 | |||
177 | lock_sock(sk); | ||
178 | err = ip6_append_data(sk, ping_getfrag, &pfh, len, | ||
179 | 0, hlimit, | ||
180 | np->tclass, NULL, &fl6, rt, | ||
181 | MSG_DONTWAIT, np->dontfrag); | ||
182 | |||
183 | if (err) { | ||
184 | ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, | ||
185 | ICMP6_MIB_OUTERRORS); | ||
186 | ip6_flush_pending_frames(sk); | ||
187 | } else { | ||
188 | err = icmpv6_push_pending_frames(sk, &fl6, | ||
189 | (struct icmp6hdr *) &pfh.icmph, | ||
190 | len); | ||
191 | } | ||
192 | release_sock(sk); | ||
193 | |||
194 | if (err) | ||
195 | return err; | ||
196 | |||
197 | return len; | ||
198 | } | ||
199 | |||
200 | #ifdef CONFIG_PROC_FS | ||
201 | static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos) | ||
202 | { | ||
203 | return ping_seq_start(seq, pos, AF_INET6); | ||
204 | } | ||
205 | |||
206 | static int ping_v6_seq_show(struct seq_file *seq, void *v) | ||
207 | { | ||
208 | if (v == SEQ_START_TOKEN) { | ||
209 | seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); | ||
210 | } else { | ||
211 | int bucket = ((struct ping_iter_state *) seq->private)->bucket; | ||
212 | struct inet_sock *inet = inet_sk(v); | ||
213 | __u16 srcp = ntohs(inet->inet_sport); | ||
214 | __u16 destp = ntohs(inet->inet_dport); | ||
215 | ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); | ||
216 | } | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static struct ping_seq_afinfo ping_v6_seq_afinfo = { | ||
221 | .name = "icmp6", | ||
222 | .family = AF_INET6, | ||
223 | .seq_fops = &ping_seq_fops, | ||
224 | .seq_ops = { | ||
225 | .start = ping_v6_seq_start, | ||
226 | .show = ping_v6_seq_show, | ||
227 | .next = ping_seq_next, | ||
228 | .stop = ping_seq_stop, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | static int __net_init ping_v6_proc_init_net(struct net *net) | ||
233 | { | ||
234 | return ping_proc_register(net, &ping_v6_seq_afinfo); | ||
235 | } | ||
236 | |||
237 | static void __net_init ping_v6_proc_exit_net(struct net *net) | ||
238 | { | ||
239 | return ping_proc_unregister(net, &ping_v6_seq_afinfo); | ||
240 | } | ||
241 | |||
242 | static struct pernet_operations ping_v6_net_ops = { | ||
243 | .init = ping_v6_proc_init_net, | ||
244 | .exit = ping_v6_proc_exit_net, | ||
245 | }; | ||
246 | #endif | ||
247 | |||
248 | int __init pingv6_init(void) | ||
249 | { | ||
250 | #ifdef CONFIG_PROC_FS | ||
251 | int ret = register_pernet_subsys(&ping_v6_net_ops); | ||
252 | if (ret) | ||
253 | return ret; | ||
254 | #endif | ||
255 | pingv6_ops.ipv6_recv_error = ipv6_recv_error; | ||
256 | pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl; | ||
257 | pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; | ||
258 | pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; | ||
259 | pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; | ||
260 | return inet6_register_protosw(&pingv6_protosw); | ||
261 | } | ||
262 | |||
263 | /* This never gets called because it's not possible to unload the ipv6 module, | ||
264 | * but just in case. | ||
265 | */ | ||
266 | void pingv6_exit(void) | ||
267 | { | ||
268 | pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; | ||
269 | pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl; | ||
270 | pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; | ||
271 | pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; | ||
272 | pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; | ||
273 | #ifdef CONFIG_PROC_FS | ||
274 | unregister_pernet_subsys(&ping_v6_net_ops); | ||
275 | #endif | ||
276 | inet6_unregister_protosw(&pingv6_protosw); | ||
277 | } | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index eedff8ccded5..c45f7a5c36e9 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -1132,7 +1132,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1132 | spin_lock_bh(&sk->sk_receive_queue.lock); | 1132 | spin_lock_bh(&sk->sk_receive_queue.lock); |
1133 | skb = skb_peek(&sk->sk_receive_queue); | 1133 | skb = skb_peek(&sk->sk_receive_queue); |
1134 | if (skb != NULL) | 1134 | if (skb != NULL) |
1135 | amount = skb->tail - skb->transport_header; | 1135 | amount = skb_tail_pointer(skb) - |
1136 | skb_transport_header(skb); | ||
1136 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 1137 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
1137 | return put_user(amount, (int __user *)arg); | 1138 | return put_user(amount, (int __user *)arg); |
1138 | } | 1139 | } |
@@ -1226,45 +1227,16 @@ struct proto rawv6_prot = { | |||
1226 | }; | 1227 | }; |
1227 | 1228 | ||
1228 | #ifdef CONFIG_PROC_FS | 1229 | #ifdef CONFIG_PROC_FS |
1229 | static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | ||
1230 | { | ||
1231 | struct ipv6_pinfo *np = inet6_sk(sp); | ||
1232 | const struct in6_addr *dest, *src; | ||
1233 | __u16 destp, srcp; | ||
1234 | |||
1235 | dest = &np->daddr; | ||
1236 | src = &np->rcv_saddr; | ||
1237 | destp = 0; | ||
1238 | srcp = inet_sk(sp)->inet_num; | ||
1239 | seq_printf(seq, | ||
1240 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | ||
1241 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", | ||
1242 | i, | ||
1243 | src->s6_addr32[0], src->s6_addr32[1], | ||
1244 | src->s6_addr32[2], src->s6_addr32[3], srcp, | ||
1245 | dest->s6_addr32[0], dest->s6_addr32[1], | ||
1246 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | ||
1247 | sp->sk_state, | ||
1248 | sk_wmem_alloc_get(sp), | ||
1249 | sk_rmem_alloc_get(sp), | ||
1250 | 0, 0L, 0, | ||
1251 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | ||
1252 | 0, | ||
1253 | sock_i_ino(sp), | ||
1254 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | ||
1255 | } | ||
1256 | |||
1257 | static int raw6_seq_show(struct seq_file *seq, void *v) | 1230 | static int raw6_seq_show(struct seq_file *seq, void *v) |
1258 | { | 1231 | { |
1259 | if (v == SEQ_START_TOKEN) | 1232 | if (v == SEQ_START_TOKEN) { |
1260 | seq_printf(seq, | 1233 | seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); |
1261 | " sl " | 1234 | } else { |
1262 | "local_address " | 1235 | struct sock *sp = v; |
1263 | "remote_address " | 1236 | __u16 srcp = inet_sk(sp)->inet_num; |
1264 | "st tx_queue rx_queue tr tm->when retrnsmt" | 1237 | ip6_dgram_sock_seq_show(seq, v, srcp, 0, |
1265 | " uid timeout inode ref pointer drops\n"); | 1238 | raw_seq_private(seq)->bucket); |
1266 | else | 1239 | } |
1267 | raw6_sock_seq_show(seq, v, raw_seq_private(seq)->bucket); | ||
1268 | return 0; | 1240 | return 0; |
1269 | } | 1241 | } |
1270 | 1242 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad0aa6b0b86a..bd5fd7054031 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -83,6 +83,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
83 | struct sk_buff *skb, u32 mtu); | 83 | struct sk_buff *skb, u32 mtu); |
84 | static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, | 84 | static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, |
85 | struct sk_buff *skb); | 85 | struct sk_buff *skb); |
86 | static int rt6_score_route(struct rt6_info *rt, int oif, int strict); | ||
86 | 87 | ||
87 | #ifdef CONFIG_IPV6_ROUTE_INFO | 88 | #ifdef CONFIG_IPV6_ROUTE_INFO |
88 | static struct rt6_info *rt6_add_route_info(struct net *net, | 89 | static struct rt6_info *rt6_add_route_info(struct net *net, |
@@ -394,7 +395,8 @@ static int rt6_info_hash_nhsfn(unsigned int candidate_count, | |||
394 | } | 395 | } |
395 | 396 | ||
396 | static struct rt6_info *rt6_multipath_select(struct rt6_info *match, | 397 | static struct rt6_info *rt6_multipath_select(struct rt6_info *match, |
397 | struct flowi6 *fl6) | 398 | struct flowi6 *fl6, int oif, |
399 | int strict) | ||
398 | { | 400 | { |
399 | struct rt6_info *sibling, *next_sibling; | 401 | struct rt6_info *sibling, *next_sibling; |
400 | int route_choosen; | 402 | int route_choosen; |
@@ -408,6 +410,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, | |||
408 | &match->rt6i_siblings, rt6i_siblings) { | 410 | &match->rt6i_siblings, rt6i_siblings) { |
409 | route_choosen--; | 411 | route_choosen--; |
410 | if (route_choosen == 0) { | 412 | if (route_choosen == 0) { |
413 | if (rt6_score_route(sibling, oif, strict) < 0) | ||
414 | break; | ||
411 | match = sibling; | 415 | match = sibling; |
412 | break; | 416 | break; |
413 | } | 417 | } |
@@ -547,6 +551,8 @@ static inline bool rt6_check_neigh(struct rt6_info *rt) | |||
547 | ret = true; | 551 | ret = true; |
548 | #endif | 552 | #endif |
549 | read_unlock(&neigh->lock); | 553 | read_unlock(&neigh->lock); |
554 | } else if (IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) { | ||
555 | ret = true; | ||
550 | } | 556 | } |
551 | rcu_read_unlock_bh(); | 557 | rcu_read_unlock_bh(); |
552 | 558 | ||
@@ -743,7 +749,7 @@ restart: | |||
743 | rt = fn->leaf; | 749 | rt = fn->leaf; |
744 | rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); | 750 | rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); |
745 | if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) | 751 | if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) |
746 | rt = rt6_multipath_select(rt, fl6); | 752 | rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags); |
747 | BACKTRACK(net, &fl6->saddr); | 753 | BACKTRACK(net, &fl6->saddr); |
748 | out: | 754 | out: |
749 | dst_use(&rt->dst, jiffies); | 755 | dst_use(&rt->dst, jiffies); |
@@ -875,8 +881,8 @@ restart_2: | |||
875 | 881 | ||
876 | restart: | 882 | restart: |
877 | rt = rt6_select(fn, oif, strict | reachable); | 883 | rt = rt6_select(fn, oif, strict | reachable); |
878 | if (rt->rt6i_nsiblings && oif == 0) | 884 | if (rt->rt6i_nsiblings) |
879 | rt = rt6_multipath_select(rt, fl6); | 885 | rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); |
880 | BACKTRACK(net, &fl6->saddr); | 886 | BACKTRACK(net, &fl6->saddr); |
881 | if (rt == net->ipv6.ip6_null_entry || | 887 | if (rt == net->ipv6.ip6_null_entry || |
882 | rt->rt6i_flags & RTF_CACHE) | 888 | rt->rt6i_flags & RTF_CACHE) |
@@ -1649,7 +1655,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu | |||
1649 | int optlen, on_link; | 1655 | int optlen, on_link; |
1650 | u8 *lladdr; | 1656 | u8 *lladdr; |
1651 | 1657 | ||
1652 | optlen = skb->tail - skb->transport_header; | 1658 | optlen = skb_tail_pointer(skb) - skb_transport_header(skb); |
1653 | optlen -= sizeof(*msg); | 1659 | optlen -= sizeof(*msg); |
1654 | 1660 | ||
1655 | if (optlen < 0) { | 1661 | if (optlen < 0) { |
@@ -2681,9 +2687,9 @@ errout: | |||
2681 | } | 2687 | } |
2682 | 2688 | ||
2683 | static int ip6_route_dev_notify(struct notifier_block *this, | 2689 | static int ip6_route_dev_notify(struct notifier_block *this, |
2684 | unsigned long event, void *data) | 2690 | unsigned long event, void *ptr) |
2685 | { | 2691 | { |
2686 | struct net_device *dev = (struct net_device *)data; | 2692 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
2687 | struct net *net = dev_net(dev); | 2693 | struct net *net = dev_net(dev); |
2688 | 2694 | ||
2689 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | 2695 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { |
@@ -2790,7 +2796,7 @@ static const struct file_operations rt6_stats_seq_fops = { | |||
2790 | #ifdef CONFIG_SYSCTL | 2796 | #ifdef CONFIG_SYSCTL |
2791 | 2797 | ||
2792 | static | 2798 | static |
2793 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, | 2799 | int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write, |
2794 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2800 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2795 | { | 2801 | { |
2796 | struct net *net; | 2802 | struct net *net; |
@@ -2805,7 +2811,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, | |||
2805 | return 0; | 2811 | return 0; |
2806 | } | 2812 | } |
2807 | 2813 | ||
2808 | ctl_table ipv6_route_table_template[] = { | 2814 | struct ctl_table ipv6_route_table_template[] = { |
2809 | { | 2815 | { |
2810 | .procname = "flush", | 2816 | .procname = "flush", |
2811 | .data = &init_net.ipv6.sysctl.flush_delay, | 2817 | .data = &init_net.ipv6.sysctl.flush_delay, |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 335363478bbf..a3437a4cd07e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -466,14 +466,14 @@ isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) | |||
466 | 466 | ||
467 | static void ipip6_tunnel_uninit(struct net_device *dev) | 467 | static void ipip6_tunnel_uninit(struct net_device *dev) |
468 | { | 468 | { |
469 | struct net *net = dev_net(dev); | 469 | struct ip_tunnel *tunnel = netdev_priv(dev); |
470 | struct sit_net *sitn = net_generic(net, sit_net_id); | 470 | struct sit_net *sitn = net_generic(tunnel->net, sit_net_id); |
471 | 471 | ||
472 | if (dev == sitn->fb_tunnel_dev) { | 472 | if (dev == sitn->fb_tunnel_dev) { |
473 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); | 473 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); |
474 | } else { | 474 | } else { |
475 | ipip6_tunnel_unlink(sitn, netdev_priv(dev)); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
476 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
477 | } | 477 | } |
478 | dev_put(dev); | 478 | dev_put(dev); |
479 | } | 479 | } |
@@ -577,6 +577,10 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
577 | if (tunnel != NULL) { | 577 | if (tunnel != NULL) { |
578 | struct pcpu_tstats *tstats; | 578 | struct pcpu_tstats *tstats; |
579 | 579 | ||
580 | if (tunnel->parms.iph.protocol != IPPROTO_IPV6 && | ||
581 | tunnel->parms.iph.protocol != 0) | ||
582 | goto out; | ||
583 | |||
580 | secpath_reset(skb); | 584 | secpath_reset(skb); |
581 | skb->mac_header = skb->network_header; | 585 | skb->mac_header = skb->network_header; |
582 | skb_reset_network_header(skb); | 586 | skb_reset_network_header(skb); |
@@ -589,7 +593,7 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
589 | tunnel->dev->stats.rx_errors++; | 593 | tunnel->dev->stats.rx_errors++; |
590 | goto out; | 594 | goto out; |
591 | } | 595 | } |
592 | } else { | 596 | } else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) { |
593 | if (is_spoofed_6rd(tunnel, iph->saddr, | 597 | if (is_spoofed_6rd(tunnel, iph->saddr, |
594 | &ipv6_hdr(skb)->saddr) || | 598 | &ipv6_hdr(skb)->saddr) || |
595 | is_spoofed_6rd(tunnel, iph->daddr, | 599 | is_spoofed_6rd(tunnel, iph->daddr, |
@@ -617,6 +621,8 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
617 | tstats->rx_packets++; | 621 | tstats->rx_packets++; |
618 | tstats->rx_bytes += skb->len; | 622 | tstats->rx_bytes += skb->len; |
619 | 623 | ||
624 | if (tunnel->net != dev_net(tunnel->dev)) | ||
625 | skb_scrub_packet(skb); | ||
620 | netif_rx(skb); | 626 | netif_rx(skb); |
621 | 627 | ||
622 | return 0; | 628 | return 0; |
@@ -629,6 +635,40 @@ out: | |||
629 | return 0; | 635 | return 0; |
630 | } | 636 | } |
631 | 637 | ||
638 | static const struct tnl_ptk_info tpi = { | ||
639 | /* no tunnel info required for ipip. */ | ||
640 | .proto = htons(ETH_P_IP), | ||
641 | }; | ||
642 | |||
643 | static int ipip_rcv(struct sk_buff *skb) | ||
644 | { | ||
645 | const struct iphdr *iph; | ||
646 | struct ip_tunnel *tunnel; | ||
647 | |||
648 | if (iptunnel_pull_header(skb, 0, tpi.proto)) | ||
649 | goto drop; | ||
650 | |||
651 | iph = ip_hdr(skb); | ||
652 | |||
653 | tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, | ||
654 | iph->saddr, iph->daddr); | ||
655 | if (tunnel != NULL) { | ||
656 | if (tunnel->parms.iph.protocol != IPPROTO_IPIP && | ||
657 | tunnel->parms.iph.protocol != 0) | ||
658 | goto drop; | ||
659 | |||
660 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) | ||
661 | goto drop; | ||
662 | return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); | ||
663 | } | ||
664 | |||
665 | return 1; | ||
666 | |||
667 | drop: | ||
668 | kfree_skb(skb); | ||
669 | return 0; | ||
670 | } | ||
671 | |||
632 | /* | 672 | /* |
633 | * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function | 673 | * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function |
634 | * stores the embedded IPv4 address in v4dst and returns true. | 674 | * stores the embedded IPv4 address in v4dst and returns true. |
@@ -690,13 +730,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
690 | __be16 df = tiph->frag_off; | 730 | __be16 df = tiph->frag_off; |
691 | struct rtable *rt; /* Route to the other host */ | 731 | struct rtable *rt; /* Route to the other host */ |
692 | struct net_device *tdev; /* Device to other host */ | 732 | struct net_device *tdev; /* Device to other host */ |
693 | struct iphdr *iph; /* Our new IP header */ | ||
694 | unsigned int max_headroom; /* The extra header space needed */ | 733 | unsigned int max_headroom; /* The extra header space needed */ |
695 | __be32 dst = tiph->daddr; | 734 | __be32 dst = tiph->daddr; |
696 | struct flowi4 fl4; | 735 | struct flowi4 fl4; |
697 | int mtu; | 736 | int mtu; |
698 | const struct in6_addr *addr6; | 737 | const struct in6_addr *addr6; |
699 | int addr_type; | 738 | int addr_type; |
739 | u8 ttl; | ||
740 | int err; | ||
700 | 741 | ||
701 | if (skb->protocol != htons(ETH_P_IPV6)) | 742 | if (skb->protocol != htons(ETH_P_IPV6)) |
702 | goto tx_error; | 743 | goto tx_error; |
@@ -764,7 +805,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
764 | goto tx_error; | 805 | goto tx_error; |
765 | } | 806 | } |
766 | 807 | ||
767 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, | 808 | rt = ip_route_output_ports(tunnel->net, &fl4, NULL, |
768 | dst, tiph->saddr, | 809 | dst, tiph->saddr, |
769 | 0, 0, | 810 | 0, 0, |
770 | IPPROTO_IPV6, RT_TOS(tos), | 811 | IPPROTO_IPV6, RT_TOS(tos), |
@@ -819,6 +860,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
819 | tunnel->err_count = 0; | 860 | tunnel->err_count = 0; |
820 | } | 861 | } |
821 | 862 | ||
863 | if (tunnel->net != dev_net(dev)) | ||
864 | skb_scrub_packet(skb); | ||
865 | |||
822 | /* | 866 | /* |
823 | * Okay, now see if we can stuff it in the buffer as-is. | 867 | * Okay, now see if we can stuff it in the buffer as-is. |
824 | */ | 868 | */ |
@@ -839,34 +883,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
839 | skb = new_skb; | 883 | skb = new_skb; |
840 | iph6 = ipv6_hdr(skb); | 884 | iph6 = ipv6_hdr(skb); |
841 | } | 885 | } |
842 | 886 | ttl = tiph->ttl; | |
843 | skb->transport_header = skb->network_header; | 887 | if (ttl == 0) |
844 | skb_push(skb, sizeof(struct iphdr)); | 888 | ttl = iph6->hop_limit; |
845 | skb_reset_network_header(skb); | 889 | tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
846 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 890 | |
847 | IPCB(skb)->flags = 0; | 891 | err = iptunnel_xmit(dev_net(dev), rt, skb, fl4.saddr, fl4.daddr, |
848 | skb_dst_drop(skb); | 892 | IPPROTO_IPV6, tos, ttl, df); |
849 | skb_dst_set(skb, &rt->dst); | 893 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); |
850 | |||
851 | /* | ||
852 | * Push down and install the IPIP header. | ||
853 | */ | ||
854 | |||
855 | iph = ip_hdr(skb); | ||
856 | iph->version = 4; | ||
857 | iph->ihl = sizeof(struct iphdr)>>2; | ||
858 | iph->frag_off = df; | ||
859 | iph->protocol = IPPROTO_IPV6; | ||
860 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | ||
861 | iph->daddr = fl4.daddr; | ||
862 | iph->saddr = fl4.saddr; | ||
863 | |||
864 | if ((iph->ttl = tiph->ttl) == 0) | ||
865 | iph->ttl = iph6->hop_limit; | ||
866 | |||
867 | skb->ip_summed = CHECKSUM_NONE; | ||
868 | ip_select_ident(iph, skb_dst(skb), NULL); | ||
869 | iptunnel_xmit(skb, dev); | ||
870 | return NETDEV_TX_OK; | 894 | return NETDEV_TX_OK; |
871 | 895 | ||
872 | tx_error_icmp: | 896 | tx_error_icmp: |
@@ -877,6 +901,43 @@ tx_error: | |||
877 | return NETDEV_TX_OK; | 901 | return NETDEV_TX_OK; |
878 | } | 902 | } |
879 | 903 | ||
904 | static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | ||
905 | { | ||
906 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
907 | const struct iphdr *tiph = &tunnel->parms.iph; | ||
908 | |||
909 | if (likely(!skb->encapsulation)) { | ||
910 | skb_reset_inner_headers(skb); | ||
911 | skb->encapsulation = 1; | ||
912 | } | ||
913 | |||
914 | ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP); | ||
915 | return NETDEV_TX_OK; | ||
916 | } | ||
917 | |||
918 | static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, | ||
919 | struct net_device *dev) | ||
920 | { | ||
921 | switch (skb->protocol) { | ||
922 | case htons(ETH_P_IP): | ||
923 | ipip_tunnel_xmit(skb, dev); | ||
924 | break; | ||
925 | case htons(ETH_P_IPV6): | ||
926 | ipip6_tunnel_xmit(skb, dev); | ||
927 | break; | ||
928 | default: | ||
929 | goto tx_err; | ||
930 | } | ||
931 | |||
932 | return NETDEV_TX_OK; | ||
933 | |||
934 | tx_err: | ||
935 | dev->stats.tx_errors++; | ||
936 | dev_kfree_skb(skb); | ||
937 | return NETDEV_TX_OK; | ||
938 | |||
939 | } | ||
940 | |||
880 | static void ipip6_tunnel_bind_dev(struct net_device *dev) | 941 | static void ipip6_tunnel_bind_dev(struct net_device *dev) |
881 | { | 942 | { |
882 | struct net_device *tdev = NULL; | 943 | struct net_device *tdev = NULL; |
@@ -888,7 +949,8 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
888 | iph = &tunnel->parms.iph; | 949 | iph = &tunnel->parms.iph; |
889 | 950 | ||
890 | if (iph->daddr) { | 951 | if (iph->daddr) { |
891 | struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, | 952 | struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4, |
953 | NULL, | ||
892 | iph->daddr, iph->saddr, | 954 | iph->daddr, iph->saddr, |
893 | 0, 0, | 955 | 0, 0, |
894 | IPPROTO_IPV6, | 956 | IPPROTO_IPV6, |
@@ -903,7 +965,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
903 | } | 965 | } |
904 | 966 | ||
905 | if (!tdev && tunnel->parms.link) | 967 | if (!tdev && tunnel->parms.link) |
906 | tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); | 968 | tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); |
907 | 969 | ||
908 | if (tdev) { | 970 | if (tdev) { |
909 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | 971 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); |
@@ -916,7 +978,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
916 | 978 | ||
917 | static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | 979 | static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) |
918 | { | 980 | { |
919 | struct net *net = dev_net(t->dev); | 981 | struct net *net = t->net; |
920 | struct sit_net *sitn = net_generic(net, sit_net_id); | 982 | struct sit_net *sitn = net_generic(net, sit_net_id); |
921 | 983 | ||
922 | ipip6_tunnel_unlink(sitn, t); | 984 | ipip6_tunnel_unlink(sitn, t); |
@@ -1027,7 +1089,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1027 | goto done; | 1089 | goto done; |
1028 | 1090 | ||
1029 | err = -EINVAL; | 1091 | err = -EINVAL; |
1030 | if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 || | 1092 | if (p.iph.protocol != IPPROTO_IPV6 && |
1093 | p.iph.protocol != IPPROTO_IPIP && | ||
1094 | p.iph.protocol != 0) | ||
1095 | goto done; | ||
1096 | if (p.iph.version != 4 || | ||
1031 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) | 1097 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) |
1032 | goto done; | 1098 | goto done; |
1033 | if (p.iph.ttl) | 1099 | if (p.iph.ttl) |
@@ -1164,7 +1230,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | |||
1164 | 1230 | ||
1165 | static const struct net_device_ops ipip6_netdev_ops = { | 1231 | static const struct net_device_ops ipip6_netdev_ops = { |
1166 | .ndo_uninit = ipip6_tunnel_uninit, | 1232 | .ndo_uninit = ipip6_tunnel_uninit, |
1167 | .ndo_start_xmit = ipip6_tunnel_xmit, | 1233 | .ndo_start_xmit = sit_tunnel_xmit, |
1168 | .ndo_do_ioctl = ipip6_tunnel_ioctl, | 1234 | .ndo_do_ioctl = ipip6_tunnel_ioctl, |
1169 | .ndo_change_mtu = ipip6_tunnel_change_mtu, | 1235 | .ndo_change_mtu = ipip6_tunnel_change_mtu, |
1170 | .ndo_get_stats64 = ip_tunnel_get_stats64, | 1236 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
@@ -1188,7 +1254,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
1188 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 1254 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
1189 | dev->iflink = 0; | 1255 | dev->iflink = 0; |
1190 | dev->addr_len = 4; | 1256 | dev->addr_len = 4; |
1191 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
1192 | dev->features |= NETIF_F_LLTX; | 1257 | dev->features |= NETIF_F_LLTX; |
1193 | } | 1258 | } |
1194 | 1259 | ||
@@ -1197,6 +1262,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1197 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1262 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1198 | 1263 | ||
1199 | tunnel->dev = dev; | 1264 | tunnel->dev = dev; |
1265 | tunnel->net = dev_net(dev); | ||
1200 | 1266 | ||
1201 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 1267 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
1202 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 1268 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
@@ -1217,6 +1283,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1217 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1283 | struct sit_net *sitn = net_generic(net, sit_net_id); |
1218 | 1284 | ||
1219 | tunnel->dev = dev; | 1285 | tunnel->dev = dev; |
1286 | tunnel->net = dev_net(dev); | ||
1220 | strcpy(tunnel->parms.name, dev->name); | 1287 | strcpy(tunnel->parms.name, dev->name); |
1221 | 1288 | ||
1222 | iph->version = 4; | 1289 | iph->version = 4; |
@@ -1232,6 +1299,22 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1232 | return 0; | 1299 | return 0; |
1233 | } | 1300 | } |
1234 | 1301 | ||
1302 | static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
1303 | { | ||
1304 | u8 proto; | ||
1305 | |||
1306 | if (!data || !data[IFLA_IPTUN_PROTO]) | ||
1307 | return 0; | ||
1308 | |||
1309 | proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); | ||
1310 | if (proto != IPPROTO_IPV6 && | ||
1311 | proto != IPPROTO_IPIP && | ||
1312 | proto != 0) | ||
1313 | return -EINVAL; | ||
1314 | |||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1235 | static void ipip6_netlink_parms(struct nlattr *data[], | 1318 | static void ipip6_netlink_parms(struct nlattr *data[], |
1236 | struct ip_tunnel_parm *parms) | 1319 | struct ip_tunnel_parm *parms) |
1237 | { | 1320 | { |
@@ -1268,6 +1351,10 @@ static void ipip6_netlink_parms(struct nlattr *data[], | |||
1268 | 1351 | ||
1269 | if (data[IFLA_IPTUN_FLAGS]) | 1352 | if (data[IFLA_IPTUN_FLAGS]) |
1270 | parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]); | 1353 | parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]); |
1354 | |||
1355 | if (data[IFLA_IPTUN_PROTO]) | ||
1356 | parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]); | ||
1357 | |||
1271 | } | 1358 | } |
1272 | 1359 | ||
1273 | #ifdef CONFIG_IPV6_SIT_6RD | 1360 | #ifdef CONFIG_IPV6_SIT_6RD |
@@ -1339,9 +1426,9 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, | |||
1339 | static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], | 1426 | static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], |
1340 | struct nlattr *data[]) | 1427 | struct nlattr *data[]) |
1341 | { | 1428 | { |
1342 | struct ip_tunnel *t; | 1429 | struct ip_tunnel *t = netdev_priv(dev); |
1343 | struct ip_tunnel_parm p; | 1430 | struct ip_tunnel_parm p; |
1344 | struct net *net = dev_net(dev); | 1431 | struct net *net = t->net; |
1345 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1432 | struct sit_net *sitn = net_generic(net, sit_net_id); |
1346 | #ifdef CONFIG_IPV6_SIT_6RD | 1433 | #ifdef CONFIG_IPV6_SIT_6RD |
1347 | struct ip_tunnel_6rd ip6rd; | 1434 | struct ip_tunnel_6rd ip6rd; |
@@ -1391,6 +1478,8 @@ static size_t ipip6_get_size(const struct net_device *dev) | |||
1391 | nla_total_size(1) + | 1478 | nla_total_size(1) + |
1392 | /* IFLA_IPTUN_FLAGS */ | 1479 | /* IFLA_IPTUN_FLAGS */ |
1393 | nla_total_size(2) + | 1480 | nla_total_size(2) + |
1481 | /* IFLA_IPTUN_PROTO */ | ||
1482 | nla_total_size(1) + | ||
1394 | #ifdef CONFIG_IPV6_SIT_6RD | 1483 | #ifdef CONFIG_IPV6_SIT_6RD |
1395 | /* IFLA_IPTUN_6RD_PREFIX */ | 1484 | /* IFLA_IPTUN_6RD_PREFIX */ |
1396 | nla_total_size(sizeof(struct in6_addr)) + | 1485 | nla_total_size(sizeof(struct in6_addr)) + |
@@ -1416,6 +1505,7 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
1416 | nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) || | 1505 | nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) || |
1417 | nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, | 1506 | nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, |
1418 | !!(parm->iph.frag_off & htons(IP_DF))) || | 1507 | !!(parm->iph.frag_off & htons(IP_DF))) || |
1508 | nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) || | ||
1419 | nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags)) | 1509 | nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags)) |
1420 | goto nla_put_failure; | 1510 | goto nla_put_failure; |
1421 | 1511 | ||
@@ -1445,6 +1535,7 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { | |||
1445 | [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, | 1535 | [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, |
1446 | [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, | 1536 | [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, |
1447 | [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, | 1537 | [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, |
1538 | [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, | ||
1448 | #ifdef CONFIG_IPV6_SIT_6RD | 1539 | #ifdef CONFIG_IPV6_SIT_6RD |
1449 | [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) }, | 1540 | [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) }, |
1450 | [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, | 1541 | [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, |
@@ -1459,6 +1550,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = { | |||
1459 | .policy = ipip6_policy, | 1550 | .policy = ipip6_policy, |
1460 | .priv_size = sizeof(struct ip_tunnel), | 1551 | .priv_size = sizeof(struct ip_tunnel), |
1461 | .setup = ipip6_tunnel_setup, | 1552 | .setup = ipip6_tunnel_setup, |
1553 | .validate = ipip6_validate, | ||
1462 | .newlink = ipip6_newlink, | 1554 | .newlink = ipip6_newlink, |
1463 | .changelink = ipip6_changelink, | 1555 | .changelink = ipip6_changelink, |
1464 | .get_size = ipip6_get_size, | 1556 | .get_size = ipip6_get_size, |
@@ -1471,10 +1563,22 @@ static struct xfrm_tunnel sit_handler __read_mostly = { | |||
1471 | .priority = 1, | 1563 | .priority = 1, |
1472 | }; | 1564 | }; |
1473 | 1565 | ||
1566 | static struct xfrm_tunnel ipip_handler __read_mostly = { | ||
1567 | .handler = ipip_rcv, | ||
1568 | .err_handler = ipip6_err, | ||
1569 | .priority = 2, | ||
1570 | }; | ||
1571 | |||
1474 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) | 1572 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) |
1475 | { | 1573 | { |
1574 | struct net *net = dev_net(sitn->fb_tunnel_dev); | ||
1575 | struct net_device *dev, *aux; | ||
1476 | int prio; | 1576 | int prio; |
1477 | 1577 | ||
1578 | for_each_netdev_safe(net, dev, aux) | ||
1579 | if (dev->rtnl_link_ops == &sit_link_ops) | ||
1580 | unregister_netdevice_queue(dev, head); | ||
1581 | |||
1478 | for (prio = 1; prio < 4; prio++) { | 1582 | for (prio = 1; prio < 4; prio++) { |
1479 | int h; | 1583 | int h; |
1480 | for (h = 0; h < HASH_SIZE; h++) { | 1584 | for (h = 0; h < HASH_SIZE; h++) { |
@@ -1482,7 +1586,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1482 | 1586 | ||
1483 | t = rtnl_dereference(sitn->tunnels[prio][h]); | 1587 | t = rtnl_dereference(sitn->tunnels[prio][h]); |
1484 | while (t != NULL) { | 1588 | while (t != NULL) { |
1485 | unregister_netdevice_queue(t->dev, head); | 1589 | /* If dev is in the same netns, it has already |
1590 | * been added to the list by the previous loop. | ||
1591 | */ | ||
1592 | if (dev_net(t->dev) != net) | ||
1593 | unregister_netdevice_queue(t->dev, | ||
1594 | head); | ||
1486 | t = rtnl_dereference(t->next); | 1595 | t = rtnl_dereference(t->next); |
1487 | } | 1596 | } |
1488 | } | 1597 | } |
@@ -1507,6 +1616,10 @@ static int __net_init sit_init_net(struct net *net) | |||
1507 | goto err_alloc_dev; | 1616 | goto err_alloc_dev; |
1508 | } | 1617 | } |
1509 | dev_net_set(sitn->fb_tunnel_dev, net); | 1618 | dev_net_set(sitn->fb_tunnel_dev, net); |
1619 | /* FB netdevice is special: we have one, and only one per netns. | ||
1620 | * Allowing to move it to another netns is clearly unsafe. | ||
1621 | */ | ||
1622 | sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | ||
1510 | 1623 | ||
1511 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); | 1624 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); |
1512 | if (err) | 1625 | if (err) |
@@ -1553,6 +1666,7 @@ static void __exit sit_cleanup(void) | |||
1553 | { | 1666 | { |
1554 | rtnl_link_unregister(&sit_link_ops); | 1667 | rtnl_link_unregister(&sit_link_ops); |
1555 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | 1668 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); |
1669 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
1556 | 1670 | ||
1557 | unregister_pernet_device(&sit_net_ops); | 1671 | unregister_pernet_device(&sit_net_ops); |
1558 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1672 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
@@ -1569,9 +1683,14 @@ static int __init sit_init(void) | |||
1569 | return err; | 1683 | return err; |
1570 | err = xfrm4_tunnel_register(&sit_handler, AF_INET6); | 1684 | err = xfrm4_tunnel_register(&sit_handler, AF_INET6); |
1571 | if (err < 0) { | 1685 | if (err < 0) { |
1572 | pr_info("%s: can't add protocol\n", __func__); | 1686 | pr_info("%s: can't register ip6ip4\n", __func__); |
1573 | goto xfrm_tunnel_failed; | 1687 | goto xfrm_tunnel_failed; |
1574 | } | 1688 | } |
1689 | err = xfrm4_tunnel_register(&ipip_handler, AF_INET); | ||
1690 | if (err < 0) { | ||
1691 | pr_info("%s: can't register ip4ip4\n", __func__); | ||
1692 | goto xfrm_tunnel4_failed; | ||
1693 | } | ||
1575 | err = rtnl_link_register(&sit_link_ops); | 1694 | err = rtnl_link_register(&sit_link_ops); |
1576 | if (err < 0) | 1695 | if (err < 0) |
1577 | goto rtnl_link_failed; | 1696 | goto rtnl_link_failed; |
@@ -1580,6 +1699,8 @@ out: | |||
1580 | return err; | 1699 | return err; |
1581 | 1700 | ||
1582 | rtnl_link_failed: | 1701 | rtnl_link_failed: |
1702 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
1703 | xfrm_tunnel4_failed: | ||
1583 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | 1704 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); |
1584 | xfrm_tunnel_failed: | 1705 | xfrm_tunnel_failed: |
1585 | unregister_pernet_device(&sit_net_ops); | 1706 | unregister_pernet_device(&sit_net_ops); |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index e85c48bd404f..107b2f1d90ae 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <net/addrconf.h> | 16 | #include <net/addrconf.h> |
17 | #include <net/inet_frag.h> | 17 | #include <net/inet_frag.h> |
18 | 18 | ||
19 | static ctl_table ipv6_table_template[] = { | 19 | static struct ctl_table ipv6_table_template[] = { |
20 | { | 20 | { |
21 | .procname = "bindv6only", | 21 | .procname = "bindv6only", |
22 | .data = &init_net.ipv6.sysctl.bindv6only, | 22 | .data = &init_net.ipv6.sysctl.bindv6only, |
@@ -27,7 +27,7 @@ static ctl_table ipv6_table_template[] = { | |||
27 | { } | 27 | { } |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static ctl_table ipv6_rotable[] = { | 30 | static struct ctl_table ipv6_rotable[] = { |
31 | { | 31 | { |
32 | .procname = "mld_max_msf", | 32 | .procname = "mld_max_msf", |
33 | .data = &sysctl_mld_max_msf, | 33 | .data = &sysctl_mld_max_msf, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0a17ed9eaf39..5cffa5c3e6b8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <net/inet_common.h> | 63 | #include <net/inet_common.h> |
64 | #include <net/secure_seq.h> | 64 | #include <net/secure_seq.h> |
65 | #include <net/tcp_memcontrol.h> | 65 | #include <net/tcp_memcontrol.h> |
66 | #include <net/ll_poll.h> | ||
66 | 67 | ||
67 | #include <asm/uaccess.h> | 68 | #include <asm/uaccess.h> |
68 | 69 | ||
@@ -1498,6 +1499,7 @@ process: | |||
1498 | if (sk_filter(sk, skb)) | 1499 | if (sk_filter(sk, skb)) |
1499 | goto discard_and_relse; | 1500 | goto discard_and_relse; |
1500 | 1501 | ||
1502 | sk_mark_ll(sk, skb); | ||
1501 | skb->dev = NULL; | 1503 | skb->dev = NULL; |
1502 | 1504 | ||
1503 | bh_lock_sock_nested(sk); | 1505 | bh_lock_sock_nested(sk); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 42923b14dfa6..b6f31437a1f8 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <net/ip6_checksum.h> | 46 | #include <net/ip6_checksum.h> |
47 | #include <net/xfrm.h> | 47 | #include <net/xfrm.h> |
48 | #include <net/inet6_hashtables.h> | 48 | #include <net/inet6_hashtables.h> |
49 | #include <net/ll_poll.h> | ||
49 | 50 | ||
50 | #include <linux/proc_fs.h> | 51 | #include <linux/proc_fs.h> |
51 | #include <linux/seq_file.h> | 52 | #include <linux/seq_file.h> |
@@ -841,7 +842,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
841 | */ | 842 | */ |
842 | sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); | 843 | sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); |
843 | if (sk != NULL) { | 844 | if (sk != NULL) { |
844 | int ret = udpv6_queue_rcv_skb(sk, skb); | 845 | int ret; |
846 | |||
847 | sk_mark_ll(sk, skb); | ||
848 | ret = udpv6_queue_rcv_skb(sk, skb); | ||
845 | sock_put(sk); | 849 | sock_put(sk); |
846 | 850 | ||
847 | /* a return value > 0 means to resubmit the input, but | 851 | /* a return value > 0 means to resubmit the input, but |
@@ -955,11 +959,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
955 | struct udphdr *uh; | 959 | struct udphdr *uh; |
956 | struct udp_sock *up = udp_sk(sk); | 960 | struct udp_sock *up = udp_sk(sk); |
957 | struct inet_sock *inet = inet_sk(sk); | 961 | struct inet_sock *inet = inet_sk(sk); |
958 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; | 962 | struct flowi6 *fl6; |
959 | int err = 0; | 963 | int err = 0; |
960 | int is_udplite = IS_UDPLITE(sk); | 964 | int is_udplite = IS_UDPLITE(sk); |
961 | __wsum csum = 0; | 965 | __wsum csum = 0; |
962 | 966 | ||
967 | if (up->pending == AF_INET) | ||
968 | return udp_push_pending_frames(sk); | ||
969 | |||
970 | fl6 = &inet->cork.fl.u.ip6; | ||
971 | |||
963 | /* Grab the skbuff where UDP header space exists. */ | 972 | /* Grab the skbuff where UDP header space exists. */ |
964 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) | 973 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) |
965 | goto out; | 974 | goto out; |
@@ -1359,48 +1368,17 @@ static const struct inet6_protocol udpv6_protocol = { | |||
1359 | 1368 | ||
1360 | /* ------------------------------------------------------------------------ */ | 1369 | /* ------------------------------------------------------------------------ */ |
1361 | #ifdef CONFIG_PROC_FS | 1370 | #ifdef CONFIG_PROC_FS |
1362 | |||
1363 | static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket) | ||
1364 | { | ||
1365 | struct inet_sock *inet = inet_sk(sp); | ||
1366 | struct ipv6_pinfo *np = inet6_sk(sp); | ||
1367 | const struct in6_addr *dest, *src; | ||
1368 | __u16 destp, srcp; | ||
1369 | |||
1370 | dest = &np->daddr; | ||
1371 | src = &np->rcv_saddr; | ||
1372 | destp = ntohs(inet->inet_dport); | ||
1373 | srcp = ntohs(inet->inet_sport); | ||
1374 | seq_printf(seq, | ||
1375 | "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | ||
1376 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", | ||
1377 | bucket, | ||
1378 | src->s6_addr32[0], src->s6_addr32[1], | ||
1379 | src->s6_addr32[2], src->s6_addr32[3], srcp, | ||
1380 | dest->s6_addr32[0], dest->s6_addr32[1], | ||
1381 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | ||
1382 | sp->sk_state, | ||
1383 | sk_wmem_alloc_get(sp), | ||
1384 | sk_rmem_alloc_get(sp), | ||
1385 | 0, 0L, 0, | ||
1386 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | ||
1387 | 0, | ||
1388 | sock_i_ino(sp), | ||
1389 | atomic_read(&sp->sk_refcnt), sp, | ||
1390 | atomic_read(&sp->sk_drops)); | ||
1391 | } | ||
1392 | |||
1393 | int udp6_seq_show(struct seq_file *seq, void *v) | 1371 | int udp6_seq_show(struct seq_file *seq, void *v) |
1394 | { | 1372 | { |
1395 | if (v == SEQ_START_TOKEN) | 1373 | if (v == SEQ_START_TOKEN) { |
1396 | seq_printf(seq, | 1374 | seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); |
1397 | " sl " | 1375 | } else { |
1398 | "local_address " | 1376 | int bucket = ((struct udp_iter_state *)seq->private)->bucket; |
1399 | "remote_address " | 1377 | struct inet_sock *inet = inet_sk(v); |
1400 | "st tx_queue rx_queue tr tm->when retrnsmt" | 1378 | __u16 srcp = ntohs(inet->inet_sport); |
1401 | " uid timeout inode ref pointer drops\n"); | 1379 | __u16 destp = ntohs(inet->inet_dport); |
1402 | else | 1380 | ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); |
1403 | udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket); | 1381 | } |
1404 | return 0; | 1382 | return 0; |
1405 | } | 1383 | } |
1406 | 1384 | ||
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index d3cfaf9c7a08..5d1b8d7ac993 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
@@ -64,7 +64,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
64 | if (unlikely(type & ~(SKB_GSO_UDP | | 64 | if (unlikely(type & ~(SKB_GSO_UDP | |
65 | SKB_GSO_DODGY | | 65 | SKB_GSO_DODGY | |
66 | SKB_GSO_UDP_TUNNEL | | 66 | SKB_GSO_UDP_TUNNEL | |
67 | SKB_GSO_GRE) || | 67 | SKB_GSO_GRE | |
68 | SKB_GSO_MPLS) || | ||
68 | !(type & (SKB_GSO_UDP)))) | 69 | !(type & (SKB_GSO_UDP)))) |
69 | goto out; | 70 | goto out; |
70 | 71 | ||