diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 130 | ||||
-rw-r--r-- | net/ipv6/addrlabel.c | 9 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 35 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 8 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 16 | ||||
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 5 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 8 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 67 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 10 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 11 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 11 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 2 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 16 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 14 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_REJECT.c | 9 | ||||
-rw-r--r-- | net/ipv6/raw.c | 149 | ||||
-rw-r--r-- | net/ipv6/route.c | 138 | ||||
-rw-r--r-- | net/ipv6/sit.c | 14 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 3 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 50 | ||||
-rw-r--r-- | net/ipv6/udp.c | 6 |
24 files changed, 473 insertions, 263 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 498b927f68b..1587d0d9295 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -374,8 +374,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
374 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | 374 | "%s(): cannot allocate memory for statistics; dev=%s.\n", |
375 | __func__, dev->name)); | 375 | __func__, dev->name)); |
376 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 376 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
377 | ndev->dead = 1; | 377 | dev_put(dev); |
378 | in6_dev_finish_destroy(ndev); | 378 | kfree(ndev); |
379 | return NULL; | 379 | return NULL; |
380 | } | 380 | } |
381 | 381 | ||
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
656 | * layer address of our nexhop router | 656 | * layer address of our nexhop router |
657 | */ | 657 | */ |
658 | 658 | ||
659 | if (rt->rt6i_nexthop == NULL) | 659 | if (dst_get_neighbour_raw(&rt->dst) == NULL) |
660 | ifa->flags &= ~IFA_F_OPTIMISTIC; | 660 | ifa->flags &= ~IFA_F_OPTIMISTIC; |
661 | 661 | ||
662 | ifa->idev = idev; | 662 | ifa->idev = idev; |
@@ -824,12 +824,13 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
824 | { | 824 | { |
825 | struct inet6_dev *idev = ifp->idev; | 825 | struct inet6_dev *idev = ifp->idev; |
826 | struct in6_addr addr, *tmpaddr; | 826 | struct in6_addr addr, *tmpaddr; |
827 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age; | 827 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_tstamp, age; |
828 | unsigned long regen_advance; | 828 | unsigned long regen_advance; |
829 | int tmp_plen; | 829 | int tmp_plen; |
830 | int ret = 0; | 830 | int ret = 0; |
831 | int max_addresses; | 831 | int max_addresses; |
832 | u32 addr_flags; | 832 | u32 addr_flags; |
833 | unsigned long now = jiffies; | ||
833 | 834 | ||
834 | write_lock(&idev->lock); | 835 | write_lock(&idev->lock); |
835 | if (ift) { | 836 | if (ift) { |
@@ -874,7 +875,7 @@ retry: | |||
874 | goto out; | 875 | goto out; |
875 | } | 876 | } |
876 | memcpy(&addr.s6_addr[8], idev->rndid, 8); | 877 | memcpy(&addr.s6_addr[8], idev->rndid, 8); |
877 | age = (jiffies - ifp->tstamp) / HZ; | 878 | age = (now - ifp->tstamp) / HZ; |
878 | tmp_valid_lft = min_t(__u32, | 879 | tmp_valid_lft = min_t(__u32, |
879 | ifp->valid_lft, | 880 | ifp->valid_lft, |
880 | idev->cnf.temp_valid_lft + age); | 881 | idev->cnf.temp_valid_lft + age); |
@@ -884,7 +885,6 @@ retry: | |||
884 | idev->cnf.max_desync_factor); | 885 | idev->cnf.max_desync_factor); |
885 | tmp_plen = ifp->prefix_len; | 886 | tmp_plen = ifp->prefix_len; |
886 | max_addresses = idev->cnf.max_addresses; | 887 | max_addresses = idev->cnf.max_addresses; |
887 | tmp_cstamp = ifp->cstamp; | ||
888 | tmp_tstamp = ifp->tstamp; | 888 | tmp_tstamp = ifp->tstamp; |
889 | spin_unlock_bh(&ifp->lock); | 889 | spin_unlock_bh(&ifp->lock); |
890 | 890 | ||
@@ -929,7 +929,7 @@ retry: | |||
929 | ift->ifpub = ifp; | 929 | ift->ifpub = ifp; |
930 | ift->valid_lft = tmp_valid_lft; | 930 | ift->valid_lft = tmp_valid_lft; |
931 | ift->prefered_lft = tmp_prefered_lft; | 931 | ift->prefered_lft = tmp_prefered_lft; |
932 | ift->cstamp = tmp_cstamp; | 932 | ift->cstamp = now; |
933 | ift->tstamp = tmp_tstamp; | 933 | ift->tstamp = tmp_tstamp; |
934 | spin_unlock_bh(&ift->lock); | 934 | spin_unlock_bh(&ift->lock); |
935 | 935 | ||
@@ -1470,6 +1470,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1470 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1470 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1471 | { | 1471 | { |
1472 | struct in6_addr addr; | 1472 | struct in6_addr addr; |
1473 | if (ifp->prefix_len == 127) /* RFC 6164 */ | ||
1474 | return; | ||
1473 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1475 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
1474 | if (ipv6_addr_any(&addr)) | 1476 | if (ipv6_addr_any(&addr)) |
1475 | return; | 1477 | return; |
@@ -1479,6 +1481,8 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1479 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1481 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1480 | { | 1482 | { |
1481 | struct in6_addr addr; | 1483 | struct in6_addr addr; |
1484 | if (ifp->prefix_len == 127) /* RFC 6164 */ | ||
1485 | return; | ||
1482 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1486 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
1483 | if (ipv6_addr_any(&addr)) | 1487 | if (ipv6_addr_any(&addr)) |
1484 | return; | 1488 | return; |
@@ -1559,6 +1563,11 @@ static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) | |||
1559 | return -1; | 1563 | return -1; |
1560 | } | 1564 | } |
1561 | 1565 | ||
1566 | static int addrconf_ifid_gre(u8 *eui, struct net_device *dev) | ||
1567 | { | ||
1568 | return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); | ||
1569 | } | ||
1570 | |||
1562 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | 1571 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) |
1563 | { | 1572 | { |
1564 | switch (dev->type) { | 1573 | switch (dev->type) { |
@@ -1572,6 +1581,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
1572 | return addrconf_ifid_infiniband(eui, dev); | 1581 | return addrconf_ifid_infiniband(eui, dev); |
1573 | case ARPHRD_SIT: | 1582 | case ARPHRD_SIT: |
1574 | return addrconf_ifid_sit(eui, dev); | 1583 | return addrconf_ifid_sit(eui, dev); |
1584 | case ARPHRD_IPGRE: | ||
1585 | return addrconf_ifid_gre(eui, dev); | ||
1575 | } | 1586 | } |
1576 | return -1; | 1587 | return -1; |
1577 | } | 1588 | } |
@@ -1988,25 +1999,50 @@ ok: | |||
1988 | #ifdef CONFIG_IPV6_PRIVACY | 1999 | #ifdef CONFIG_IPV6_PRIVACY |
1989 | read_lock_bh(&in6_dev->lock); | 2000 | read_lock_bh(&in6_dev->lock); |
1990 | /* update all temporary addresses in the list */ | 2001 | /* update all temporary addresses in the list */ |
1991 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { | 2002 | list_for_each_entry(ift, &in6_dev->tempaddr_list, |
1992 | /* | 2003 | tmp_list) { |
1993 | * When adjusting the lifetimes of an existing | 2004 | int age, max_valid, max_prefered; |
1994 | * temporary address, only lower the lifetimes. | 2005 | |
1995 | * Implementations must not increase the | ||
1996 | * lifetimes of an existing temporary address | ||
1997 | * when processing a Prefix Information Option. | ||
1998 | */ | ||
1999 | if (ifp != ift->ifpub) | 2006 | if (ifp != ift->ifpub) |
2000 | continue; | 2007 | continue; |
2001 | 2008 | ||
2009 | /* | ||
2010 | * RFC 4941 section 3.3: | ||
2011 | * If a received option will extend the lifetime | ||
2012 | * of a public address, the lifetimes of | ||
2013 | * temporary addresses should be extended, | ||
2014 | * subject to the overall constraint that no | ||
2015 | * temporary addresses should ever remain | ||
2016 | * "valid" or "preferred" for a time longer than | ||
2017 | * (TEMP_VALID_LIFETIME) or | ||
2018 | * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), | ||
2019 | * respectively. | ||
2020 | */ | ||
2021 | age = (now - ift->cstamp) / HZ; | ||
2022 | max_valid = in6_dev->cnf.temp_valid_lft - age; | ||
2023 | if (max_valid < 0) | ||
2024 | max_valid = 0; | ||
2025 | |||
2026 | max_prefered = in6_dev->cnf.temp_prefered_lft - | ||
2027 | in6_dev->cnf.max_desync_factor - | ||
2028 | age; | ||
2029 | if (max_prefered < 0) | ||
2030 | max_prefered = 0; | ||
2031 | |||
2032 | if (valid_lft > max_valid) | ||
2033 | valid_lft = max_valid; | ||
2034 | |||
2035 | if (prefered_lft > max_prefered) | ||
2036 | prefered_lft = max_prefered; | ||
2037 | |||
2002 | spin_lock(&ift->lock); | 2038 | spin_lock(&ift->lock); |
2003 | flags = ift->flags; | 2039 | flags = ift->flags; |
2004 | if (ift->valid_lft > valid_lft && | 2040 | ift->valid_lft = valid_lft; |
2005 | ift->valid_lft - valid_lft > (jiffies - ift->tstamp) / HZ) | 2041 | ift->prefered_lft = prefered_lft; |
2006 | ift->valid_lft = valid_lft + (jiffies - ift->tstamp) / HZ; | 2042 | ift->tstamp = now; |
2007 | if (ift->prefered_lft > prefered_lft && | 2043 | if (prefered_lft > 0) |
2008 | ift->prefered_lft - prefered_lft > (jiffies - ift->tstamp) / HZ) | 2044 | ift->flags &= ~IFA_F_DEPRECATED; |
2009 | ift->prefered_lft = prefered_lft + (jiffies - ift->tstamp) / HZ; | 2045 | |
2010 | spin_unlock(&ift->lock); | 2046 | spin_unlock(&ift->lock); |
2011 | if (!(flags&IFA_F_TENTATIVE)) | 2047 | if (!(flags&IFA_F_TENTATIVE)) |
2012 | ipv6_ifa_notify(0, ift); | 2048 | ipv6_ifa_notify(0, ift); |
@@ -2014,9 +2050,11 @@ ok: | |||
2014 | 2050 | ||
2015 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { | 2051 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { |
2016 | /* | 2052 | /* |
2017 | * When a new public address is created as described in [ADDRCONF], | 2053 | * When a new public address is created as |
2018 | * also create a new temporary address. Also create a temporary | 2054 | * described in [ADDRCONF], also create a new |
2019 | * address if it's enabled but no temporary address currently exists. | 2055 | * temporary address. Also create a temporary |
2056 | * address if it's enabled but no temporary | ||
2057 | * address currently exists. | ||
2020 | */ | 2058 | */ |
2021 | read_unlock_bh(&in6_dev->lock); | 2059 | read_unlock_bh(&in6_dev->lock); |
2022 | ipv6_create_tempaddr(ifp, NULL); | 2060 | ipv6_create_tempaddr(ifp, NULL); |
@@ -2423,6 +2461,29 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2423 | } | 2461 | } |
2424 | #endif | 2462 | #endif |
2425 | 2463 | ||
2464 | #if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE) | ||
2465 | static void addrconf_gre_config(struct net_device *dev) | ||
2466 | { | ||
2467 | struct inet6_dev *idev; | ||
2468 | struct in6_addr addr; | ||
2469 | |||
2470 | pr_info("ipv6: addrconf_gre_config(%s)\n", dev->name); | ||
2471 | |||
2472 | ASSERT_RTNL(); | ||
2473 | |||
2474 | if ((idev = ipv6_find_idev(dev)) == NULL) { | ||
2475 | printk(KERN_DEBUG "init gre: add_dev failed\n"); | ||
2476 | return; | ||
2477 | } | ||
2478 | |||
2479 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
2480 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
2481 | |||
2482 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
2483 | addrconf_add_linklocal(idev, &addr); | ||
2484 | } | ||
2485 | #endif | ||
2486 | |||
2426 | static inline int | 2487 | static inline int |
2427 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | 2488 | ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) |
2428 | { | 2489 | { |
@@ -2539,6 +2600,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2539 | addrconf_sit_config(dev); | 2600 | addrconf_sit_config(dev); |
2540 | break; | 2601 | break; |
2541 | #endif | 2602 | #endif |
2603 | #if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE) | ||
2604 | case ARPHRD_IPGRE: | ||
2605 | addrconf_gre_config(dev); | ||
2606 | break; | ||
2607 | #endif | ||
2542 | case ARPHRD_TUNNEL6: | 2608 | case ARPHRD_TUNNEL6: |
2543 | addrconf_ip6_tnl_config(dev); | 2609 | addrconf_ip6_tnl_config(dev); |
2544 | break; | 2610 | break; |
@@ -4692,16 +4758,20 @@ int __init addrconf_init(void) | |||
4692 | if (err < 0) | 4758 | if (err < 0) |
4693 | goto errout_af; | 4759 | goto errout_af; |
4694 | 4760 | ||
4695 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo); | 4761 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo, |
4762 | NULL); | ||
4696 | if (err < 0) | 4763 | if (err < 0) |
4697 | goto errout; | 4764 | goto errout; |
4698 | 4765 | ||
4699 | /* Only the first call to __rtnl_register can fail */ | 4766 | /* Only the first call to __rtnl_register can fail */ |
4700 | __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL); | 4767 | __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL); |
4701 | __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL); | 4768 | __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL); |
4702 | __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr); | 4769 | __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, |
4703 | __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr); | 4770 | inet6_dump_ifaddr, NULL); |
4704 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr); | 4771 | __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, |
4772 | inet6_dump_ifmcaddr, NULL); | ||
4773 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, | ||
4774 | inet6_dump_ifacaddr, NULL); | ||
4705 | 4775 | ||
4706 | ipv6_addr_label_rtnl_register(); | 4776 | ipv6_addr_label_rtnl_register(); |
4707 | 4777 | ||
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index c8993e5a337..2d8ddba9ee5 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -592,8 +592,11 @@ out: | |||
592 | 592 | ||
593 | void __init ipv6_addr_label_rtnl_register(void) | 593 | void __init ipv6_addr_label_rtnl_register(void) |
594 | { | 594 | { |
595 | __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL); | 595 | __rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, |
596 | __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL); | 596 | NULL, NULL); |
597 | __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump); | 597 | __rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, |
598 | NULL, NULL); | ||
599 | __rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, | ||
600 | ip6addrlbl_dump, NULL); | ||
598 | } | 601 | } |
599 | 602 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3b5669a2582..4252b3cc183 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -63,6 +63,20 @@ | |||
63 | #include <asm/system.h> | 63 | #include <asm/system.h> |
64 | #include <linux/mroute6.h> | 64 | #include <linux/mroute6.h> |
65 | 65 | ||
66 | #ifdef CONFIG_ANDROID_PARANOID_NETWORK | ||
67 | #include <linux/android_aid.h> | ||
68 | |||
69 | static inline int current_has_network(void) | ||
70 | { | ||
71 | return in_egroup_p(AID_INET) || capable(CAP_NET_RAW); | ||
72 | } | ||
73 | #else | ||
74 | static inline int current_has_network(void) | ||
75 | { | ||
76 | return 1; | ||
77 | } | ||
78 | #endif | ||
79 | |||
66 | MODULE_AUTHOR("Cast of dozens"); | 80 | MODULE_AUTHOR("Cast of dozens"); |
67 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); | 81 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); |
68 | MODULE_LICENSE("GPL"); | 82 | MODULE_LICENSE("GPL"); |
@@ -109,6 +123,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, | |||
109 | int try_loading_module = 0; | 123 | int try_loading_module = 0; |
110 | int err; | 124 | int err; |
111 | 125 | ||
126 | if (!current_has_network()) | ||
127 | return -EACCES; | ||
128 | |||
112 | if (sock->type != SOCK_RAW && | 129 | if (sock->type != SOCK_RAW && |
113 | sock->type != SOCK_DGRAM && | 130 | sock->type != SOCK_DGRAM && |
114 | !inet_ehash_secret) | 131 | !inet_ehash_secret) |
@@ -477,6 +494,21 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
477 | 494 | ||
478 | EXPORT_SYMBOL(inet6_getname); | 495 | EXPORT_SYMBOL(inet6_getname); |
479 | 496 | ||
497 | int inet6_killaddr_ioctl(struct net *net, void __user *arg) { | ||
498 | struct in6_ifreq ireq; | ||
499 | struct sockaddr_in6 sin6; | ||
500 | |||
501 | if (!capable(CAP_NET_ADMIN)) | ||
502 | return -EACCES; | ||
503 | |||
504 | if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) | ||
505 | return -EFAULT; | ||
506 | |||
507 | sin6.sin6_family = AF_INET6; | ||
508 | ipv6_addr_copy(&sin6.sin6_addr, &ireq.ifr6_addr); | ||
509 | return tcp_nuke_addr(net, (struct sockaddr *) &sin6); | ||
510 | } | ||
511 | |||
480 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 512 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
481 | { | 513 | { |
482 | struct sock *sk = sock->sk; | 514 | struct sock *sk = sock->sk; |
@@ -501,6 +533,8 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
501 | return addrconf_del_ifaddr(net, (void __user *) arg); | 533 | return addrconf_del_ifaddr(net, (void __user *) arg); |
502 | case SIOCSIFDSTADDR: | 534 | case SIOCSIFDSTADDR: |
503 | return addrconf_set_dstaddr(net, (void __user *) arg); | 535 | return addrconf_set_dstaddr(net, (void __user *) arg); |
536 | case SIOCKILLADDR: | ||
537 | return inet6_killaddr_ioctl(net, (void __user *) arg); | ||
504 | default: | 538 | default: |
505 | if (!sk->sk_prot->ioctl) | 539 | if (!sk->sk_prot->ioctl) |
506 | return -ENOIOCTLCMD; | 540 | return -ENOIOCTLCMD; |
@@ -875,6 +909,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
875 | skb_reset_transport_header(skb); | 909 | skb_reset_transport_header(skb); |
876 | __skb_push(skb, skb_gro_offset(skb)); | 910 | __skb_push(skb, skb_gro_offset(skb)); |
877 | 911 | ||
912 | ops = rcu_dereference(inet6_protos[proto]); | ||
878 | if (!ops || !ops->gro_receive) | 913 | if (!ops || !ops->gro_receive) |
879 | goto out_unlock; | 914 | goto out_unlock; |
880 | 915 | ||
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2195ae65192..4c0f894d084 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err) | |||
324 | #endif | 324 | #endif |
325 | } | 325 | } |
326 | 326 | ||
327 | err = ah->nexthdr; | ||
328 | |||
329 | kfree(AH_SKB_CB(skb)->tmp); | 327 | kfree(AH_SKB_CB(skb)->tmp); |
330 | xfrm_output_resume(skb, err); | 328 | xfrm_output_resume(skb, err); |
331 | } | 329 | } |
@@ -466,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err) | |||
466 | if (err) | 464 | if (err) |
467 | goto out; | 465 | goto out; |
468 | 466 | ||
467 | err = ah->nexthdr; | ||
468 | |||
469 | skb->network_header += ah_hlen; | 469 | skb->network_header += ah_hlen; |
470 | memcpy(skb_network_header(skb), work_iph, hdr_len); | 470 | memcpy(skb_network_header(skb), work_iph, hdr_len); |
471 | __skb_pull(skb, ah_hlen + hdr_len); | 471 | __skb_pull(skb, ah_hlen + hdr_len); |
472 | skb_set_transport_header(skb, -hdr_len); | 472 | skb_set_transport_header(skb, -hdr_len); |
473 | |||
474 | err = ah->nexthdr; | ||
475 | out: | 473 | out: |
476 | kfree(AH_SKB_CB(skb)->tmp); | 474 | kfree(AH_SKB_CB(skb)->tmp); |
477 | xfrm_input_resume(skb, err); | 475 | xfrm_input_resume(skb, err); |
@@ -583,8 +581,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
583 | if (err == -EINPROGRESS) | 581 | if (err == -EINPROGRESS) |
584 | goto out; | 582 | goto out; |
585 | 583 | ||
586 | if (err == -EBUSY) | ||
587 | err = NET_XMIT_DROP; | ||
588 | goto out_free; | 584 | goto out_free; |
589 | } | 585 | } |
590 | 586 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 16560336eb7..b46e9f88ce3 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -33,6 +33,11 @@ | |||
33 | #include <linux/errqueue.h> | 33 | #include <linux/errqueue.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | 35 | ||
36 | static inline int ipv6_mapped_addr_any(const struct in6_addr *a) | ||
37 | { | ||
38 | return (ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0)); | ||
39 | } | ||
40 | |||
36 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 41 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
37 | { | 42 | { |
38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 43 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
@@ -102,10 +107,12 @@ ipv4_connected: | |||
102 | 107 | ||
103 | ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr); | 108 | ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr); |
104 | 109 | ||
105 | if (ipv6_addr_any(&np->saddr)) | 110 | if (ipv6_addr_any(&np->saddr) || |
111 | ipv6_mapped_addr_any(&np->saddr)) | ||
106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); | 112 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); |
107 | 113 | ||
108 | if (ipv6_addr_any(&np->rcv_saddr)) { | 114 | if (ipv6_addr_any(&np->rcv_saddr) || |
115 | ipv6_mapped_addr_any(&np->rcv_saddr)) { | ||
109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, | 116 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, |
110 | &np->rcv_saddr); | 117 | &np->rcv_saddr); |
111 | if (sk->sk_prot->rehash) | 118 | if (sk->sk_prot->rehash) |
@@ -592,7 +599,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
592 | return 0; | 599 | return 0; |
593 | } | 600 | } |
594 | 601 | ||
595 | int datagram_send_ctl(struct net *net, | 602 | int datagram_send_ctl(struct net *net, struct sock *sk, |
596 | struct msghdr *msg, struct flowi6 *fl6, | 603 | struct msghdr *msg, struct flowi6 *fl6, |
597 | struct ipv6_txoptions *opt, | 604 | struct ipv6_txoptions *opt, |
598 | int *hlimit, int *tclass, int *dontfrag) | 605 | int *hlimit, int *tclass, int *dontfrag) |
@@ -651,7 +658,8 @@ int datagram_send_ctl(struct net *net, | |||
651 | 658 | ||
652 | if (addr_type != IPV6_ADDR_ANY) { | 659 | if (addr_type != IPV6_ADDR_ANY) { |
653 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; | 660 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
654 | if (!ipv6_chk_addr(net, &src_info->ipi6_addr, | 661 | if (!inet_sk(sk)->transparent && |
662 | !ipv6_chk_addr(net, &src_info->ipi6_addr, | ||
655 | strict ? dev : NULL, 0)) | 663 | strict ? dev : NULL, 0)) |
656 | err = -EINVAL; | 664 | err = -EINVAL; |
657 | else | 665 | else |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index b5319723370..73f1a00a96a 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <net/inet_connection_sock.h> | 20 | #include <net/inet_connection_sock.h> |
21 | #include <net/inet_hashtables.h> | 21 | #include <net/inet_hashtables.h> |
22 | #include <net/inet6_hashtables.h> | 22 | #include <net/inet6_hashtables.h> |
23 | #include <net/secure_seq.h> | ||
23 | #include <net/ip.h> | 24 | #include <net/ip.h> |
24 | 25 | ||
25 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) | 26 | int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4076a0b14b2..320d91d20ad 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1455 | RT6_TRACE("aging clone %p\n", rt); | 1455 | RT6_TRACE("aging clone %p\n", rt); |
1456 | return -1; | 1456 | return -1; |
1457 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1457 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && |
1458 | (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) { | 1458 | (!(dst_get_neighbour_raw(&rt->dst)->flags & NTF_ROUTER))) { |
1459 | RT6_TRACE("purging route %p via non-router but gateway\n", | 1459 | RT6_TRACE("purging route %p via non-router but gateway\n", |
1460 | rt); | 1460 | rt); |
1461 | return -1; | 1461 | return -1; |
@@ -1586,7 +1586,8 @@ int __init fib6_init(void) | |||
1586 | if (ret) | 1586 | if (ret) |
1587 | goto out_kmem_cache_create; | 1587 | goto out_kmem_cache_create; |
1588 | 1588 | ||
1589 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | 1589 | ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, |
1590 | NULL); | ||
1590 | if (ret) | 1591 | if (ret) |
1591 | goto out_unregister_subsys; | 1592 | goto out_unregister_subsys; |
1592 | out: | 1593 | out: |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index f3caf1b8d57..54303945019 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -322,8 +322,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo | |||
322 | } | 322 | } |
323 | 323 | ||
324 | static struct ip6_flowlabel * | 324 | static struct ip6_flowlabel * |
325 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | 325 | fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, |
326 | int optlen, int *err_p) | 326 | char __user *optval, int optlen, int *err_p) |
327 | { | 327 | { |
328 | struct ip6_flowlabel *fl = NULL; | 328 | struct ip6_flowlabel *fl = NULL; |
329 | int olen; | 329 | int olen; |
@@ -360,7 +360,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
360 | msg.msg_control = (void*)(fl->opt+1); | 360 | msg.msg_control = (void*)(fl->opt+1); |
361 | memset(&flowi6, 0, sizeof(flowi6)); | 361 | memset(&flowi6, 0, sizeof(flowi6)); |
362 | 362 | ||
363 | err = datagram_send_ctl(net, &msg, &flowi6, fl->opt, &junk, | 363 | err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk, |
364 | &junk, &junk); | 364 | &junk, &junk); |
365 | if (err) | 365 | if (err) |
366 | goto done; | 366 | goto done; |
@@ -528,7 +528,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
528 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) | 528 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) |
529 | return -EINVAL; | 529 | return -EINVAL; |
530 | 530 | ||
531 | fl = fl_create(net, &freq, optval, optlen, &err); | 531 | fl = fl_create(net, sk, &freq, optval, optlen, &err); |
532 | if (fl == NULL) | 532 | if (fl == NULL) |
533 | return err; | 533 | return err; |
534 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); | 534 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9d4b165837d..55a35c1dede 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -100,6 +100,7 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
100 | { | 100 | { |
101 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
102 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
103 | struct neighbour *neigh; | ||
103 | 104 | ||
104 | skb->protocol = htons(ETH_P_IPV6); | 105 | skb->protocol = htons(ETH_P_IPV6); |
105 | skb->dev = dev; | 106 | skb->dev = dev; |
@@ -134,11 +135,15 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
134 | skb->len); | 135 | skb->len); |
135 | } | 136 | } |
136 | 137 | ||
137 | if (dst->hh) | 138 | rcu_read_lock(); |
138 | return neigh_hh_output(dst->hh, skb); | 139 | neigh = dst_get_neighbour(dst); |
139 | else if (dst->neighbour) | 140 | if (neigh) { |
140 | return dst->neighbour->output(skb); | 141 | int res = neigh_output(neigh, skb); |
141 | 142 | ||
143 | rcu_read_unlock(); | ||
144 | return res; | ||
145 | } | ||
146 | rcu_read_unlock(); | ||
142 | IP6_INC_STATS_BH(dev_net(dst->dev), | 147 | IP6_INC_STATS_BH(dev_net(dst->dev), |
143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 148 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
144 | kfree_skb(skb); | 149 | kfree_skb(skb); |
@@ -385,6 +390,7 @@ int ip6_forward(struct sk_buff *skb) | |||
385 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 390 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
386 | struct inet6_skb_parm *opt = IP6CB(skb); | 391 | struct inet6_skb_parm *opt = IP6CB(skb); |
387 | struct net *net = dev_net(dst->dev); | 392 | struct net *net = dev_net(dst->dev); |
393 | struct neighbour *n; | ||
388 | u32 mtu; | 394 | u32 mtu; |
389 | 395 | ||
390 | if (net->ipv6.devconf_all->forwarding == 0) | 396 | if (net->ipv6.devconf_all->forwarding == 0) |
@@ -459,11 +465,10 @@ int ip6_forward(struct sk_buff *skb) | |||
459 | send redirects to source routed frames. | 465 | send redirects to source routed frames. |
460 | We don't send redirects to frames decapsulated from IPsec. | 466 | We don't send redirects to frames decapsulated from IPsec. |
461 | */ | 467 | */ |
462 | if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 && | 468 | n = dst_get_neighbour(dst); |
463 | !skb_sec_path(skb)) { | 469 | if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) { |
464 | struct in6_addr *target = NULL; | 470 | struct in6_addr *target = NULL; |
465 | struct rt6_info *rt; | 471 | struct rt6_info *rt; |
466 | struct neighbour *n = dst->neighbour; | ||
467 | 472 | ||
468 | /* | 473 | /* |
469 | * incoming and outgoing devices are the same | 474 | * incoming and outgoing devices are the same |
@@ -596,6 +601,31 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
596 | return offset; | 601 | return offset; |
597 | } | 602 | } |
598 | 603 | ||
604 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | ||
605 | { | ||
606 | static atomic_t ipv6_fragmentation_id; | ||
607 | int old, new; | ||
608 | |||
609 | if (rt && !(rt->dst.flags & DST_NOPEER)) { | ||
610 | struct inet_peer *peer; | ||
611 | |||
612 | if (!rt->rt6i_peer) | ||
613 | rt6_bind_peer(rt, 1); | ||
614 | peer = rt->rt6i_peer; | ||
615 | if (peer) { | ||
616 | fhdr->identification = htonl(inet_getid(peer, 0)); | ||
617 | return; | ||
618 | } | ||
619 | } | ||
620 | do { | ||
621 | old = atomic_read(&ipv6_fragmentation_id); | ||
622 | new = old + 1; | ||
623 | if (!new) | ||
624 | new = 1; | ||
625 | } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); | ||
626 | fhdr->identification = htonl(new); | ||
627 | } | ||
628 | |||
599 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 629 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
600 | { | 630 | { |
601 | struct sk_buff *frag; | 631 | struct sk_buff *frag; |
@@ -680,7 +710,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
680 | skb_reset_network_header(skb); | 710 | skb_reset_network_header(skb); |
681 | memcpy(skb_network_header(skb), tmp_hdr, hlen); | 711 | memcpy(skb_network_header(skb), tmp_hdr, hlen); |
682 | 712 | ||
683 | ipv6_select_ident(fh); | 713 | ipv6_select_ident(fh, rt); |
684 | fh->nexthdr = nexthdr; | 714 | fh->nexthdr = nexthdr; |
685 | fh->reserved = 0; | 715 | fh->reserved = 0; |
686 | fh->frag_off = htons(IP6_MF); | 716 | fh->frag_off = htons(IP6_MF); |
@@ -826,7 +856,7 @@ slow_path: | |||
826 | fh->nexthdr = nexthdr; | 856 | fh->nexthdr = nexthdr; |
827 | fh->reserved = 0; | 857 | fh->reserved = 0; |
828 | if (!frag_id) { | 858 | if (!frag_id) { |
829 | ipv6_select_ident(fh); | 859 | ipv6_select_ident(fh, rt); |
830 | frag_id = fh->identification; | 860 | frag_id = fh->identification; |
831 | } else | 861 | } else |
832 | fh->identification = frag_id; | 862 | fh->identification = frag_id; |
@@ -920,8 +950,11 @@ out: | |||
920 | static int ip6_dst_lookup_tail(struct sock *sk, | 950 | static int ip6_dst_lookup_tail(struct sock *sk, |
921 | struct dst_entry **dst, struct flowi6 *fl6) | 951 | struct dst_entry **dst, struct flowi6 *fl6) |
922 | { | 952 | { |
923 | int err; | ||
924 | struct net *net = sock_net(sk); | 953 | struct net *net = sock_net(sk); |
954 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
955 | struct neighbour *n; | ||
956 | #endif | ||
957 | int err; | ||
925 | 958 | ||
926 | if (*dst == NULL) | 959 | if (*dst == NULL) |
927 | *dst = ip6_route_output(net, sk, fl6); | 960 | *dst = ip6_route_output(net, sk, fl6); |
@@ -947,11 +980,14 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
947 | * dst entry and replace it instead with the | 980 | * dst entry and replace it instead with the |
948 | * dst entry of the nexthop router | 981 | * dst entry of the nexthop router |
949 | */ | 982 | */ |
950 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { | 983 | rcu_read_lock(); |
984 | n = dst_get_neighbour(*dst); | ||
985 | if (n && !(n->nud_state & NUD_VALID)) { | ||
951 | struct inet6_ifaddr *ifp; | 986 | struct inet6_ifaddr *ifp; |
952 | struct flowi6 fl_gw6; | 987 | struct flowi6 fl_gw6; |
953 | int redirect; | 988 | int redirect; |
954 | 989 | ||
990 | rcu_read_unlock(); | ||
955 | ifp = ipv6_get_ifaddr(net, &fl6->saddr, | 991 | ifp = ipv6_get_ifaddr(net, &fl6->saddr, |
956 | (*dst)->dev, 1); | 992 | (*dst)->dev, 1); |
957 | 993 | ||
@@ -971,6 +1007,8 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
971 | if ((err = (*dst)->error)) | 1007 | if ((err = (*dst)->error)) |
972 | goto out_err_release; | 1008 | goto out_err_release; |
973 | } | 1009 | } |
1010 | } else { | ||
1011 | rcu_read_unlock(); | ||
974 | } | 1012 | } |
975 | #endif | 1013 | #endif |
976 | 1014 | ||
@@ -1072,7 +1110,8 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1072 | int getfrag(void *from, char *to, int offset, int len, | 1110 | int getfrag(void *from, char *to, int offset, int len, |
1073 | int odd, struct sk_buff *skb), | 1111 | int odd, struct sk_buff *skb), |
1074 | void *from, int length, int hh_len, int fragheaderlen, | 1112 | void *from, int length, int hh_len, int fragheaderlen, |
1075 | int transhdrlen, int mtu,unsigned int flags) | 1113 | int transhdrlen, int mtu,unsigned int flags, |
1114 | struct rt6_info *rt) | ||
1076 | 1115 | ||
1077 | { | 1116 | { |
1078 | struct sk_buff *skb; | 1117 | struct sk_buff *skb; |
@@ -1116,7 +1155,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1116 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - | 1155 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - |
1117 | sizeof(struct frag_hdr)) & ~7; | 1156 | sizeof(struct frag_hdr)) & ~7; |
1118 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1157 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1119 | ipv6_select_ident(&fhdr); | 1158 | ipv6_select_ident(&fhdr, rt); |
1120 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | 1159 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; |
1121 | __skb_queue_tail(&sk->sk_write_queue, skb); | 1160 | __skb_queue_tail(&sk->sk_write_queue, skb); |
1122 | 1161 | ||
@@ -1282,7 +1321,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1282 | 1321 | ||
1283 | err = ip6_ufo_append_data(sk, getfrag, from, length, | 1322 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1284 | hh_len, fragheaderlen, | 1323 | hh_len, fragheaderlen, |
1285 | transhdrlen, mtu, flags); | 1324 | transhdrlen, mtu, flags, rt); |
1286 | if (err) | 1325 | if (err) |
1287 | goto error; | 1326 | goto error; |
1288 | return 0; | 1327 | return 0; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 36c2842a86b..4e6922f1c68 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | 41 | ||
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/atomic.h> | 43 | #include <linux/atomic.h> |
44 | 44 | ||
45 | #include <net/icmp.h> | 45 | #include <net/icmp.h> |
46 | #include <net/ip.h> | 46 | #include <net/ip.h> |
@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) | |||
289 | if ((err = register_netdevice(dev)) < 0) | 289 | if ((err = register_netdevice(dev)) < 0) |
290 | goto failed_free; | 290 | goto failed_free; |
291 | 291 | ||
292 | strcpy(t->parms.name, dev->name); | ||
293 | |||
292 | dev_hold(dev); | 294 | dev_hold(dev); |
293 | ip6_tnl_link(ip6n, t); | 295 | ip6_tnl_link(ip6n, t); |
294 | return t; | 296 | return t; |
@@ -1397,7 +1399,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) | |||
1397 | struct ip6_tnl *t = netdev_priv(dev); | 1399 | struct ip6_tnl *t = netdev_priv(dev); |
1398 | 1400 | ||
1399 | t->dev = dev; | 1401 | t->dev = dev; |
1400 | strcpy(t->parms.name, dev->name); | ||
1401 | dev->tstats = alloc_percpu(struct pcpu_tstats); | 1402 | dev->tstats = alloc_percpu(struct pcpu_tstats); |
1402 | if (!dev->tstats) | 1403 | if (!dev->tstats) |
1403 | return -ENOMEM; | 1404 | return -ENOMEM; |
@@ -1477,6 +1478,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) | |||
1477 | static int __net_init ip6_tnl_init_net(struct net *net) | 1478 | static int __net_init ip6_tnl_init_net(struct net *net) |
1478 | { | 1479 | { |
1479 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1480 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
1481 | struct ip6_tnl *t = NULL; | ||
1480 | int err; | 1482 | int err; |
1481 | 1483 | ||
1482 | ip6n->tnls[0] = ip6n->tnls_wc; | 1484 | ip6n->tnls[0] = ip6n->tnls_wc; |
@@ -1497,6 +1499,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
1497 | err = register_netdev(ip6n->fb_tnl_dev); | 1499 | err = register_netdev(ip6n->fb_tnl_dev); |
1498 | if (err < 0) | 1500 | if (err < 0) |
1499 | goto err_register; | 1501 | goto err_register; |
1502 | |||
1503 | t = netdev_priv(ip6n->fb_tnl_dev); | ||
1504 | |||
1505 | strcpy(t->parms.name, ip6n->fb_tnl_dev->name); | ||
1500 | return 0; | 1506 | return 0; |
1501 | 1507 | ||
1502 | err_register: | 1508 | err_register: |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 82a809901f8..def0538e241 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -696,8 +696,10 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
696 | int err; | 696 | int err; |
697 | 697 | ||
698 | err = ip6mr_fib_lookup(net, &fl6, &mrt); | 698 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
699 | if (err < 0) | 699 | if (err < 0) { |
700 | kfree_skb(skb); | ||
700 | return err; | 701 | return err; |
702 | } | ||
701 | 703 | ||
702 | read_lock(&mrt_lock); | 704 | read_lock(&mrt_lock); |
703 | dev->stats.tx_bytes += skb->len; | 705 | dev->stats.tx_bytes += skb->len; |
@@ -1354,7 +1356,8 @@ int __init ip6_mr_init(void) | |||
1354 | goto add_proto_fail; | 1356 | goto add_proto_fail; |
1355 | } | 1357 | } |
1356 | #endif | 1358 | #endif |
1357 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute); | 1359 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, |
1360 | ip6mr_rtm_dumproute, NULL); | ||
1358 | return 0; | 1361 | return 0; |
1359 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1362 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1360 | add_proto_fail: | 1363 | add_proto_fail: |
@@ -2051,8 +2054,10 @@ int ip6_mr_input(struct sk_buff *skb) | |||
2051 | int err; | 2054 | int err; |
2052 | 2055 | ||
2053 | err = ip6mr_fib_lookup(net, &fl6, &mrt); | 2056 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
2054 | if (err < 0) | 2057 | if (err < 0) { |
2058 | kfree_skb(skb); | ||
2055 | return err; | 2059 | return err; |
2060 | } | ||
2056 | 2061 | ||
2057 | read_lock(&mrt_lock); | 2062 | read_lock(&mrt_lock); |
2058 | cache = ip6mr_cache_find(mrt, | 2063 | cache = ip6mr_cache_find(mrt, |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 9cb191ecaba..2fbda5fc4cc 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -475,7 +475,7 @@ sticky_done: | |||
475 | msg.msg_controllen = optlen; | 475 | msg.msg_controllen = optlen; |
476 | msg.msg_control = (void*)(opt+1); | 476 | msg.msg_control = (void*)(opt+1); |
477 | 477 | ||
478 | retv = datagram_send_ctl(net, &msg, &fl6, opt, &junk, &junk, | 478 | retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk, |
479 | &junk); | 479 | &junk); |
480 | if (retv) | 480 | if (retv) |
481 | goto done; | 481 | goto done; |
@@ -913,7 +913,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, | |||
913 | } | 913 | } |
914 | 914 | ||
915 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | 915 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, |
916 | char __user *optval, int __user *optlen) | 916 | char __user *optval, int __user *optlen, unsigned flags) |
917 | { | 917 | { |
918 | struct ipv6_pinfo *np = inet6_sk(sk); | 918 | struct ipv6_pinfo *np = inet6_sk(sk); |
919 | int len; | 919 | int len; |
@@ -962,7 +962,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
962 | 962 | ||
963 | msg.msg_control = optval; | 963 | msg.msg_control = optval; |
964 | msg.msg_controllen = len; | 964 | msg.msg_controllen = len; |
965 | msg.msg_flags = 0; | 965 | msg.msg_flags = flags; |
966 | 966 | ||
967 | lock_sock(sk); | 967 | lock_sock(sk); |
968 | skb = np->pktoptions; | 968 | skb = np->pktoptions; |
@@ -1222,7 +1222,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1222 | if(level != SOL_IPV6) | 1222 | if(level != SOL_IPV6) |
1223 | return -ENOPROTOOPT; | 1223 | return -ENOPROTOOPT; |
1224 | 1224 | ||
1225 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); | 1225 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, 0); |
1226 | #ifdef CONFIG_NETFILTER | 1226 | #ifdef CONFIG_NETFILTER |
1227 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | 1227 | /* we need to exclude all possible ENOPROTOOPTs except default case */ |
1228 | if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { | 1228 | if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { |
@@ -1264,7 +1264,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1264 | return compat_mc_getsockopt(sk, level, optname, optval, optlen, | 1264 | return compat_mc_getsockopt(sk, level, optname, optval, optlen, |
1265 | ipv6_getsockopt); | 1265 | ipv6_getsockopt); |
1266 | 1266 | ||
1267 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); | 1267 | err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, |
1268 | MSG_CMSG_COMPAT); | ||
1268 | #ifdef CONFIG_NETFILTER | 1269 | #ifdef CONFIG_NETFILTER |
1269 | /* we need to exclude all possible ENOPROTOOPTs except default case */ | 1270 | /* we need to exclude all possible ENOPROTOOPTs except default case */ |
1270 | if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { | 1271 | if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3e6ebcdb477..ee7839f4d6e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1059,7 +1059,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
1059 | break; | 1059 | break; |
1060 | for (i=0; i<nsrcs; i++) { | 1060 | for (i=0; i<nsrcs; i++) { |
1061 | /* skip inactive filters */ | 1061 | /* skip inactive filters */ |
1062 | if (pmc->mca_sfcount[MCAST_INCLUDE] || | 1062 | if (psf->sf_count[MCAST_INCLUDE] || |
1063 | pmc->mca_sfcount[MCAST_EXCLUDE] != | 1063 | pmc->mca_sfcount[MCAST_EXCLUDE] != |
1064 | psf->sf_count[MCAST_EXCLUDE]) | 1064 | psf->sf_count[MCAST_EXCLUDE]) |
1065 | continue; | 1065 | continue; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 7596f071d30..9da6e02eaae 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -107,8 +107,6 @@ static const struct neigh_ops ndisc_generic_ops = { | |||
107 | .error_report = ndisc_error_report, | 107 | .error_report = ndisc_error_report, |
108 | .output = neigh_resolve_output, | 108 | .output = neigh_resolve_output, |
109 | .connected_output = neigh_connected_output, | 109 | .connected_output = neigh_connected_output, |
110 | .hh_output = dev_queue_xmit, | ||
111 | .queue_xmit = dev_queue_xmit, | ||
112 | }; | 110 | }; |
113 | 111 | ||
114 | static const struct neigh_ops ndisc_hh_ops = { | 112 | static const struct neigh_ops ndisc_hh_ops = { |
@@ -117,17 +115,13 @@ static const struct neigh_ops ndisc_hh_ops = { | |||
117 | .error_report = ndisc_error_report, | 115 | .error_report = ndisc_error_report, |
118 | .output = neigh_resolve_output, | 116 | .output = neigh_resolve_output, |
119 | .connected_output = neigh_resolve_output, | 117 | .connected_output = neigh_resolve_output, |
120 | .hh_output = dev_queue_xmit, | ||
121 | .queue_xmit = dev_queue_xmit, | ||
122 | }; | 118 | }; |
123 | 119 | ||
124 | 120 | ||
125 | static const struct neigh_ops ndisc_direct_ops = { | 121 | static const struct neigh_ops ndisc_direct_ops = { |
126 | .family = AF_INET6, | 122 | .family = AF_INET6, |
127 | .output = dev_queue_xmit, | 123 | .output = neigh_direct_output, |
128 | .connected_output = dev_queue_xmit, | 124 | .connected_output = neigh_direct_output, |
129 | .hh_output = dev_queue_xmit, | ||
130 | .queue_xmit = dev_queue_xmit, | ||
131 | }; | 125 | }; |
132 | 126 | ||
133 | struct neigh_table nd_tbl = { | 127 | struct neigh_table nd_tbl = { |
@@ -392,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh) | |||
392 | if (!dev->header_ops) { | 386 | if (!dev->header_ops) { |
393 | neigh->nud_state = NUD_NOARP; | 387 | neigh->nud_state = NUD_NOARP; |
394 | neigh->ops = &ndisc_direct_ops; | 388 | neigh->ops = &ndisc_direct_ops; |
395 | neigh->output = neigh->ops->queue_xmit; | 389 | neigh->output = neigh_direct_output; |
396 | } else { | 390 | } else { |
397 | if (is_multicast) { | 391 | if (is_multicast) { |
398 | neigh->nud_state = NUD_NOARP; | 392 | neigh->nud_state = NUD_NOARP; |
@@ -1244,7 +1238,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1244 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); | 1238 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); |
1245 | 1239 | ||
1246 | if (rt) | 1240 | if (rt) |
1247 | neigh = rt->rt6i_nexthop; | 1241 | neigh = dst_get_neighbour(&rt->dst); |
1248 | 1242 | ||
1249 | if (rt && lifetime == 0) { | 1243 | if (rt && lifetime == 0) { |
1250 | neigh_clone(neigh); | 1244 | neigh_clone(neigh); |
@@ -1265,7 +1259,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1265 | return; | 1259 | return; |
1266 | } | 1260 | } |
1267 | 1261 | ||
1268 | neigh = rt->rt6i_nexthop; | 1262 | neigh = dst_get_neighbour(&rt->dst); |
1269 | if (neigh == NULL) { | 1263 | if (neigh == NULL) { |
1270 | ND_PRINTK0(KERN_ERR | 1264 | ND_PRINTK0(KERN_ERR |
1271 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1265 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 448464844a2..5bbf5316920 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -174,6 +174,18 @@ config IP6_NF_TARGET_REJECT | |||
174 | 174 | ||
175 | To compile it as a module, choose M here. If unsure, say N. | 175 | To compile it as a module, choose M here. If unsure, say N. |
176 | 176 | ||
177 | config IP6_NF_TARGET_REJECT_SKERR | ||
178 | bool "Force socket error when rejecting with icmp*" | ||
179 | depends on IP6_NF_TARGET_REJECT | ||
180 | default n | ||
181 | help | ||
182 | This option enables turning a "--reject-with icmp*" into a matching | ||
183 | socket error also. | ||
184 | The REJECT target normally allows sending an ICMP message. But it | ||
185 | leaves the local socket unaware of any ingress rejects. | ||
186 | |||
187 | If unsure, say N. | ||
188 | |||
177 | config IP6_NF_MANGLE | 189 | config IP6_NF_MANGLE |
178 | tristate "Packet mangling" | 190 | tristate "Packet mangling" |
179 | default m if NETFILTER_ADVANCED=n | 191 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 24939486328..e63c3972a73 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -218,6 +218,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
218 | return skb; | 218 | return skb; |
219 | 219 | ||
220 | nlmsg_failure: | 220 | nlmsg_failure: |
221 | kfree_skb(skb); | ||
221 | *errp = -EINVAL; | 222 | *errp = -EINVAL; |
222 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); | 223 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); |
223 | return NULL; | 224 | return NULL; |
@@ -313,7 +314,7 @@ ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) | |||
313 | { | 314 | { |
314 | struct nf_queue_entry *entry; | 315 | struct nf_queue_entry *entry; |
315 | 316 | ||
316 | if (vmsg->value > NF_MAX_VERDICT) | 317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) |
317 | return -EINVAL; | 318 | return -EINVAL; |
318 | 319 | ||
319 | entry = ipq_find_dequeue_entry(vmsg->id); | 320 | entry = ipq_find_dequeue_entry(vmsg->id); |
@@ -358,12 +359,9 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg, | |||
358 | break; | 359 | break; |
359 | 360 | ||
360 | case IPQM_VERDICT: | 361 | case IPQM_VERDICT: |
361 | if (pmsg->msg.verdict.value > NF_MAX_VERDICT) | 362 | status = ipq_set_verdict(&pmsg->msg.verdict, |
362 | status = -EINVAL; | 363 | len - sizeof(*pmsg)); |
363 | else | 364 | break; |
364 | status = ipq_set_verdict(&pmsg->msg.verdict, | ||
365 | len - sizeof(*pmsg)); | ||
366 | break; | ||
367 | default: | 365 | default: |
368 | status = -EINVAL; | 366 | status = -EINVAL; |
369 | } | 367 | } |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 94874b0bdcd..14cb310064f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -2292,16 +2292,15 @@ static void __exit ip6_tables_fini(void) | |||
2292 | * "No next header". | 2292 | * "No next header". |
2293 | * | 2293 | * |
2294 | * If target header is found, its offset is set in *offset and return protocol | 2294 | * If target header is found, its offset is set in *offset and return protocol |
2295 | * number. Otherwise, return -1. | 2295 | * number. Otherwise, return -ENOENT or -EBADMSG. |
2296 | * | 2296 | * |
2297 | * If the first fragment doesn't contain the final protocol header or | 2297 | * If the first fragment doesn't contain the final protocol header or |
2298 | * NEXTHDR_NONE it is considered invalid. | 2298 | * NEXTHDR_NONE it is considered invalid. |
2299 | * | 2299 | * |
2300 | * Note that non-1st fragment is special case that "the protocol number | 2300 | * Note that non-1st fragment is special case that "the protocol number |
2301 | * of last header" is "next header" field in Fragment header. In this case, | 2301 | * of last header" is "next header" field in Fragment header. In this case, |
2302 | * *offset is meaningless and fragment offset is stored in *fragoff if fragoff | 2302 | * *offset is meaningless. If fragoff is not NULL, the fragment offset is |
2303 | * isn't NULL. | 2303 | * stored in *fragoff; if it is NULL, return -EINVAL. |
2304 | * | ||
2305 | */ | 2304 | */ |
2306 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | 2305 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, |
2307 | int target, unsigned short *fragoff) | 2306 | int target, unsigned short *fragoff) |
@@ -2342,9 +2341,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
2342 | if (target < 0 && | 2341 | if (target < 0 && |
2343 | ((!ipv6_ext_hdr(hp->nexthdr)) || | 2342 | ((!ipv6_ext_hdr(hp->nexthdr)) || |
2344 | hp->nexthdr == NEXTHDR_NONE)) { | 2343 | hp->nexthdr == NEXTHDR_NONE)) { |
2345 | if (fragoff) | 2344 | if (fragoff) { |
2346 | *fragoff = _frag_off; | 2345 | *fragoff = _frag_off; |
2347 | return hp->nexthdr; | 2346 | return hp->nexthdr; |
2347 | } else { | ||
2348 | return -EINVAL; | ||
2349 | } | ||
2348 | } | 2350 | } |
2349 | return -ENOENT; | 2351 | return -ENOENT; |
2350 | } | 2352 | } |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index a5a4c5dd539..09d30498c92 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -177,6 +177,15 @@ send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code, | |||
177 | skb_in->dev = net->loopback_dev; | 177 | skb_in->dev = net->loopback_dev; |
178 | 178 | ||
179 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); | 179 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); |
180 | #ifdef CONFIG_IP6_NF_TARGET_REJECT_SKERR | ||
181 | if (skb_in->sk) { | ||
182 | icmpv6_err_convert(ICMPV6_DEST_UNREACH, code, | ||
183 | &skb_in->sk->sk_err); | ||
184 | skb_in->sk->sk_error_report(skb_in->sk); | ||
185 | pr_debug("ip6t_REJECT: sk_err=%d for skb=%p sk=%p\n", | ||
186 | skb_in->sk->sk_err, skb_in, skb_in->sk); | ||
187 | } | ||
188 | #endif | ||
180 | } | 189 | } |
181 | 190 | ||
182 | static unsigned int | 191 | static unsigned int |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index cc7313b8f7e..343852e5c70 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -817,8 +817,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
818 | opt->tot_len = sizeof(struct ipv6_txoptions); | 818 | opt->tot_len = sizeof(struct ipv6_txoptions); |
819 | 819 | ||
820 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, | 820 | err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, |
821 | &tclass, &dontfrag); | 821 | &hlimit, &tclass, &dontfrag); |
822 | if (err < 0) { | 822 | if (err < 0) { |
823 | fl6_sock_release(flowlabel); | 823 | fl6_sock_release(flowlabel); |
824 | return err; | 824 | return err; |
@@ -959,57 +959,54 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
959 | return -EFAULT; | 959 | return -EFAULT; |
960 | 960 | ||
961 | switch (optname) { | 961 | switch (optname) { |
962 | case IPV6_CHECKSUM: | 962 | case IPV6_CHECKSUM: |
963 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && | 963 | if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && |
964 | level == IPPROTO_IPV6) { | 964 | level == IPPROTO_IPV6) { |
965 | /* | 965 | /* |
966 | * RFC3542 tells that IPV6_CHECKSUM socket | 966 | * RFC3542 tells that IPV6_CHECKSUM socket |
967 | * option in the IPPROTO_IPV6 level is not | 967 | * option in the IPPROTO_IPV6 level is not |
968 | * allowed on ICMPv6 sockets. | 968 | * allowed on ICMPv6 sockets. |
969 | * If you want to set it, use IPPROTO_RAW | 969 | * If you want to set it, use IPPROTO_RAW |
970 | * level IPV6_CHECKSUM socket option | 970 | * level IPV6_CHECKSUM socket option |
971 | * (Linux extension). | 971 | * (Linux extension). |
972 | */ | 972 | */ |
973 | return -EINVAL; | 973 | return -EINVAL; |
974 | } | 974 | } |
975 | 975 | ||
976 | /* You may get strange result with a positive odd offset; | 976 | /* You may get strange result with a positive odd offset; |
977 | RFC2292bis agrees with me. */ | 977 | RFC2292bis agrees with me. */ |
978 | if (val > 0 && (val&1)) | 978 | if (val > 0 && (val&1)) |
979 | return -EINVAL; | 979 | return -EINVAL; |
980 | if (val < 0) { | 980 | if (val < 0) { |
981 | rp->checksum = 0; | 981 | rp->checksum = 0; |
982 | } else { | 982 | } else { |
983 | rp->checksum = 1; | 983 | rp->checksum = 1; |
984 | rp->offset = val; | 984 | rp->offset = val; |
985 | } | 985 | } |
986 | 986 | ||
987 | return 0; | 987 | return 0; |
988 | break; | ||
989 | 988 | ||
990 | default: | 989 | default: |
991 | return -ENOPROTOOPT; | 990 | return -ENOPROTOOPT; |
992 | } | 991 | } |
993 | } | 992 | } |
994 | 993 | ||
995 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, | 994 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, |
996 | char __user *optval, unsigned int optlen) | 995 | char __user *optval, unsigned int optlen) |
997 | { | 996 | { |
998 | switch(level) { | 997 | switch (level) { |
999 | case SOL_RAW: | 998 | case SOL_RAW: |
1000 | break; | 999 | break; |
1001 | 1000 | ||
1002 | case SOL_ICMPV6: | 1001 | case SOL_ICMPV6: |
1003 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) | 1002 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
1004 | return -EOPNOTSUPP; | 1003 | return -EOPNOTSUPP; |
1005 | return rawv6_seticmpfilter(sk, level, optname, optval, | 1004 | return rawv6_seticmpfilter(sk, level, optname, optval, optlen); |
1006 | optlen); | 1005 | case SOL_IPV6: |
1007 | case SOL_IPV6: | 1006 | if (optname == IPV6_CHECKSUM) |
1008 | if (optname == IPV6_CHECKSUM) | 1007 | break; |
1009 | break; | 1008 | default: |
1010 | default: | 1009 | return ipv6_setsockopt(sk, level, optname, optval, optlen); |
1011 | return ipv6_setsockopt(sk, level, optname, optval, | ||
1012 | optlen); | ||
1013 | } | 1010 | } |
1014 | 1011 | ||
1015 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | 1012 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
@@ -1075,21 +1072,19 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1075 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, | 1072 | static int rawv6_getsockopt(struct sock *sk, int level, int optname, |
1076 | char __user *optval, int __user *optlen) | 1073 | char __user *optval, int __user *optlen) |
1077 | { | 1074 | { |
1078 | switch(level) { | 1075 | switch (level) { |
1079 | case SOL_RAW: | 1076 | case SOL_RAW: |
1080 | break; | 1077 | break; |
1081 | 1078 | ||
1082 | case SOL_ICMPV6: | 1079 | case SOL_ICMPV6: |
1083 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) | 1080 | if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
1084 | return -EOPNOTSUPP; | 1081 | return -EOPNOTSUPP; |
1085 | return rawv6_geticmpfilter(sk, level, optname, optval, | 1082 | return rawv6_geticmpfilter(sk, level, optname, optval, optlen); |
1086 | optlen); | 1083 | case SOL_IPV6: |
1087 | case SOL_IPV6: | 1084 | if (optname == IPV6_CHECKSUM) |
1088 | if (optname == IPV6_CHECKSUM) | 1085 | break; |
1089 | break; | 1086 | default: |
1090 | default: | 1087 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
1091 | return ipv6_getsockopt(sk, level, optname, optval, | ||
1092 | optlen); | ||
1093 | } | 1088 | } |
1094 | 1089 | ||
1095 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | 1090 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
@@ -1119,31 +1114,29 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1119 | 1114 | ||
1120 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | 1115 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) |
1121 | { | 1116 | { |
1122 | switch(cmd) { | 1117 | switch (cmd) { |
1123 | case SIOCOUTQ: | 1118 | case SIOCOUTQ: { |
1124 | { | 1119 | int amount = sk_wmem_alloc_get(sk); |
1125 | int amount = sk_wmem_alloc_get(sk); | ||
1126 | 1120 | ||
1127 | return put_user(amount, (int __user *)arg); | 1121 | return put_user(amount, (int __user *)arg); |
1128 | } | 1122 | } |
1129 | case SIOCINQ: | 1123 | case SIOCINQ: { |
1130 | { | 1124 | struct sk_buff *skb; |
1131 | struct sk_buff *skb; | 1125 | int amount = 0; |
1132 | int amount = 0; | 1126 | |
1133 | 1127 | spin_lock_bh(&sk->sk_receive_queue.lock); | |
1134 | spin_lock_bh(&sk->sk_receive_queue.lock); | 1128 | skb = skb_peek(&sk->sk_receive_queue); |
1135 | skb = skb_peek(&sk->sk_receive_queue); | 1129 | if (skb != NULL) |
1136 | if (skb != NULL) | 1130 | amount = skb->tail - skb->transport_header; |
1137 | amount = skb->tail - skb->transport_header; | 1131 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
1138 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 1132 | return put_user(amount, (int __user *)arg); |
1139 | return put_user(amount, (int __user *)arg); | 1133 | } |
1140 | } | ||
1141 | 1134 | ||
1142 | default: | 1135 | default: |
1143 | #ifdef CONFIG_IPV6_MROUTE | 1136 | #ifdef CONFIG_IPV6_MROUTE |
1144 | return ip6mr_ioctl(sk, cmd, (void __user *)arg); | 1137 | return ip6mr_ioctl(sk, cmd, (void __user *)arg); |
1145 | #else | 1138 | #else |
1146 | return -ENOIOCTLCMD; | 1139 | return -ENOIOCTLCMD; |
1147 | #endif | 1140 | #endif |
1148 | } | 1141 | } |
1149 | } | 1142 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0ef1f086feb..f02fe523bd3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -72,7 +72,8 @@ | |||
72 | #define RT6_TRACE(x...) do { ; } while (0) | 72 | #define RT6_TRACE(x...) do { ; } while (0) |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); | 75 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
76 | const struct in6_addr *dest); | ||
76 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 77 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
77 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 78 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
78 | static unsigned int ip6_default_mtu(const struct dst_entry *dst); | 79 | static unsigned int ip6_default_mtu(const struct dst_entry *dst); |
@@ -103,6 +104,9 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
103 | struct inet_peer *peer; | 104 | struct inet_peer *peer; |
104 | u32 *p = NULL; | 105 | u32 *p = NULL; |
105 | 106 | ||
107 | if (!(rt->dst.flags & DST_HOST)) | ||
108 | return NULL; | ||
109 | |||
106 | if (!rt->rt6i_peer) | 110 | if (!rt->rt6i_peer) |
107 | rt6_bind_peer(rt, 1); | 111 | rt6_bind_peer(rt, 1); |
108 | 112 | ||
@@ -127,6 +131,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
127 | return p; | 131 | return p; |
128 | } | 132 | } |
129 | 133 | ||
134 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | ||
135 | { | ||
136 | return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev); | ||
137 | } | ||
138 | |||
130 | static struct dst_ops ip6_dst_ops_template = { | 139 | static struct dst_ops ip6_dst_ops_template = { |
131 | .family = AF_INET6, | 140 | .family = AF_INET6, |
132 | .protocol = cpu_to_be16(ETH_P_IPV6), | 141 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -142,6 +151,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
142 | .link_failure = ip6_link_failure, | 151 | .link_failure = ip6_link_failure, |
143 | .update_pmtu = ip6_rt_update_pmtu, | 152 | .update_pmtu = ip6_rt_update_pmtu, |
144 | .local_out = __ip6_local_out, | 153 | .local_out = __ip6_local_out, |
154 | .neigh_lookup = ip6_neigh_lookup, | ||
145 | }; | 155 | }; |
146 | 156 | ||
147 | static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) | 157 | static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) |
@@ -168,6 +178,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
168 | .default_advmss = ip6_default_advmss, | 178 | .default_advmss = ip6_default_advmss, |
169 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 179 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
170 | .cow_metrics = ip6_rt_blackhole_cow_metrics, | 180 | .cow_metrics = ip6_rt_blackhole_cow_metrics, |
181 | .neigh_lookup = ip6_neigh_lookup, | ||
171 | }; | 182 | }; |
172 | 183 | ||
173 | static const u32 ip6_template_metrics[RTAX_MAX] = { | 184 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
@@ -233,7 +244,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | |||
233 | { | 244 | { |
234 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); | 245 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
235 | 246 | ||
236 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | 247 | if (rt != NULL) |
248 | memset(&rt->rt6i_table, 0, | ||
249 | sizeof(*rt) - sizeof(struct dst_entry)); | ||
237 | 250 | ||
238 | return rt; | 251 | return rt; |
239 | } | 252 | } |
@@ -244,6 +257,9 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
244 | struct inet6_dev *idev = rt->rt6i_idev; | 257 | struct inet6_dev *idev = rt->rt6i_idev; |
245 | struct inet_peer *peer = rt->rt6i_peer; | 258 | struct inet_peer *peer = rt->rt6i_peer; |
246 | 259 | ||
260 | if (!(rt->dst.flags & DST_HOST)) | ||
261 | dst_destroy_metrics_generic(dst); | ||
262 | |||
247 | if (idev != NULL) { | 263 | if (idev != NULL) { |
248 | rt->rt6i_idev = NULL; | 264 | rt->rt6i_idev = NULL; |
249 | in6_dev_put(idev); | 265 | in6_dev_put(idev); |
@@ -356,7 +372,7 @@ out: | |||
356 | #ifdef CONFIG_IPV6_ROUTER_PREF | 372 | #ifdef CONFIG_IPV6_ROUTER_PREF |
357 | static void rt6_probe(struct rt6_info *rt) | 373 | static void rt6_probe(struct rt6_info *rt) |
358 | { | 374 | { |
359 | struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL; | 375 | struct neighbour *neigh; |
360 | /* | 376 | /* |
361 | * Okay, this does not seem to be appropriate | 377 | * Okay, this does not seem to be appropriate |
362 | * for now, however, we need to check if it | 378 | * for now, however, we need to check if it |
@@ -365,8 +381,10 @@ static void rt6_probe(struct rt6_info *rt) | |||
365 | * Router Reachability Probe MUST be rate-limited | 381 | * Router Reachability Probe MUST be rate-limited |
366 | * to no more than one per minute. | 382 | * to no more than one per minute. |
367 | */ | 383 | */ |
384 | rcu_read_lock(); | ||
385 | neigh = rt ? dst_get_neighbour(&rt->dst) : NULL; | ||
368 | if (!neigh || (neigh->nud_state & NUD_VALID)) | 386 | if (!neigh || (neigh->nud_state & NUD_VALID)) |
369 | return; | 387 | goto out; |
370 | read_lock_bh(&neigh->lock); | 388 | read_lock_bh(&neigh->lock); |
371 | if (!(neigh->nud_state & NUD_VALID) && | 389 | if (!(neigh->nud_state & NUD_VALID) && |
372 | time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { | 390 | time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { |
@@ -379,8 +397,11 @@ static void rt6_probe(struct rt6_info *rt) | |||
379 | target = (struct in6_addr *)&neigh->primary_key; | 397 | target = (struct in6_addr *)&neigh->primary_key; |
380 | addrconf_addr_solict_mult(target, &mcaddr); | 398 | addrconf_addr_solict_mult(target, &mcaddr); |
381 | ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); | 399 | ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); |
382 | } else | 400 | } else { |
383 | read_unlock_bh(&neigh->lock); | 401 | read_unlock_bh(&neigh->lock); |
402 | } | ||
403 | out: | ||
404 | rcu_read_unlock(); | ||
384 | } | 405 | } |
385 | #else | 406 | #else |
386 | static inline void rt6_probe(struct rt6_info *rt) | 407 | static inline void rt6_probe(struct rt6_info *rt) |
@@ -404,8 +425,11 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif) | |||
404 | 425 | ||
405 | static inline int rt6_check_neigh(struct rt6_info *rt) | 426 | static inline int rt6_check_neigh(struct rt6_info *rt) |
406 | { | 427 | { |
407 | struct neighbour *neigh = rt->rt6i_nexthop; | 428 | struct neighbour *neigh; |
408 | int m; | 429 | int m; |
430 | |||
431 | rcu_read_lock(); | ||
432 | neigh = dst_get_neighbour(&rt->dst); | ||
409 | if (rt->rt6i_flags & RTF_NONEXTHOP || | 433 | if (rt->rt6i_flags & RTF_NONEXTHOP || |
410 | !(rt->rt6i_flags & RTF_GATEWAY)) | 434 | !(rt->rt6i_flags & RTF_GATEWAY)) |
411 | m = 1; | 435 | m = 1; |
@@ -422,6 +446,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt) | |||
422 | read_unlock_bh(&neigh->lock); | 446 | read_unlock_bh(&neigh->lock); |
423 | } else | 447 | } else |
424 | m = 0; | 448 | m = 0; |
449 | rcu_read_unlock(); | ||
425 | return m; | 450 | return m; |
426 | } | 451 | } |
427 | 452 | ||
@@ -683,7 +708,8 @@ int ip6_ins_rt(struct rt6_info *rt) | |||
683 | return __ip6_ins_rt(rt, &info); | 708 | return __ip6_ins_rt(rt, &info); |
684 | } | 709 | } |
685 | 710 | ||
686 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, | 711 | static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, |
712 | const struct in6_addr *daddr, | ||
687 | const struct in6_addr *saddr) | 713 | const struct in6_addr *saddr) |
688 | { | 714 | { |
689 | struct rt6_info *rt; | 715 | struct rt6_info *rt; |
@@ -692,23 +718,20 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add | |||
692 | * Clone the route. | 718 | * Clone the route. |
693 | */ | 719 | */ |
694 | 720 | ||
695 | rt = ip6_rt_copy(ort); | 721 | rt = ip6_rt_copy(ort, daddr); |
696 | 722 | ||
697 | if (rt) { | 723 | if (rt) { |
698 | struct neighbour *neigh; | 724 | struct neighbour *neigh; |
699 | int attempts = !in_softirq(); | 725 | int attempts = !in_softirq(); |
700 | 726 | ||
701 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { | 727 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { |
702 | if (rt->rt6i_dst.plen != 128 && | 728 | if (ort->rt6i_dst.plen != 128 && |
703 | ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) | 729 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) |
704 | rt->rt6i_flags |= RTF_ANYCAST; | 730 | rt->rt6i_flags |= RTF_ANYCAST; |
705 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 731 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
706 | } | 732 | } |
707 | 733 | ||
708 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | ||
709 | rt->rt6i_dst.plen = 128; | ||
710 | rt->rt6i_flags |= RTF_CACHE; | 734 | rt->rt6i_flags |= RTF_CACHE; |
711 | rt->dst.flags |= DST_HOST; | ||
712 | 735 | ||
713 | #ifdef CONFIG_IPV6_SUBTREES | 736 | #ifdef CONFIG_IPV6_SUBTREES |
714 | if (rt->rt6i_src.plen && saddr) { | 737 | if (rt->rt6i_src.plen && saddr) { |
@@ -745,22 +768,21 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add | |||
745 | dst_free(&rt->dst); | 768 | dst_free(&rt->dst); |
746 | return NULL; | 769 | return NULL; |
747 | } | 770 | } |
748 | rt->rt6i_nexthop = neigh; | 771 | dst_set_neighbour(&rt->dst, neigh); |
749 | 772 | ||
750 | } | 773 | } |
751 | 774 | ||
752 | return rt; | 775 | return rt; |
753 | } | 776 | } |
754 | 777 | ||
755 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr) | 778 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, |
779 | const struct in6_addr *daddr) | ||
756 | { | 780 | { |
757 | struct rt6_info *rt = ip6_rt_copy(ort); | 781 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); |
782 | |||
758 | if (rt) { | 783 | if (rt) { |
759 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | ||
760 | rt->rt6i_dst.plen = 128; | ||
761 | rt->rt6i_flags |= RTF_CACHE; | 784 | rt->rt6i_flags |= RTF_CACHE; |
762 | rt->dst.flags |= DST_HOST; | 785 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); |
763 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); | ||
764 | } | 786 | } |
765 | return rt; | 787 | return rt; |
766 | } | 788 | } |
@@ -794,7 +816,7 @@ restart: | |||
794 | dst_hold(&rt->dst); | 816 | dst_hold(&rt->dst); |
795 | read_unlock_bh(&table->tb6_lock); | 817 | read_unlock_bh(&table->tb6_lock); |
796 | 818 | ||
797 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 819 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
798 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); | 820 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
799 | else if (!(rt->dst.flags & DST_HOST)) | 821 | else if (!(rt->dst.flags & DST_HOST)) |
800 | nrt = rt6_alloc_clone(rt, &fl6->daddr); | 822 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
@@ -900,7 +922,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
900 | new->input = dst_discard; | 922 | new->input = dst_discard; |
901 | new->output = dst_discard; | 923 | new->output = dst_discard; |
902 | 924 | ||
903 | dst_copy_metrics(new, &ort->dst); | 925 | if (dst_metrics_read_only(&ort->dst)) |
926 | new->_metrics = ort->dst._metrics; | ||
927 | else | ||
928 | dst_copy_metrics(new, &ort->dst); | ||
904 | rt->rt6i_idev = ort->rt6i_idev; | 929 | rt->rt6i_idev = ort->rt6i_idev; |
905 | if (rt->rt6i_idev) | 930 | if (rt->rt6i_idev) |
906 | in6_dev_hold(rt->rt6i_idev); | 931 | in6_dev_hold(rt->rt6i_idev); |
@@ -1057,11 +1082,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1057 | neigh = NULL; | 1082 | neigh = NULL; |
1058 | } | 1083 | } |
1059 | 1084 | ||
1060 | rt->rt6i_idev = idev; | 1085 | rt->dst.flags |= DST_HOST; |
1061 | rt->rt6i_nexthop = neigh; | 1086 | rt->dst.output = ip6_output; |
1087 | dst_set_neighbour(&rt->dst, neigh); | ||
1062 | atomic_set(&rt->dst.__refcnt, 1); | 1088 | atomic_set(&rt->dst.__refcnt, 1); |
1089 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | ||
1090 | rt->rt6i_dst.plen = 128; | ||
1091 | rt->rt6i_idev = idev; | ||
1063 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1092 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
1064 | rt->dst.output = ip6_output; | ||
1065 | 1093 | ||
1066 | spin_lock_bh(&icmp6_dst_lock); | 1094 | spin_lock_bh(&icmp6_dst_lock); |
1067 | rt->dst.next = icmp6_dst_gc_list; | 1095 | rt->dst.next = icmp6_dst_gc_list; |
@@ -1239,6 +1267,14 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1239 | if (rt->rt6i_dst.plen == 128) | 1267 | if (rt->rt6i_dst.plen == 128) |
1240 | rt->dst.flags |= DST_HOST; | 1268 | rt->dst.flags |= DST_HOST; |
1241 | 1269 | ||
1270 | if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) { | ||
1271 | u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
1272 | if (!metrics) { | ||
1273 | err = -ENOMEM; | ||
1274 | goto out; | ||
1275 | } | ||
1276 | dst_init_metrics(&rt->dst, metrics, 0); | ||
1277 | } | ||
1242 | #ifdef CONFIG_IPV6_SUBTREES | 1278 | #ifdef CONFIG_IPV6_SUBTREES |
1243 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1279 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
1244 | rt->rt6i_src.plen = cfg->fc_src_len; | 1280 | rt->rt6i_src.plen = cfg->fc_src_len; |
@@ -1338,12 +1374,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1338 | rt->rt6i_prefsrc.plen = 0; | 1374 | rt->rt6i_prefsrc.plen = 0; |
1339 | 1375 | ||
1340 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { | 1376 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { |
1341 | rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); | 1377 | struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); |
1342 | if (IS_ERR(rt->rt6i_nexthop)) { | 1378 | if (IS_ERR(n)) { |
1343 | err = PTR_ERR(rt->rt6i_nexthop); | 1379 | err = PTR_ERR(n); |
1344 | rt->rt6i_nexthop = NULL; | ||
1345 | goto out; | 1380 | goto out; |
1346 | } | 1381 | } |
1382 | dst_set_neighbour(&rt->dst, n); | ||
1347 | } | 1383 | } |
1348 | 1384 | ||
1349 | rt->rt6i_flags = cfg->fc_flags; | 1385 | rt->rt6i_flags = cfg->fc_flags; |
@@ -1574,10 +1610,10 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1574 | dst_confirm(&rt->dst); | 1610 | dst_confirm(&rt->dst); |
1575 | 1611 | ||
1576 | /* Duplicate redirect: silently ignore. */ | 1612 | /* Duplicate redirect: silently ignore. */ |
1577 | if (neigh == rt->dst.neighbour) | 1613 | if (neigh == dst_get_neighbour_raw(&rt->dst)) |
1578 | goto out; | 1614 | goto out; |
1579 | 1615 | ||
1580 | nrt = ip6_rt_copy(rt); | 1616 | nrt = ip6_rt_copy(rt, dest); |
1581 | if (nrt == NULL) | 1617 | if (nrt == NULL) |
1582 | goto out; | 1618 | goto out; |
1583 | 1619 | ||
@@ -1585,12 +1621,8 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1585 | if (on_link) | 1621 | if (on_link) |
1586 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1622 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1587 | 1623 | ||
1588 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); | ||
1589 | nrt->rt6i_dst.plen = 128; | ||
1590 | nrt->dst.flags |= DST_HOST; | ||
1591 | |||
1592 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1624 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
1593 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1625 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1594 | 1626 | ||
1595 | if (ip6_ins_rt(nrt)) | 1627 | if (ip6_ins_rt(nrt)) |
1596 | goto out; | 1628 | goto out; |
@@ -1670,7 +1702,7 @@ again: | |||
1670 | 1. It is connected route. Action: COW | 1702 | 1. It is connected route. Action: COW |
1671 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. | 1703 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. |
1672 | */ | 1704 | */ |
1673 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 1705 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
1674 | nrt = rt6_alloc_cow(rt, daddr, saddr); | 1706 | nrt = rt6_alloc_cow(rt, daddr, saddr); |
1675 | else | 1707 | else |
1676 | nrt = rt6_alloc_clone(rt, daddr); | 1708 | nrt = rt6_alloc_clone(rt, daddr); |
@@ -1723,7 +1755,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad | |||
1723 | * Misc support functions | 1755 | * Misc support functions |
1724 | */ | 1756 | */ |
1725 | 1757 | ||
1726 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1758 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
1759 | const struct in6_addr *dest) | ||
1727 | { | 1760 | { |
1728 | struct net *net = dev_net(ort->rt6i_dev); | 1761 | struct net *net = dev_net(ort->rt6i_dev); |
1729 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 1762 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
@@ -1732,7 +1765,10 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1732 | if (rt) { | 1765 | if (rt) { |
1733 | rt->dst.input = ort->dst.input; | 1766 | rt->dst.input = ort->dst.input; |
1734 | rt->dst.output = ort->dst.output; | 1767 | rt->dst.output = ort->dst.output; |
1768 | rt->dst.flags |= DST_HOST; | ||
1735 | 1769 | ||
1770 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | ||
1771 | rt->rt6i_dst.plen = 128; | ||
1736 | dst_copy_metrics(&rt->dst, &ort->dst); | 1772 | dst_copy_metrics(&rt->dst, &ort->dst); |
1737 | rt->dst.error = ort->dst.error; | 1773 | rt->dst.error = ort->dst.error; |
1738 | rt->rt6i_idev = ort->rt6i_idev; | 1774 | rt->rt6i_idev = ort->rt6i_idev; |
@@ -1745,7 +1781,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1745 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 1781 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
1746 | rt->rt6i_metric = 0; | 1782 | rt->rt6i_metric = 0; |
1747 | 1783 | ||
1748 | memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); | ||
1749 | #ifdef CONFIG_IPV6_SUBTREES | 1784 | #ifdef CONFIG_IPV6_SUBTREES |
1750 | memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); | 1785 | memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); |
1751 | #endif | 1786 | #endif |
@@ -2035,7 +2070,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2035 | 2070 | ||
2036 | return ERR_CAST(neigh); | 2071 | return ERR_CAST(neigh); |
2037 | } | 2072 | } |
2038 | rt->rt6i_nexthop = neigh; | 2073 | dst_set_neighbour(&rt->dst, neigh); |
2039 | 2074 | ||
2040 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 2075 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
2041 | rt->rt6i_dst.plen = 128; | 2076 | rt->rt6i_dst.plen = 128; |
@@ -2312,6 +2347,7 @@ static int rt6_fill_node(struct net *net, | |||
2312 | struct nlmsghdr *nlh; | 2347 | struct nlmsghdr *nlh; |
2313 | long expires; | 2348 | long expires; |
2314 | u32 table; | 2349 | u32 table; |
2350 | struct neighbour *n; | ||
2315 | 2351 | ||
2316 | if (prefix) { /* user wants prefix routes only */ | 2352 | if (prefix) { /* user wants prefix routes only */ |
2317 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { | 2353 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { |
@@ -2400,8 +2436,11 @@ static int rt6_fill_node(struct net *net, | |||
2400 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) | 2436 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2401 | goto nla_put_failure; | 2437 | goto nla_put_failure; |
2402 | 2438 | ||
2403 | if (rt->dst.neighbour) | 2439 | rcu_read_lock(); |
2404 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); | 2440 | n = dst_get_neighbour(&rt->dst); |
2441 | if (n) | ||
2442 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); | ||
2443 | rcu_read_unlock(); | ||
2405 | 2444 | ||
2406 | if (rt->dst.dev) | 2445 | if (rt->dst.dev) |
2407 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2446 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
@@ -2585,6 +2624,7 @@ struct rt6_proc_arg | |||
2585 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) | 2624 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) |
2586 | { | 2625 | { |
2587 | struct seq_file *m = p_arg; | 2626 | struct seq_file *m = p_arg; |
2627 | struct neighbour *n; | ||
2588 | 2628 | ||
2589 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); | 2629 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); |
2590 | 2630 | ||
@@ -2593,12 +2633,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2593 | #else | 2633 | #else |
2594 | seq_puts(m, "00000000000000000000000000000000 00 "); | 2634 | seq_puts(m, "00000000000000000000000000000000 00 "); |
2595 | #endif | 2635 | #endif |
2596 | 2636 | rcu_read_lock(); | |
2597 | if (rt->rt6i_nexthop) { | 2637 | n = dst_get_neighbour(&rt->dst); |
2598 | seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key); | 2638 | if (n) { |
2639 | seq_printf(m, "%pi6", n->primary_key); | ||
2599 | } else { | 2640 | } else { |
2600 | seq_puts(m, "00000000000000000000000000000000"); | 2641 | seq_puts(m, "00000000000000000000000000000000"); |
2601 | } | 2642 | } |
2643 | rcu_read_unlock(); | ||
2602 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2644 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
2603 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), | 2645 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
2604 | rt->dst.__use, rt->rt6i_flags, | 2646 | rt->dst.__use, rt->rt6i_flags, |
@@ -2918,9 +2960,9 @@ int __init ip6_route_init(void) | |||
2918 | goto xfrm6_init; | 2960 | goto xfrm6_init; |
2919 | 2961 | ||
2920 | ret = -ENOBUFS; | 2962 | ret = -ENOBUFS; |
2921 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) || | 2963 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || |
2922 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) || | 2964 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || |
2923 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2965 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) |
2924 | goto fib6_rules_init; | 2966 | goto fib6_rules_init; |
2925 | 2967 | ||
2926 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); | 2968 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1cca5761aea..c1e0d63db2e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -263,6 +263,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | |||
263 | if (register_netdevice(dev) < 0) | 263 | if (register_netdevice(dev) < 0) |
264 | goto failed_free; | 264 | goto failed_free; |
265 | 265 | ||
266 | strcpy(nt->parms.name, dev->name); | ||
267 | |||
266 | dev_hold(dev); | 268 | dev_hold(dev); |
267 | 269 | ||
268 | ipip6_tunnel_link(sitn, nt); | 270 | ipip6_tunnel_link(sitn, nt); |
@@ -672,12 +674,15 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
672 | if (skb->protocol != htons(ETH_P_IPV6)) | 674 | if (skb->protocol != htons(ETH_P_IPV6)) |
673 | goto tx_error; | 675 | goto tx_error; |
674 | 676 | ||
677 | if (tos == 1) | ||
678 | tos = ipv6_get_dsfield(iph6); | ||
679 | |||
675 | /* ISATAP (RFC4214) - must come before 6to4 */ | 680 | /* ISATAP (RFC4214) - must come before 6to4 */ |
676 | if (dev->priv_flags & IFF_ISATAP) { | 681 | if (dev->priv_flags & IFF_ISATAP) { |
677 | struct neighbour *neigh = NULL; | 682 | struct neighbour *neigh = NULL; |
678 | 683 | ||
679 | if (skb_dst(skb)) | 684 | if (skb_dst(skb)) |
680 | neigh = skb_dst(skb)->neighbour; | 685 | neigh = dst_get_neighbour(skb_dst(skb)); |
681 | 686 | ||
682 | if (neigh == NULL) { | 687 | if (neigh == NULL) { |
683 | if (net_ratelimit()) | 688 | if (net_ratelimit()) |
@@ -702,7 +707,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
702 | struct neighbour *neigh = NULL; | 707 | struct neighbour *neigh = NULL; |
703 | 708 | ||
704 | if (skb_dst(skb)) | 709 | if (skb_dst(skb)) |
705 | neigh = skb_dst(skb)->neighbour; | 710 | neigh = dst_get_neighbour(skb_dst(skb)); |
706 | 711 | ||
707 | if (neigh == NULL) { | 712 | if (neigh == NULL) { |
708 | if (net_ratelimit()) | 713 | if (net_ratelimit()) |
@@ -1141,7 +1146,6 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1141 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1146 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1142 | 1147 | ||
1143 | tunnel->dev = dev; | 1148 | tunnel->dev = dev; |
1144 | strcpy(tunnel->parms.name, dev->name); | ||
1145 | 1149 | ||
1146 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 1150 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
1147 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 1151 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
@@ -1204,6 +1208,7 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1204 | static int __net_init sit_init_net(struct net *net) | 1208 | static int __net_init sit_init_net(struct net *net) |
1205 | { | 1209 | { |
1206 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1210 | struct sit_net *sitn = net_generic(net, sit_net_id); |
1211 | struct ip_tunnel *t; | ||
1207 | int err; | 1212 | int err; |
1208 | 1213 | ||
1209 | sitn->tunnels[0] = sitn->tunnels_wc; | 1214 | sitn->tunnels[0] = sitn->tunnels_wc; |
@@ -1228,6 +1233,9 @@ static int __net_init sit_init_net(struct net *net) | |||
1228 | if ((err = register_netdev(sitn->fb_tunnel_dev))) | 1233 | if ((err = register_netdev(sitn->fb_tunnel_dev))) |
1229 | goto err_reg_dev; | 1234 | goto err_reg_dev; |
1230 | 1235 | ||
1236 | t = netdev_priv(sitn->fb_tunnel_dev); | ||
1237 | |||
1238 | strcpy(t->parms.name, sitn->fb_tunnel_dev->name); | ||
1231 | return 0; | 1239 | return 0; |
1232 | 1240 | ||
1233 | err_reg_dev: | 1241 | err_reg_dev: |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 8b9644a8b69..ac838965ff3 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -165,7 +165,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
165 | int mss; | 165 | int mss; |
166 | struct dst_entry *dst; | 166 | struct dst_entry *dst; |
167 | __u8 rcv_wscale; | 167 | __u8 rcv_wscale; |
168 | bool ecn_ok; | 168 | bool ecn_ok = false; |
169 | 169 | ||
170 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 170 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
171 | goto out; | 171 | goto out; |
@@ -223,6 +223,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
223 | ireq->wscale_ok = tcp_opt.wscale_ok; | 223 | ireq->wscale_ok = tcp_opt.wscale_ok; |
224 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 224 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |
225 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | 225 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; |
226 | treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; | ||
226 | treq->rcv_isn = ntohl(th->seq) - 1; | 227 | treq->rcv_isn = ntohl(th->seq) - 1; |
227 | treq->snt_isn = cookie; | 228 | treq->snt_isn = cookie; |
228 | 229 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 87551ca568c..cdbce216521 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <net/timewait_sock.h> | 61 | #include <net/timewait_sock.h> |
62 | #include <net/netdma.h> | 62 | #include <net/netdma.h> |
63 | #include <net/inet_common.h> | 63 | #include <net/inet_common.h> |
64 | #include <net/secure_seq.h> | ||
64 | 65 | ||
65 | #include <asm/uaccess.h> | 66 | #include <asm/uaccess.h> |
66 | 67 | ||
@@ -530,20 +531,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | |||
530 | return tcp_v6_send_synack(sk, req, rvp); | 531 | return tcp_v6_send_synack(sk, req, rvp); |
531 | } | 532 | } |
532 | 533 | ||
533 | static inline void syn_flood_warning(struct sk_buff *skb) | ||
534 | { | ||
535 | #ifdef CONFIG_SYN_COOKIES | ||
536 | if (sysctl_tcp_syncookies) | ||
537 | printk(KERN_INFO | ||
538 | "TCPv6: Possible SYN flooding on port %d. " | ||
539 | "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest)); | ||
540 | else | ||
541 | #endif | ||
542 | printk(KERN_INFO | ||
543 | "TCPv6: Possible SYN flooding on port %d. " | ||
544 | "Dropping request.\n", ntohs(tcp_hdr(skb)->dest)); | ||
545 | } | ||
546 | |||
547 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
548 | { | 535 | { |
549 | kfree_skb(inet6_rsk(req)->pktopts); | 536 | kfree_skb(inet6_rsk(req)->pktopts); |
@@ -604,7 +591,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | |||
604 | } | 591 | } |
605 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | 592 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
606 | } | 593 | } |
607 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 594 | if (tp->md5sig_info->entries6 == 0 && |
595 | tcp_alloc_md5sig_pool(sk) == NULL) { | ||
608 | kfree(newkey); | 596 | kfree(newkey); |
609 | return -ENOMEM; | 597 | return -ENOMEM; |
610 | } | 598 | } |
@@ -613,8 +601,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | |||
613 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); | 601 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); |
614 | 602 | ||
615 | if (!keys) { | 603 | if (!keys) { |
616 | tcp_free_md5sig_pool(); | ||
617 | kfree(newkey); | 604 | kfree(newkey); |
605 | if (tp->md5sig_info->entries6 == 0) | ||
606 | tcp_free_md5sig_pool(); | ||
618 | return -ENOMEM; | 607 | return -ENOMEM; |
619 | } | 608 | } |
620 | 609 | ||
@@ -660,6 +649,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) | |||
660 | kfree(tp->md5sig_info->keys6); | 649 | kfree(tp->md5sig_info->keys6); |
661 | tp->md5sig_info->keys6 = NULL; | 650 | tp->md5sig_info->keys6 = NULL; |
662 | tp->md5sig_info->alloced6 = 0; | 651 | tp->md5sig_info->alloced6 = 0; |
652 | tcp_free_md5sig_pool(); | ||
663 | } else { | 653 | } else { |
664 | /* shrink the database */ | 654 | /* shrink the database */ |
665 | if (tp->md5sig_info->entries6 != i) | 655 | if (tp->md5sig_info->entries6 != i) |
@@ -668,7 +658,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) | |||
668 | (tp->md5sig_info->entries6 - i) | 658 | (tp->md5sig_info->entries6 - i) |
669 | * sizeof (tp->md5sig_info->keys6[0])); | 659 | * sizeof (tp->md5sig_info->keys6[0])); |
670 | } | 660 | } |
671 | tcp_free_md5sig_pool(); | ||
672 | return 0; | 661 | return 0; |
673 | } | 662 | } |
674 | } | 663 | } |
@@ -1093,7 +1082,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1093 | 1082 | ||
1094 | #ifdef CONFIG_TCP_MD5SIG | 1083 | #ifdef CONFIG_TCP_MD5SIG |
1095 | if (sk) | 1084 | if (sk) |
1096 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); | 1085 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr); |
1097 | #endif | 1086 | #endif |
1098 | 1087 | ||
1099 | if (th->ack) | 1088 | if (th->ack) |
@@ -1178,11 +1167,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1178 | struct tcp_sock *tp = tcp_sk(sk); | 1167 | struct tcp_sock *tp = tcp_sk(sk); |
1179 | __u32 isn = TCP_SKB_CB(skb)->when; | 1168 | __u32 isn = TCP_SKB_CB(skb)->when; |
1180 | struct dst_entry *dst = NULL; | 1169 | struct dst_entry *dst = NULL; |
1181 | #ifdef CONFIG_SYN_COOKIES | ||
1182 | int want_cookie = 0; | 1170 | int want_cookie = 0; |
1183 | #else | ||
1184 | #define want_cookie 0 | ||
1185 | #endif | ||
1186 | 1171 | ||
1187 | if (skb->protocol == htons(ETH_P_IP)) | 1172 | if (skb->protocol == htons(ETH_P_IP)) |
1188 | return tcp_v4_conn_request(sk, skb); | 1173 | return tcp_v4_conn_request(sk, skb); |
@@ -1191,14 +1176,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1191 | goto drop; | 1176 | goto drop; |
1192 | 1177 | ||
1193 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1178 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1194 | if (net_ratelimit()) | 1179 | want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6"); |
1195 | syn_flood_warning(skb); | 1180 | if (!want_cookie) |
1196 | #ifdef CONFIG_SYN_COOKIES | 1181 | goto drop; |
1197 | if (sysctl_tcp_syncookies) | ||
1198 | want_cookie = 1; | ||
1199 | else | ||
1200 | #endif | ||
1201 | goto drop; | ||
1202 | } | 1182 | } |
1203 | 1183 | ||
1204 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) | 1184 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) |
@@ -1248,9 +1228,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1248 | while (l-- > 0) | 1228 | while (l-- > 0) |
1249 | *c++ ^= *hash_location++; | 1229 | *c++ ^= *hash_location++; |
1250 | 1230 | ||
1251 | #ifdef CONFIG_SYN_COOKIES | ||
1252 | want_cookie = 0; /* not our kind of cookie */ | 1231 | want_cookie = 0; /* not our kind of cookie */ |
1253 | #endif | ||
1254 | tmp_ext.cookie_out_never = 0; /* false */ | 1232 | tmp_ext.cookie_out_never = 0; /* false */ |
1255 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | 1233 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; |
1256 | } else if (!tp->rx_opt.cookie_in_always) { | 1234 | } else if (!tp->rx_opt.cookie_in_always) { |
@@ -1341,6 +1319,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1341 | } | 1319 | } |
1342 | have_isn: | 1320 | have_isn: |
1343 | tcp_rsk(req)->snt_isn = isn; | 1321 | tcp_rsk(req)->snt_isn = isn; |
1322 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1344 | 1323 | ||
1345 | security_inet_conn_request(sk, skb, req); | 1324 | security_inet_conn_request(sk, skb, req); |
1346 | 1325 | ||
@@ -1406,6 +1385,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1406 | newtp->af_specific = &tcp_sock_ipv6_mapped_specific; | 1385 | newtp->af_specific = &tcp_sock_ipv6_mapped_specific; |
1407 | #endif | 1386 | #endif |
1408 | 1387 | ||
1388 | newnp->ipv6_ac_list = NULL; | ||
1389 | newnp->ipv6_fl_list = NULL; | ||
1409 | newnp->pktoptions = NULL; | 1390 | newnp->pktoptions = NULL; |
1410 | newnp->opt = NULL; | 1391 | newnp->opt = NULL; |
1411 | newnp->mcast_oif = inet6_iif(skb); | 1392 | newnp->mcast_oif = inet6_iif(skb); |
@@ -1470,6 +1451,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1470 | First: no IPv4 options. | 1451 | First: no IPv4 options. |
1471 | */ | 1452 | */ |
1472 | newinet->inet_opt = NULL; | 1453 | newinet->inet_opt = NULL; |
1454 | newnp->ipv6_ac_list = NULL; | ||
1473 | newnp->ipv6_fl_list = NULL; | 1455 | newnp->ipv6_fl_list = NULL; |
1474 | 1456 | ||
1475 | /* Clone RX bits */ | 1457 | /* Clone RX bits */ |
@@ -1509,6 +1491,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1509 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1491 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1510 | newtp->advmss = dst_metric_advmss(dst); | 1492 | newtp->advmss = dst_metric_advmss(dst); |
1511 | tcp_initialize_rcv_mss(newsk); | 1493 | tcp_initialize_rcv_mss(newsk); |
1494 | if (tcp_rsk(req)->snt_synack) | ||
1495 | tcp_valid_rtt_meas(newsk, | ||
1496 | tcp_time_stamp - tcp_rsk(req)->snt_synack); | ||
1497 | newtp->total_retrans = req->retrans; | ||
1512 | 1498 | ||
1513 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; | 1499 | newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; |
1514 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; | 1500 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 328985c4088..bb95e8e1c6f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1090,8 +1090,8 @@ do_udp_sendmsg: | |||
1090 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1090 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1091 | opt->tot_len = sizeof(*opt); | 1091 | opt->tot_len = sizeof(*opt); |
1092 | 1092 | ||
1093 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, | 1093 | err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, |
1094 | &tclass, &dontfrag); | 1094 | &hlimit, &tclass, &dontfrag); |
1095 | if (err < 0) { | 1095 | if (err < 0) { |
1096 | fl6_sock_release(flowlabel); | 1096 | fl6_sock_release(flowlabel); |
1097 | return err; | 1097 | return err; |
@@ -1359,7 +1359,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) | |||
1359 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); | 1359 | fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); |
1360 | fptr->nexthdr = nexthdr; | 1360 | fptr->nexthdr = nexthdr; |
1361 | fptr->reserved = 0; | 1361 | fptr->reserved = 0; |
1362 | ipv6_select_ident(fptr); | 1362 | ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb)); |
1363 | 1363 | ||
1364 | /* Fragment the skb. ipv6 header and the remaining fields of the | 1364 | /* Fragment the skb. ipv6 header and the remaining fields of the |
1365 | * fragment header are updated in ipv6_gso_segment() | 1365 | * fragment header are updated in ipv6_gso_segment() |