diff options
Diffstat (limited to 'net/ipv6')
36 files changed, 468 insertions, 308 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ed0b9e2e797a..11b13ea69db4 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -156,6 +156,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION | |||
156 | config IPV6_SIT | 156 | config IPV6_SIT |
157 | tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)" | 157 | tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)" |
158 | select INET_TUNNEL | 158 | select INET_TUNNEL |
159 | select NET_IP_TUNNEL | ||
159 | select IPV6_NDISC_NODETYPE | 160 | select IPV6_NDISC_NODETYPE |
160 | default y | 161 | default y |
161 | ---help--- | 162 | ---help--- |
@@ -201,6 +202,7 @@ config IPV6_TUNNEL | |||
201 | config IPV6_GRE | 202 | config IPV6_GRE |
202 | tristate "IPv6: GRE tunnel" | 203 | tristate "IPv6: GRE tunnel" |
203 | select IPV6_TUNNEL | 204 | select IPV6_TUNNEL |
205 | select NET_IP_TUNNEL | ||
204 | ---help--- | 206 | ---help--- |
205 | Tunneling means encapsulating data of one protocol type within | 207 | Tunneling means encapsulating data of one protocol type within |
206 | another protocol and sending it over a channel that understands the | 208 | another protocol and sending it over a channel that understands the |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 309af19a0a0a..9af088d2cdaa 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -40,7 +40,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o | |||
40 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 40 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
41 | obj-$(CONFIG_IPV6_GRE) += ip6_gre.o | 41 | obj-$(CONFIG_IPV6_GRE) += ip6_gre.o |
42 | 42 | ||
43 | obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o | 43 | obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o |
44 | obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) | 44 | obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) |
45 | 45 | ||
46 | obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o | 46 | obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index dae802c0af7c..d1ab6ab29a55 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <net/snmp.h> | 70 | #include <net/snmp.h> |
71 | 71 | ||
72 | #include <net/af_ieee802154.h> | 72 | #include <net/af_ieee802154.h> |
73 | #include <net/firewire.h> | ||
73 | #include <net/ipv6.h> | 74 | #include <net/ipv6.h> |
74 | #include <net/protocol.h> | 75 | #include <net/protocol.h> |
75 | #include <net/ndisc.h> | 76 | #include <net/ndisc.h> |
@@ -419,6 +420,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
419 | ipv6_regen_rndid((unsigned long) ndev); | 420 | ipv6_regen_rndid((unsigned long) ndev); |
420 | } | 421 | } |
421 | #endif | 422 | #endif |
423 | ndev->token = in6addr_any; | ||
422 | 424 | ||
423 | if (netif_running(dev) && addrconf_qdisc_ok(dev)) | 425 | if (netif_running(dev) && addrconf_qdisc_ok(dev)) |
424 | ndev->if_flags |= IF_READY; | 426 | ndev->if_flags |= IF_READY; |
@@ -542,8 +544,7 @@ static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { | |||
542 | }; | 544 | }; |
543 | 545 | ||
544 | static int inet6_netconf_get_devconf(struct sk_buff *in_skb, | 546 | static int inet6_netconf_get_devconf(struct sk_buff *in_skb, |
545 | struct nlmsghdr *nlh, | 547 | struct nlmsghdr *nlh) |
546 | void *arg) | ||
547 | { | 548 | { |
548 | struct net *net = sock_net(in_skb->sk); | 549 | struct net *net = sock_net(in_skb->sk); |
549 | struct nlattr *tb[NETCONFA_MAX+1]; | 550 | struct nlattr *tb[NETCONFA_MAX+1]; |
@@ -603,6 +604,77 @@ errout: | |||
603 | return err; | 604 | return err; |
604 | } | 605 | } |
605 | 606 | ||
607 | static int inet6_netconf_dump_devconf(struct sk_buff *skb, | ||
608 | struct netlink_callback *cb) | ||
609 | { | ||
610 | struct net *net = sock_net(skb->sk); | ||
611 | int h, s_h; | ||
612 | int idx, s_idx; | ||
613 | struct net_device *dev; | ||
614 | struct inet6_dev *idev; | ||
615 | struct hlist_head *head; | ||
616 | |||
617 | s_h = cb->args[0]; | ||
618 | s_idx = idx = cb->args[1]; | ||
619 | |||
620 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||
621 | idx = 0; | ||
622 | head = &net->dev_index_head[h]; | ||
623 | rcu_read_lock(); | ||
624 | cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ | ||
625 | net->dev_base_seq; | ||
626 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | ||
627 | if (idx < s_idx) | ||
628 | goto cont; | ||
629 | idev = __in6_dev_get(dev); | ||
630 | if (!idev) | ||
631 | goto cont; | ||
632 | |||
633 | if (inet6_netconf_fill_devconf(skb, dev->ifindex, | ||
634 | &idev->cnf, | ||
635 | NETLINK_CB(cb->skb).portid, | ||
636 | cb->nlh->nlmsg_seq, | ||
637 | RTM_NEWNETCONF, | ||
638 | NLM_F_MULTI, | ||
639 | -1) <= 0) { | ||
640 | rcu_read_unlock(); | ||
641 | goto done; | ||
642 | } | ||
643 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
644 | cont: | ||
645 | idx++; | ||
646 | } | ||
647 | rcu_read_unlock(); | ||
648 | } | ||
649 | if (h == NETDEV_HASHENTRIES) { | ||
650 | if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL, | ||
651 | net->ipv6.devconf_all, | ||
652 | NETLINK_CB(cb->skb).portid, | ||
653 | cb->nlh->nlmsg_seq, | ||
654 | RTM_NEWNETCONF, NLM_F_MULTI, | ||
655 | -1) <= 0) | ||
656 | goto done; | ||
657 | else | ||
658 | h++; | ||
659 | } | ||
660 | if (h == NETDEV_HASHENTRIES + 1) { | ||
661 | if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT, | ||
662 | net->ipv6.devconf_dflt, | ||
663 | NETLINK_CB(cb->skb).portid, | ||
664 | cb->nlh->nlmsg_seq, | ||
665 | RTM_NEWNETCONF, NLM_F_MULTI, | ||
666 | -1) <= 0) | ||
667 | goto done; | ||
668 | else | ||
669 | h++; | ||
670 | } | ||
671 | done: | ||
672 | cb->args[0] = h; | ||
673 | cb->args[1] = idx; | ||
674 | |||
675 | return skb->len; | ||
676 | } | ||
677 | |||
606 | #ifdef CONFIG_SYSCTL | 678 | #ifdef CONFIG_SYSCTL |
607 | static void dev_forward_change(struct inet6_dev *idev) | 679 | static void dev_forward_change(struct inet6_dev *idev) |
608 | { | 680 | { |
@@ -804,6 +876,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
804 | ifa->prefix_len = pfxlen; | 876 | ifa->prefix_len = pfxlen; |
805 | ifa->flags = flags | IFA_F_TENTATIVE; | 877 | ifa->flags = flags | IFA_F_TENTATIVE; |
806 | ifa->cstamp = ifa->tstamp = jiffies; | 878 | ifa->cstamp = ifa->tstamp = jiffies; |
879 | ifa->tokenized = false; | ||
807 | 880 | ||
808 | ifa->rt = rt; | 881 | ifa->rt = rt; |
809 | 882 | ||
@@ -1666,6 +1739,20 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev) | |||
1666 | return 0; | 1739 | return 0; |
1667 | } | 1740 | } |
1668 | 1741 | ||
1742 | static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev) | ||
1743 | { | ||
1744 | union fwnet_hwaddr *ha; | ||
1745 | |||
1746 | if (dev->addr_len != FWNET_ALEN) | ||
1747 | return -1; | ||
1748 | |||
1749 | ha = (union fwnet_hwaddr *)dev->dev_addr; | ||
1750 | |||
1751 | memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id)); | ||
1752 | eui[0] ^= 2; | ||
1753 | return 0; | ||
1754 | } | ||
1755 | |||
1669 | static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) | 1756 | static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) |
1670 | { | 1757 | { |
1671 | /* XXX: inherit EUI-64 from other interface -- yoshfuji */ | 1758 | /* XXX: inherit EUI-64 from other interface -- yoshfuji */ |
@@ -1730,6 +1817,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
1730 | return addrconf_ifid_gre(eui, dev); | 1817 | return addrconf_ifid_gre(eui, dev); |
1731 | case ARPHRD_IEEE802154: | 1818 | case ARPHRD_IEEE802154: |
1732 | return addrconf_ifid_eui64(eui, dev); | 1819 | return addrconf_ifid_eui64(eui, dev); |
1820 | case ARPHRD_IEEE1394: | ||
1821 | return addrconf_ifid_ieee1394(eui, dev); | ||
1733 | } | 1822 | } |
1734 | return -1; | 1823 | return -1; |
1735 | } | 1824 | } |
@@ -2044,11 +2133,19 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) | |||
2044 | struct inet6_ifaddr *ifp; | 2133 | struct inet6_ifaddr *ifp; |
2045 | struct in6_addr addr; | 2134 | struct in6_addr addr; |
2046 | int create = 0, update_lft = 0; | 2135 | int create = 0, update_lft = 0; |
2136 | bool tokenized = false; | ||
2047 | 2137 | ||
2048 | if (pinfo->prefix_len == 64) { | 2138 | if (pinfo->prefix_len == 64) { |
2049 | memcpy(&addr, &pinfo->prefix, 8); | 2139 | memcpy(&addr, &pinfo->prefix, 8); |
2050 | if (ipv6_generate_eui64(addr.s6_addr + 8, dev) && | 2140 | |
2051 | ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) { | 2141 | if (!ipv6_addr_any(&in6_dev->token)) { |
2142 | read_lock_bh(&in6_dev->lock); | ||
2143 | memcpy(addr.s6_addr + 8, | ||
2144 | in6_dev->token.s6_addr + 8, 8); | ||
2145 | read_unlock_bh(&in6_dev->lock); | ||
2146 | tokenized = true; | ||
2147 | } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) && | ||
2148 | ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) { | ||
2052 | in6_dev_put(in6_dev); | 2149 | in6_dev_put(in6_dev); |
2053 | return; | 2150 | return; |
2054 | } | 2151 | } |
@@ -2089,6 +2186,7 @@ ok: | |||
2089 | 2186 | ||
2090 | update_lft = create = 1; | 2187 | update_lft = create = 1; |
2091 | ifp->cstamp = jiffies; | 2188 | ifp->cstamp = jiffies; |
2189 | ifp->tokenized = tokenized; | ||
2092 | addrconf_dad_start(ifp); | 2190 | addrconf_dad_start(ifp); |
2093 | } | 2191 | } |
2094 | 2192 | ||
@@ -2598,7 +2696,8 @@ static void addrconf_dev_config(struct net_device *dev) | |||
2598 | (dev->type != ARPHRD_FDDI) && | 2696 | (dev->type != ARPHRD_FDDI) && |
2599 | (dev->type != ARPHRD_ARCNET) && | 2697 | (dev->type != ARPHRD_ARCNET) && |
2600 | (dev->type != ARPHRD_INFINIBAND) && | 2698 | (dev->type != ARPHRD_INFINIBAND) && |
2601 | (dev->type != ARPHRD_IEEE802154)) { | 2699 | (dev->type != ARPHRD_IEEE802154) && |
2700 | (dev->type != ARPHRD_IEEE1394)) { | ||
2602 | /* Alas, we support only Ethernet autoconfiguration. */ | 2701 | /* Alas, we support only Ethernet autoconfiguration. */ |
2603 | return; | 2702 | return; |
2604 | } | 2703 | } |
@@ -3535,7 +3634,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = { | |||
3535 | }; | 3634 | }; |
3536 | 3635 | ||
3537 | static int | 3636 | static int |
3538 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3637 | inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) |
3539 | { | 3638 | { |
3540 | struct net *net = sock_net(skb->sk); | 3639 | struct net *net = sock_net(skb->sk); |
3541 | struct ifaddrmsg *ifm; | 3640 | struct ifaddrmsg *ifm; |
@@ -3601,7 +3700,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3601 | } | 3700 | } |
3602 | 3701 | ||
3603 | static int | 3702 | static int |
3604 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 3703 | inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) |
3605 | { | 3704 | { |
3606 | struct net *net = sock_net(skb->sk); | 3705 | struct net *net = sock_net(skb->sk); |
3607 | struct ifaddrmsg *ifm; | 3706 | struct ifaddrmsg *ifm; |
@@ -3832,6 +3931,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3832 | NLM_F_MULTI); | 3931 | NLM_F_MULTI); |
3833 | if (err <= 0) | 3932 | if (err <= 0) |
3834 | break; | 3933 | break; |
3934 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
3835 | } | 3935 | } |
3836 | break; | 3936 | break; |
3837 | } | 3937 | } |
@@ -3889,6 +3989,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3889 | s_ip_idx = ip_idx = cb->args[2]; | 3989 | s_ip_idx = ip_idx = cb->args[2]; |
3890 | 3990 | ||
3891 | rcu_read_lock(); | 3991 | rcu_read_lock(); |
3992 | cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ net->dev_base_seq; | ||
3892 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | 3993 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
3893 | idx = 0; | 3994 | idx = 0; |
3894 | head = &net->dev_index_head[h]; | 3995 | head = &net->dev_index_head[h]; |
@@ -3940,8 +4041,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
3940 | return inet6_dump_addr(skb, cb, type); | 4041 | return inet6_dump_addr(skb, cb, type); |
3941 | } | 4042 | } |
3942 | 4043 | ||
3943 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh, | 4044 | static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh) |
3944 | void *arg) | ||
3945 | { | 4045 | { |
3946 | struct net *net = sock_net(in_skb->sk); | 4046 | struct net *net = sock_net(in_skb->sk); |
3947 | struct ifaddrmsg *ifm; | 4047 | struct ifaddrmsg *ifm; |
@@ -4074,7 +4174,8 @@ static inline size_t inet6_ifla6_size(void) | |||
4074 | + nla_total_size(sizeof(struct ifla_cacheinfo)) | 4174 | + nla_total_size(sizeof(struct ifla_cacheinfo)) |
4075 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ | 4175 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ |
4076 | + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ | 4176 | + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ |
4077 | + nla_total_size(ICMP6_MIB_MAX * 8); /* IFLA_INET6_ICMP6STATS */ | 4177 | + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */ |
4178 | + nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */ | ||
4078 | } | 4179 | } |
4079 | 4180 | ||
4080 | static inline size_t inet6_if_nlmsg_size(void) | 4181 | static inline size_t inet6_if_nlmsg_size(void) |
@@ -4161,6 +4262,13 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) | |||
4161 | goto nla_put_failure; | 4262 | goto nla_put_failure; |
4162 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); | 4263 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); |
4163 | 4264 | ||
4265 | nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); | ||
4266 | if (nla == NULL) | ||
4267 | goto nla_put_failure; | ||
4268 | read_lock_bh(&idev->lock); | ||
4269 | memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla)); | ||
4270 | read_unlock_bh(&idev->lock); | ||
4271 | |||
4164 | return 0; | 4272 | return 0; |
4165 | 4273 | ||
4166 | nla_put_failure: | 4274 | nla_put_failure: |
@@ -4188,6 +4296,80 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | |||
4188 | return 0; | 4296 | return 0; |
4189 | } | 4297 | } |
4190 | 4298 | ||
4299 | static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | ||
4300 | { | ||
4301 | struct inet6_ifaddr *ifp; | ||
4302 | struct net_device *dev = idev->dev; | ||
4303 | bool update_rs = false; | ||
4304 | |||
4305 | if (token == NULL) | ||
4306 | return -EINVAL; | ||
4307 | if (ipv6_addr_any(token)) | ||
4308 | return -EINVAL; | ||
4309 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) | ||
4310 | return -EINVAL; | ||
4311 | if (!ipv6_accept_ra(idev)) | ||
4312 | return -EINVAL; | ||
4313 | if (idev->cnf.rtr_solicits <= 0) | ||
4314 | return -EINVAL; | ||
4315 | |||
4316 | write_lock_bh(&idev->lock); | ||
4317 | |||
4318 | BUILD_BUG_ON(sizeof(token->s6_addr) != 16); | ||
4319 | memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8); | ||
4320 | |||
4321 | write_unlock_bh(&idev->lock); | ||
4322 | |||
4323 | if (!idev->dead && (idev->if_flags & IF_READY)) { | ||
4324 | struct in6_addr ll_addr; | ||
4325 | |||
4326 | ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | | ||
4327 | IFA_F_OPTIMISTIC); | ||
4328 | |||
4329 | /* If we're not ready, then normal ifup will take care | ||
4330 | * of this. Otherwise, we need to request our rs here. | ||
4331 | */ | ||
4332 | ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters); | ||
4333 | update_rs = true; | ||
4334 | } | ||
4335 | |||
4336 | write_lock_bh(&idev->lock); | ||
4337 | |||
4338 | if (update_rs) | ||
4339 | idev->if_flags |= IF_RS_SENT; | ||
4340 | |||
4341 | /* Well, that's kinda nasty ... */ | ||
4342 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | ||
4343 | spin_lock(&ifp->lock); | ||
4344 | if (ifp->tokenized) { | ||
4345 | ifp->valid_lft = 0; | ||
4346 | ifp->prefered_lft = 0; | ||
4347 | } | ||
4348 | spin_unlock(&ifp->lock); | ||
4349 | } | ||
4350 | |||
4351 | write_unlock_bh(&idev->lock); | ||
4352 | return 0; | ||
4353 | } | ||
4354 | |||
4355 | static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) | ||
4356 | { | ||
4357 | int err = -EINVAL; | ||
4358 | struct inet6_dev *idev = __in6_dev_get(dev); | ||
4359 | struct nlattr *tb[IFLA_INET6_MAX + 1]; | ||
4360 | |||
4361 | if (!idev) | ||
4362 | return -EAFNOSUPPORT; | ||
4363 | |||
4364 | if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0) | ||
4365 | BUG(); | ||
4366 | |||
4367 | if (tb[IFLA_INET6_TOKEN]) | ||
4368 | err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); | ||
4369 | |||
4370 | return err; | ||
4371 | } | ||
4372 | |||
4191 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 4373 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
4192 | u32 portid, u32 seq, int event, unsigned int flags) | 4374 | u32 portid, u32 seq, int event, unsigned int flags) |
4193 | { | 4375 | { |
@@ -4366,6 +4548,8 @@ errout: | |||
4366 | 4548 | ||
4367 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4549 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
4368 | { | 4550 | { |
4551 | struct net *net = dev_net(ifp->idev->dev); | ||
4552 | |||
4369 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); | 4553 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); |
4370 | 4554 | ||
4371 | switch (event) { | 4555 | switch (event) { |
@@ -4391,6 +4575,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4391 | dst_free(&ifp->rt->dst); | 4575 | dst_free(&ifp->rt->dst); |
4392 | break; | 4576 | break; |
4393 | } | 4577 | } |
4578 | atomic_inc(&net->ipv6.dev_addr_genid); | ||
4394 | } | 4579 | } |
4395 | 4580 | ||
4396 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4581 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
@@ -4871,6 +5056,7 @@ static struct rtnl_af_ops inet6_ops = { | |||
4871 | .family = AF_INET6, | 5056 | .family = AF_INET6, |
4872 | .fill_link_af = inet6_fill_link_af, | 5057 | .fill_link_af = inet6_fill_link_af, |
4873 | .get_link_af_size = inet6_get_link_af_size, | 5058 | .get_link_af_size = inet6_get_link_af_size, |
5059 | .set_link_af = inet6_set_link_af, | ||
4874 | }; | 5060 | }; |
4875 | 5061 | ||
4876 | /* | 5062 | /* |
@@ -4943,7 +5129,7 @@ int __init addrconf_init(void) | |||
4943 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, | 5129 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, |
4944 | inet6_dump_ifacaddr, NULL); | 5130 | inet6_dump_ifacaddr, NULL); |
4945 | __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf, | 5131 | __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf, |
4946 | NULL, NULL); | 5132 | inet6_netconf_dump_devconf, NULL); |
4947 | 5133 | ||
4948 | ipv6_addr_label_rtnl_register(); | 5134 | ipv6_addr_label_rtnl_register(); |
4949 | 5135 | ||
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index aad64352cb60..f083a583a05c 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -414,8 +414,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = { | |||
414 | [IFAL_LABEL] = { .len = sizeof(u32), }, | 414 | [IFAL_LABEL] = { .len = sizeof(u32), }, |
415 | }; | 415 | }; |
416 | 416 | ||
417 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | 417 | static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh) |
418 | void *arg) | ||
419 | { | 418 | { |
420 | struct net *net = sock_net(skb->sk); | 419 | struct net *net = sock_net(skb->sk); |
421 | struct ifaddrlblmsg *ifal; | 420 | struct ifaddrlblmsg *ifal; |
@@ -436,10 +435,7 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
436 | 435 | ||
437 | if (!tb[IFAL_ADDRESS]) | 436 | if (!tb[IFAL_ADDRESS]) |
438 | return -EINVAL; | 437 | return -EINVAL; |
439 | |||
440 | pfx = nla_data(tb[IFAL_ADDRESS]); | 438 | pfx = nla_data(tb[IFAL_ADDRESS]); |
441 | if (!pfx) | ||
442 | return -EINVAL; | ||
443 | 439 | ||
444 | if (!tb[IFAL_LABEL]) | 440 | if (!tb[IFAL_LABEL]) |
445 | return -EINVAL; | 441 | return -EINVAL; |
@@ -533,8 +529,7 @@ static inline int ip6addrlbl_msgsize(void) | |||
533 | + nla_total_size(4); /* IFAL_LABEL */ | 529 | + nla_total_size(4); /* IFAL_LABEL */ |
534 | } | 530 | } |
535 | 531 | ||
536 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | 532 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh) |
537 | void *arg) | ||
538 | { | 533 | { |
539 | struct net *net = sock_net(in_skb->sk); | 534 | struct net *net = sock_net(in_skb->sk); |
540 | struct ifaddrlblmsg *ifal; | 535 | struct ifaddrlblmsg *ifal; |
@@ -561,10 +556,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
561 | 556 | ||
562 | if (!tb[IFAL_ADDRESS]) | 557 | if (!tb[IFAL_ADDRESS]) |
563 | return -EINVAL; | 558 | return -EINVAL; |
564 | |||
565 | addr = nla_data(tb[IFAL_ADDRESS]); | 559 | addr = nla_data(tb[IFAL_ADDRESS]); |
566 | if (!addr) | ||
567 | return -EINVAL; | ||
568 | 560 | ||
569 | rcu_read_lock(); | 561 | rcu_read_lock(); |
570 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); | 562 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 6b793bfc0e10..ab5c7ad482cd 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <net/udp.h> | 49 | #include <net/udp.h> |
50 | #include <net/udplite.h> | 50 | #include <net/udplite.h> |
51 | #include <net/tcp.h> | 51 | #include <net/tcp.h> |
52 | #include <net/ipip.h> | ||
53 | #include <net/protocol.h> | 52 | #include <net/protocol.h> |
54 | #include <net/inet_common.h> | 53 | #include <net/inet_common.h> |
55 | #include <net/route.h> | 54 | #include <net/route.h> |
@@ -323,7 +322,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
323 | struct net_device *dev = NULL; | 322 | struct net_device *dev = NULL; |
324 | 323 | ||
325 | rcu_read_lock(); | 324 | rcu_read_lock(); |
326 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 325 | if (__ipv6_addr_needs_scope_id(addr_type)) { |
327 | if (addr_len >= sizeof(struct sockaddr_in6) && | 326 | if (addr_len >= sizeof(struct sockaddr_in6) && |
328 | addr->sin6_scope_id) { | 327 | addr->sin6_scope_id) { |
329 | /* Override any existing binding, if another one | 328 | /* Override any existing binding, if another one |
@@ -471,8 +470,8 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
471 | 470 | ||
472 | sin->sin6_port = inet->inet_sport; | 471 | sin->sin6_port = inet->inet_sport; |
473 | } | 472 | } |
474 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 473 | sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr, |
475 | sin->sin6_scope_id = sk->sk_bound_dev_if; | 474 | sk->sk_bound_dev_if); |
476 | *uaddr_len = sizeof(*sin); | 475 | *uaddr_len = sizeof(*sin); |
477 | return 0; | 476 | return 0; |
478 | } | 477 | } |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index f5a54782a340..4b56cbbc7890 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -124,7 +124,7 @@ ipv4_connected: | |||
124 | goto out; | 124 | goto out; |
125 | } | 125 | } |
126 | 126 | ||
127 | if (addr_type&IPV6_ADDR_LINKLOCAL) { | 127 | if (__ipv6_addr_needs_scope_id(addr_type)) { |
128 | if (addr_len >= sizeof(struct sockaddr_in6) && | 128 | if (addr_len >= sizeof(struct sockaddr_in6) && |
129 | usin->sin6_scope_id) { | 129 | usin->sin6_scope_id) { |
130 | if (sk->sk_bound_dev_if && | 130 | if (sk->sk_bound_dev_if && |
@@ -355,18 +355,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
355 | sin->sin6_family = AF_INET6; | 355 | sin->sin6_family = AF_INET6; |
356 | sin->sin6_flowinfo = 0; | 356 | sin->sin6_flowinfo = 0; |
357 | sin->sin6_port = serr->port; | 357 | sin->sin6_port = serr->port; |
358 | sin->sin6_scope_id = 0; | ||
359 | if (skb->protocol == htons(ETH_P_IPV6)) { | 358 | if (skb->protocol == htons(ETH_P_IPV6)) { |
360 | const struct ipv6hdr *ip6h = container_of((struct in6_addr *)(nh + serr->addr_offset), | 359 | const struct ipv6hdr *ip6h = container_of((struct in6_addr *)(nh + serr->addr_offset), |
361 | struct ipv6hdr, daddr); | 360 | struct ipv6hdr, daddr); |
362 | sin->sin6_addr = ip6h->daddr; | 361 | sin->sin6_addr = ip6h->daddr; |
363 | if (np->sndflow) | 362 | if (np->sndflow) |
364 | sin->sin6_flowinfo = ip6_flowinfo(ip6h); | 363 | sin->sin6_flowinfo = ip6_flowinfo(ip6h); |
365 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 364 | sin->sin6_scope_id = |
366 | sin->sin6_scope_id = IP6CB(skb)->iif; | 365 | ipv6_iface_scope_id(&sin->sin6_addr, |
366 | IP6CB(skb)->iif); | ||
367 | } else { | 367 | } else { |
368 | ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), | 368 | ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), |
369 | &sin->sin6_addr); | 369 | &sin->sin6_addr); |
370 | sin->sin6_scope_id = 0; | ||
370 | } | 371 | } |
371 | } | 372 | } |
372 | 373 | ||
@@ -376,18 +377,19 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
376 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 377 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
377 | sin->sin6_family = AF_INET6; | 378 | sin->sin6_family = AF_INET6; |
378 | sin->sin6_flowinfo = 0; | 379 | sin->sin6_flowinfo = 0; |
379 | sin->sin6_scope_id = 0; | ||
380 | if (skb->protocol == htons(ETH_P_IPV6)) { | 380 | if (skb->protocol == htons(ETH_P_IPV6)) { |
381 | sin->sin6_addr = ipv6_hdr(skb)->saddr; | 381 | sin->sin6_addr = ipv6_hdr(skb)->saddr; |
382 | if (np->rxopt.all) | 382 | if (np->rxopt.all) |
383 | ip6_datagram_recv_ctl(sk, msg, skb); | 383 | ip6_datagram_recv_ctl(sk, msg, skb); |
384 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 384 | sin->sin6_scope_id = |
385 | sin->sin6_scope_id = IP6CB(skb)->iif; | 385 | ipv6_iface_scope_id(&sin->sin6_addr, |
386 | IP6CB(skb)->iif); | ||
386 | } else { | 387 | } else { |
387 | struct inet_sock *inet = inet_sk(sk); | 388 | struct inet_sock *inet = inet_sk(sk); |
388 | 389 | ||
389 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 390 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
390 | &sin->sin6_addr); | 391 | &sin->sin6_addr); |
392 | sin->sin6_scope_id = 0; | ||
391 | if (inet->cmsg_flags) | 393 | if (inet->cmsg_flags) |
392 | ip_cmsg_recv(msg, skb); | 394 | ip_cmsg_recv(msg, skb); |
393 | } | 395 | } |
@@ -592,7 +594,9 @@ int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, | |||
592 | sin6.sin6_addr = ipv6_hdr(skb)->daddr; | 594 | sin6.sin6_addr = ipv6_hdr(skb)->daddr; |
593 | sin6.sin6_port = ports[1]; | 595 | sin6.sin6_port = ports[1]; |
594 | sin6.sin6_flowinfo = 0; | 596 | sin6.sin6_flowinfo = 0; |
595 | sin6.sin6_scope_id = 0; | 597 | sin6.sin6_scope_id = |
598 | ipv6_iface_scope_id(&ipv6_hdr(skb)->daddr, | ||
599 | opt->iif); | ||
596 | 600 | ||
597 | put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6); | 601 | put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6); |
598 | } | 602 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index fff5bdd8b680..b4ff0a42b8c7 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -124,15 +124,6 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * Slightly more convenient version of icmpv6_send. | ||
128 | */ | ||
129 | void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) | ||
130 | { | ||
131 | icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos); | ||
132 | kfree_skb(skb); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Figure out, may we reply to this packet with icmp error. | 127 | * Figure out, may we reply to this packet with icmp error. |
137 | * | 128 | * |
138 | * We do not reply, if: | 129 | * We do not reply, if: |
@@ -332,7 +323,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *sk | |||
332 | * anycast. | 323 | * anycast. |
333 | */ | 324 | */ |
334 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | 325 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { |
335 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | 326 | LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: acast source\n"); |
336 | dst_release(dst); | 327 | dst_release(dst); |
337 | return ERR_PTR(-EINVAL); | 328 | return ERR_PTR(-EINVAL); |
338 | } | 329 | } |
@@ -381,7 +372,7 @@ relookup_failed: | |||
381 | /* | 372 | /* |
382 | * Send an ICMP message in response to a packet in error | 373 | * Send an ICMP message in response to a packet in error |
383 | */ | 374 | */ |
384 | void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | 375 | static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) |
385 | { | 376 | { |
386 | struct net *net = dev_net(skb->dev); | 377 | struct net *net = dev_net(skb->dev); |
387 | struct inet6_dev *idev = NULL; | 378 | struct inet6_dev *idev = NULL; |
@@ -406,7 +397,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
406 | /* | 397 | /* |
407 | * Make sure we respect the rules | 398 | * Make sure we respect the rules |
408 | * i.e. RFC 1885 2.4(e) | 399 | * i.e. RFC 1885 2.4(e) |
409 | * Rule (e.1) is enforced by not using icmpv6_send | 400 | * Rule (e.1) is enforced by not using icmp6_send |
410 | * in any code that processes icmp errors. | 401 | * in any code that processes icmp errors. |
411 | */ | 402 | */ |
412 | addr_type = ipv6_addr_type(&hdr->daddr); | 403 | addr_type = ipv6_addr_type(&hdr->daddr); |
@@ -434,7 +425,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
434 | * Source addr check | 425 | * Source addr check |
435 | */ | 426 | */ |
436 | 427 | ||
437 | if (addr_type & IPV6_ADDR_LINKLOCAL) | 428 | if (__ipv6_addr_needs_scope_id(addr_type)) |
438 | iif = skb->dev->ifindex; | 429 | iif = skb->dev->ifindex; |
439 | 430 | ||
440 | /* | 431 | /* |
@@ -444,7 +435,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
444 | * and anycast addresses will be checked later. | 435 | * and anycast addresses will be checked later. |
445 | */ | 436 | */ |
446 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { | 437 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { |
447 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); | 438 | LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: addr_any/mcast source\n"); |
448 | return; | 439 | return; |
449 | } | 440 | } |
450 | 441 | ||
@@ -452,7 +443,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
452 | * Never answer to a ICMP packet. | 443 | * Never answer to a ICMP packet. |
453 | */ | 444 | */ |
454 | if (is_ineligible(skb)) { | 445 | if (is_ineligible(skb)) { |
455 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n"); | 446 | LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: no reply to icmp error\n"); |
456 | return; | 447 | return; |
457 | } | 448 | } |
458 | 449 | ||
@@ -529,7 +520,14 @@ out_dst_release: | |||
529 | out: | 520 | out: |
530 | icmpv6_xmit_unlock(sk); | 521 | icmpv6_xmit_unlock(sk); |
531 | } | 522 | } |
532 | EXPORT_SYMBOL(icmpv6_send); | 523 | |
524 | /* Slightly more convenient version of icmp6_send. | ||
525 | */ | ||
526 | void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) | ||
527 | { | ||
528 | icmp6_send(skb, ICMPV6_PARAMPROB, code, pos); | ||
529 | kfree_skb(skb); | ||
530 | } | ||
533 | 531 | ||
534 | static void icmpv6_echo_reply(struct sk_buff *skb) | 532 | static void icmpv6_echo_reply(struct sk_buff *skb) |
535 | { | 533 | { |
@@ -701,7 +699,7 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
701 | if (__skb_checksum_complete(skb)) { | 699 | if (__skb_checksum_complete(skb)) { |
702 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", | 700 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", |
703 | saddr, daddr); | 701 | saddr, daddr); |
704 | goto discard_it; | 702 | goto csum_error; |
705 | } | 703 | } |
706 | } | 704 | } |
707 | 705 | ||
@@ -787,6 +785,8 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
787 | kfree_skb(skb); | 785 | kfree_skb(skb); |
788 | return 0; | 786 | return 0; |
789 | 787 | ||
788 | csum_error: | ||
789 | ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS); | ||
790 | discard_it: | 790 | discard_it: |
791 | ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS); | 791 | ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS); |
792 | drop_no_count: | 792 | drop_no_count: |
@@ -885,8 +885,14 @@ int __init icmpv6_init(void) | |||
885 | err = -EAGAIN; | 885 | err = -EAGAIN; |
886 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) | 886 | if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) |
887 | goto fail; | 887 | goto fail; |
888 | |||
889 | err = inet6_register_icmp_sender(icmp6_send); | ||
890 | if (err) | ||
891 | goto sender_reg_err; | ||
888 | return 0; | 892 | return 0; |
889 | 893 | ||
894 | sender_reg_err: | ||
895 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | ||
890 | fail: | 896 | fail: |
891 | pr_err("Failed to register ICMP6 protocol\n"); | 897 | pr_err("Failed to register ICMP6 protocol\n"); |
892 | unregister_pernet_subsys(&icmpv6_sk_ops); | 898 | unregister_pernet_subsys(&icmpv6_sk_ops); |
@@ -895,6 +901,7 @@ fail: | |||
895 | 901 | ||
896 | void icmpv6_cleanup(void) | 902 | void icmpv6_cleanup(void) |
897 | { | 903 | { |
904 | inet6_unregister_icmp_sender(icmp6_send); | ||
898 | unregister_pernet_subsys(&icmpv6_sk_ops); | 905 | unregister_pernet_subsys(&icmpv6_sk_ops); |
899 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); | 906 | inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); |
900 | } | 907 | } |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 9bfab19ff3c0..e4311cbc8b4e 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -54,6 +54,10 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
54 | if (ipv6_rcv_saddr_equal(sk, sk2)) | 54 | if (ipv6_rcv_saddr_equal(sk, sk2)) |
55 | break; | 55 | break; |
56 | } | 56 | } |
57 | if (!relax && reuse && sk2->sk_reuse && | ||
58 | sk2->sk_state != TCP_LISTEN && | ||
59 | ipv6_rcv_saddr_equal(sk, sk2)) | ||
60 | break; | ||
57 | } | 61 | } |
58 | } | 62 | } |
59 | 63 | ||
@@ -169,10 +173,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) | |||
169 | sin6->sin6_port = inet_sk(sk)->inet_dport; | 173 | sin6->sin6_port = inet_sk(sk)->inet_dport; |
170 | /* We do not store received flowlabel for TCP */ | 174 | /* We do not store received flowlabel for TCP */ |
171 | sin6->sin6_flowinfo = 0; | 175 | sin6->sin6_flowinfo = 0; |
172 | sin6->sin6_scope_id = 0; | 176 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, |
173 | if (sk->sk_bound_dev_if && | 177 | sk->sk_bound_dev_if); |
174 | ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | ||
175 | sin6->sin6_scope_id = sk->sk_bound_dev_if; | ||
176 | } | 178 | } |
177 | 179 | ||
178 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); | 180 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index b973ed3d06cf..46e88433ec7d 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -144,7 +144,9 @@ static void ip6_fl_gc(unsigned long dummy) | |||
144 | spin_lock(&ip6_fl_lock); | 144 | spin_lock(&ip6_fl_lock); |
145 | 145 | ||
146 | for (i=0; i<=FL_HASH_MASK; i++) { | 146 | for (i=0; i<=FL_HASH_MASK; i++) { |
147 | struct ip6_flowlabel *fl, **flp; | 147 | struct ip6_flowlabel *fl; |
148 | struct ip6_flowlabel __rcu **flp; | ||
149 | |||
148 | flp = &fl_ht[i]; | 150 | flp = &fl_ht[i]; |
149 | while ((fl = rcu_dereference_protected(*flp, | 151 | while ((fl = rcu_dereference_protected(*flp, |
150 | lockdep_is_held(&ip6_fl_lock))) != NULL) { | 152 | lockdep_is_held(&ip6_fl_lock))) != NULL) { |
@@ -179,7 +181,9 @@ static void __net_exit ip6_fl_purge(struct net *net) | |||
179 | 181 | ||
180 | spin_lock(&ip6_fl_lock); | 182 | spin_lock(&ip6_fl_lock); |
181 | for (i = 0; i <= FL_HASH_MASK; i++) { | 183 | for (i = 0; i <= FL_HASH_MASK; i++) { |
182 | struct ip6_flowlabel *fl, **flp; | 184 | struct ip6_flowlabel *fl; |
185 | struct ip6_flowlabel __rcu **flp; | ||
186 | |||
183 | flp = &fl_ht[i]; | 187 | flp = &fl_ht[i]; |
184 | while ((fl = rcu_dereference_protected(*flp, | 188 | while ((fl = rcu_dereference_protected(*flp, |
185 | lockdep_is_held(&ip6_fl_lock))) != NULL) { | 189 | lockdep_is_held(&ip6_fl_lock))) != NULL) { |
@@ -506,7 +510,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
506 | struct ipv6_pinfo *np = inet6_sk(sk); | 510 | struct ipv6_pinfo *np = inet6_sk(sk); |
507 | struct in6_flowlabel_req freq; | 511 | struct in6_flowlabel_req freq; |
508 | struct ipv6_fl_socklist *sfl1=NULL; | 512 | struct ipv6_fl_socklist *sfl1=NULL; |
509 | struct ipv6_fl_socklist *sfl, **sflp; | 513 | struct ipv6_fl_socklist *sfl; |
514 | struct ipv6_fl_socklist __rcu **sflp; | ||
510 | struct ip6_flowlabel *fl, *fl1 = NULL; | 515 | struct ip6_flowlabel *fl, *fl1 = NULL; |
511 | 516 | ||
512 | 517 | ||
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index e4efffe2522e..d3ddd8400354 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -38,6 +38,7 @@ | |||
38 | 38 | ||
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | #include <net/ip.h> | 40 | #include <net/ip.h> |
41 | #include <net/ip_tunnels.h> | ||
41 | #include <net/icmp.h> | 42 | #include <net/icmp.h> |
42 | #include <net/protocol.h> | 43 | #include <net/protocol.h> |
43 | #include <net/addrconf.h> | 44 | #include <net/addrconf.h> |
@@ -110,46 +111,6 @@ static u32 HASH_ADDR(const struct in6_addr *addr) | |||
110 | #define tunnels_l tunnels[1] | 111 | #define tunnels_l tunnels[1] |
111 | #define tunnels_wc tunnels[0] | 112 | #define tunnels_wc tunnels[0] |
112 | 113 | ||
113 | static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev, | ||
114 | struct rtnl_link_stats64 *tot) | ||
115 | { | ||
116 | int i; | ||
117 | |||
118 | for_each_possible_cpu(i) { | ||
119 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | ||
120 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
121 | unsigned int start; | ||
122 | |||
123 | do { | ||
124 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
125 | rx_packets = tstats->rx_packets; | ||
126 | tx_packets = tstats->tx_packets; | ||
127 | rx_bytes = tstats->rx_bytes; | ||
128 | tx_bytes = tstats->tx_bytes; | ||
129 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
130 | |||
131 | tot->rx_packets += rx_packets; | ||
132 | tot->tx_packets += tx_packets; | ||
133 | tot->rx_bytes += rx_bytes; | ||
134 | tot->tx_bytes += tx_bytes; | ||
135 | } | ||
136 | |||
137 | tot->multicast = dev->stats.multicast; | ||
138 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
139 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
140 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
141 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
142 | tot->rx_errors = dev->stats.rx_errors; | ||
143 | |||
144 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
145 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
146 | tot->tx_dropped = dev->stats.tx_dropped; | ||
147 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
148 | tot->tx_errors = dev->stats.tx_errors; | ||
149 | |||
150 | return tot; | ||
151 | } | ||
152 | |||
153 | /* Given src, dst and key, find appropriate for input tunnel. */ | 114 | /* Given src, dst and key, find appropriate for input tunnel. */ |
154 | 115 | ||
155 | static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, | 116 | static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, |
@@ -667,7 +628,6 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
667 | struct net_device_stats *stats = &tunnel->dev->stats; | 628 | struct net_device_stats *stats = &tunnel->dev->stats; |
668 | int err = -1; | 629 | int err = -1; |
669 | u8 proto; | 630 | u8 proto; |
670 | int pkt_len; | ||
671 | struct sk_buff *new_skb; | 631 | struct sk_buff *new_skb; |
672 | 632 | ||
673 | if (dev->type == ARPHRD_ETHER) | 633 | if (dev->type == ARPHRD_ETHER) |
@@ -801,23 +761,9 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
801 | } | 761 | } |
802 | } | 762 | } |
803 | 763 | ||
804 | nf_reset(skb); | 764 | ip6tunnel_xmit(skb, dev); |
805 | pkt_len = skb->len; | ||
806 | err = ip6_local_out(skb); | ||
807 | |||
808 | if (net_xmit_eval(err) == 0) { | ||
809 | struct pcpu_tstats *tstats = this_cpu_ptr(tunnel->dev->tstats); | ||
810 | |||
811 | tstats->tx_bytes += pkt_len; | ||
812 | tstats->tx_packets++; | ||
813 | } else { | ||
814 | stats->tx_errors++; | ||
815 | stats->tx_aborted_errors++; | ||
816 | } | ||
817 | |||
818 | if (ndst) | 765 | if (ndst) |
819 | ip6_tnl_dst_store(tunnel, ndst); | 766 | ip6_tnl_dst_store(tunnel, ndst); |
820 | |||
821 | return 0; | 767 | return 0; |
822 | tx_err_link_failure: | 768 | tx_err_link_failure: |
823 | stats->tx_carrier_errors++; | 769 | stats->tx_carrier_errors++; |
@@ -1271,7 +1217,7 @@ static const struct net_device_ops ip6gre_netdev_ops = { | |||
1271 | .ndo_start_xmit = ip6gre_tunnel_xmit, | 1217 | .ndo_start_xmit = ip6gre_tunnel_xmit, |
1272 | .ndo_do_ioctl = ip6gre_tunnel_ioctl, | 1218 | .ndo_do_ioctl = ip6gre_tunnel_ioctl, |
1273 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, | 1219 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, |
1274 | .ndo_get_stats64 = ip6gre_get_stats64, | 1220 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1275 | }; | 1221 | }; |
1276 | 1222 | ||
1277 | static void ip6gre_dev_free(struct net_device *dev) | 1223 | static void ip6gre_dev_free(struct net_device *dev) |
@@ -1520,7 +1466,7 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = { | |||
1520 | .ndo_set_mac_address = eth_mac_addr, | 1466 | .ndo_set_mac_address = eth_mac_addr, |
1521 | .ndo_validate_addr = eth_validate_addr, | 1467 | .ndo_validate_addr = eth_validate_addr, |
1522 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, | 1468 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, |
1523 | .ndo_get_stats64 = ip6gre_get_stats64, | 1469 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1524 | }; | 1470 | }; |
1525 | 1471 | ||
1526 | static void ip6gre_tap_setup(struct net_device *dev) | 1472 | static void ip6gre_tap_setup(struct net_device *dev) |
diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c new file mode 100644 index 000000000000..4578e23834f7 --- /dev/null +++ b/net/ipv6/ip6_icmp.c | |||
@@ -0,0 +1,47 @@ | |||
1 | #include <linux/export.h> | ||
2 | #include <linux/icmpv6.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | |||
7 | #include <net/ipv6.h> | ||
8 | |||
9 | #if IS_ENABLED(CONFIG_IPV6) | ||
10 | |||
11 | static ip6_icmp_send_t __rcu *ip6_icmp_send; | ||
12 | |||
13 | int inet6_register_icmp_sender(ip6_icmp_send_t *fn) | ||
14 | { | ||
15 | return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ? | ||
16 | 0 : -EBUSY; | ||
17 | } | ||
18 | EXPORT_SYMBOL(inet6_register_icmp_sender); | ||
19 | |||
20 | int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) | ||
21 | { | ||
22 | int ret; | ||
23 | |||
24 | ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ? | ||
25 | 0 : -EINVAL; | ||
26 | |||
27 | synchronize_net(); | ||
28 | |||
29 | return ret; | ||
30 | } | ||
31 | EXPORT_SYMBOL(inet6_unregister_icmp_sender); | ||
32 | |||
33 | void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | ||
34 | { | ||
35 | ip6_icmp_send_t *send; | ||
36 | |||
37 | rcu_read_lock(); | ||
38 | send = rcu_dereference(ip6_icmp_send); | ||
39 | |||
40 | if (!send) | ||
41 | goto out; | ||
42 | send(skb, type, code, info); | ||
43 | out: | ||
44 | rcu_read_unlock(); | ||
45 | } | ||
46 | EXPORT_SYMBOL(icmpv6_send); | ||
47 | #endif | ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 8234c1dcdf72..71b766ee821d 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -92,14 +92,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
92 | u8 *prevhdr; | 92 | u8 *prevhdr; |
93 | int offset = 0; | 93 | int offset = 0; |
94 | 94 | ||
95 | if (!(features & NETIF_F_V6_CSUM)) | ||
96 | features &= ~NETIF_F_SG; | ||
97 | |||
98 | if (unlikely(skb_shinfo(skb)->gso_type & | 95 | if (unlikely(skb_shinfo(skb)->gso_type & |
99 | ~(SKB_GSO_UDP | | 96 | ~(SKB_GSO_UDP | |
100 | SKB_GSO_DODGY | | 97 | SKB_GSO_DODGY | |
101 | SKB_GSO_TCP_ECN | | 98 | SKB_GSO_TCP_ECN | |
102 | SKB_GSO_GRE | | 99 | SKB_GSO_GRE | |
100 | SKB_GSO_UDP_TUNNEL | | ||
103 | SKB_GSO_TCPV6 | | 101 | SKB_GSO_TCPV6 | |
104 | 0))) | 102 | 0))) |
105 | goto out; | 103 | goto out; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 155eccfa7760..d2eedf192330 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1224,11 +1224,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | /* For UDP, check if TX timestamp is enabled */ | 1226 | /* For UDP, check if TX timestamp is enabled */ |
1227 | if (sk->sk_type == SOCK_DGRAM) { | 1227 | if (sk->sk_type == SOCK_DGRAM) |
1228 | err = sock_tx_timestamp(sk, &tx_flags); | 1228 | sock_tx_timestamp(sk, &tx_flags); |
1229 | if (err) | ||
1230 | goto error; | ||
1231 | } | ||
1232 | 1229 | ||
1233 | /* | 1230 | /* |
1234 | * Let's try using as much space as possible. | 1231 | * Let's try using as much space as possible. |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fff83cbc197f..1e55866cead7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -47,6 +47,7 @@ | |||
47 | 47 | ||
48 | #include <net/icmp.h> | 48 | #include <net/icmp.h> |
49 | #include <net/ip.h> | 49 | #include <net/ip.h> |
50 | #include <net/ip_tunnels.h> | ||
50 | #include <net/ipv6.h> | 51 | #include <net/ipv6.h> |
51 | #include <net/ip6_route.h> | 52 | #include <net/ip6_route.h> |
52 | #include <net/addrconf.h> | 53 | #include <net/addrconf.h> |
@@ -955,7 +956,6 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
955 | unsigned int max_headroom = sizeof(struct ipv6hdr); | 956 | unsigned int max_headroom = sizeof(struct ipv6hdr); |
956 | u8 proto; | 957 | u8 proto; |
957 | int err = -1; | 958 | int err = -1; |
958 | int pkt_len; | ||
959 | 959 | ||
960 | if (!fl6->flowi6_mark) | 960 | if (!fl6->flowi6_mark) |
961 | dst = ip6_tnl_dst_check(t); | 961 | dst = ip6_tnl_dst_check(t); |
@@ -1035,19 +1035,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
1035 | ipv6h->nexthdr = proto; | 1035 | ipv6h->nexthdr = proto; |
1036 | ipv6h->saddr = fl6->saddr; | 1036 | ipv6h->saddr = fl6->saddr; |
1037 | ipv6h->daddr = fl6->daddr; | 1037 | ipv6h->daddr = fl6->daddr; |
1038 | nf_reset(skb); | 1038 | ip6tunnel_xmit(skb, dev); |
1039 | pkt_len = skb->len; | ||
1040 | err = ip6_local_out(skb); | ||
1041 | |||
1042 | if (net_xmit_eval(err) == 0) { | ||
1043 | struct pcpu_tstats *tstats = this_cpu_ptr(t->dev->tstats); | ||
1044 | |||
1045 | tstats->tx_bytes += pkt_len; | ||
1046 | tstats->tx_packets++; | ||
1047 | } else { | ||
1048 | stats->tx_errors++; | ||
1049 | stats->tx_aborted_errors++; | ||
1050 | } | ||
1051 | if (ndst) | 1039 | if (ndst) |
1052 | ip6_tnl_dst_store(t, ndst); | 1040 | ip6_tnl_dst_store(t, ndst); |
1053 | return 0; | 1041 | return 0; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 96bfb4e4b820..241fb8ad9fcf 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -842,9 +842,9 @@ static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c) | |||
842 | if (ipv6_hdr(skb)->version == 0) { | 842 | if (ipv6_hdr(skb)->version == 0) { |
843 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 843 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
844 | nlh->nlmsg_type = NLMSG_ERROR; | 844 | nlh->nlmsg_type = NLMSG_ERROR; |
845 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | 845 | nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); |
846 | skb_trim(skb, nlh->nlmsg_len); | 846 | skb_trim(skb, nlh->nlmsg_len); |
847 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT; | 847 | ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT; |
848 | rtnl_unicast(skb, net, NETLINK_CB(skb).portid); | 848 | rtnl_unicast(skb, net, NETLINK_CB(skb).portid); |
849 | } else | 849 | } else |
850 | kfree_skb(skb); | 850 | kfree_skb(skb); |
@@ -1100,13 +1100,13 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1100 | if (ipv6_hdr(skb)->version == 0) { | 1100 | if (ipv6_hdr(skb)->version == 0) { |
1101 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1101 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
1102 | 1102 | ||
1103 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 1103 | if (__ip6mr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) { |
1104 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; | 1104 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; |
1105 | } else { | 1105 | } else { |
1106 | nlh->nlmsg_type = NLMSG_ERROR; | 1106 | nlh->nlmsg_type = NLMSG_ERROR; |
1107 | nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr)); | 1107 | nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr)); |
1108 | skb_trim(skb, nlh->nlmsg_len); | 1108 | skb_trim(skb, nlh->nlmsg_len); |
1109 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1109 | ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE; |
1110 | } | 1110 | } |
1111 | rtnl_unicast(skb, net, NETLINK_CB(skb).portid); | 1111 | rtnl_unicast(skb, net, NETLINK_CB(skb).portid); |
1112 | } else | 1112 | } else |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 76ef4353d518..2712ab22a174 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -610,8 +610,6 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, | |||
610 | } | 610 | } |
611 | } | 611 | } |
612 | #endif | 612 | #endif |
613 | if (!dev->addr_len) | ||
614 | send_sllao = 0; | ||
615 | if (send_sllao) | 613 | if (send_sllao) |
616 | optlen += ndisc_opt_addr_space(dev); | 614 | optlen += ndisc_opt_addr_space(dev); |
617 | 615 | ||
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 429089cb073d..72836f40b730 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * IPv6 specific functions of netfilter core | ||
3 | * | ||
4 | * Rusty Russell (C) 2000 -- This code is GPL. | ||
5 | * Patrick McHardy (C) 2006-2012 | ||
6 | */ | ||
1 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
2 | #include <linux/init.h> | 8 | #include <linux/init.h> |
3 | #include <linux/ipv6.h> | 9 | #include <linux/ipv6.h> |
@@ -29,7 +35,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
29 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 35 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
30 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 36 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
31 | dst_release(dst); | 37 | dst_release(dst); |
32 | return -EINVAL; | 38 | return dst->error; |
33 | } | 39 | } |
34 | 40 | ||
35 | /* Drop old route. */ | 41 | /* Drop old route. */ |
@@ -43,7 +49,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
43 | skb_dst_set(skb, NULL); | 49 | skb_dst_set(skb, NULL); |
44 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), skb->sk, 0); | 50 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), skb->sk, 0); |
45 | if (IS_ERR(dst)) | 51 | if (IS_ERR(dst)) |
46 | return -1; | 52 | return PTR_ERR(dst); |
47 | skb_dst_set(skb, dst); | 53 | skb_dst_set(skb, dst); |
48 | } | 54 | } |
49 | #endif | 55 | #endif |
@@ -53,7 +59,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
53 | if (skb_headroom(skb) < hh_len && | 59 | if (skb_headroom(skb) < hh_len && |
54 | pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)), | 60 | pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)), |
55 | 0, GFP_ATOMIC)) | 61 | 0, GFP_ATOMIC)) |
56 | return -1; | 62 | return -ENOMEM; |
57 | 63 | ||
58 | return 0; | 64 | return 0; |
59 | } | 65 | } |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index c72532a60d88..4433ab40e7de 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -105,7 +105,7 @@ config IP6_NF_MATCH_MH | |||
105 | 105 | ||
106 | config IP6_NF_MATCH_RPFILTER | 106 | config IP6_NF_MATCH_RPFILTER |
107 | tristate '"rpfilter" reverse path filter match support' | 107 | tristate '"rpfilter" reverse path filter match support' |
108 | depends on NETFILTER_ADVANCED | 108 | depends on NETFILTER_ADVANCED && (IP6_NF_MANGLE || IP6_NF_RAW) |
109 | ---help--- | 109 | ---help--- |
110 | This option allows you to match packets whose replies would | 110 | This option allows you to match packets whose replies would |
111 | go out via the interface the packet came in. | 111 | go out via the interface the packet came in. |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 341b54ade72c..44400c216dc6 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | 4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling |
5 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> | 5 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> |
6 | * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -284,6 +285,7 @@ static void trace_packet(const struct sk_buff *skb, | |||
284 | const char *hookname, *chainname, *comment; | 285 | const char *hookname, *chainname, *comment; |
285 | const struct ip6t_entry *iter; | 286 | const struct ip6t_entry *iter; |
286 | unsigned int rulenum = 0; | 287 | unsigned int rulenum = 0; |
288 | struct net *net = dev_net(in ? in : out); | ||
287 | 289 | ||
288 | table_base = private->entries[smp_processor_id()]; | 290 | table_base = private->entries[smp_processor_id()]; |
289 | root = get_entry(table_base, private->hook_entry[hook]); | 291 | root = get_entry(table_base, private->hook_entry[hook]); |
@@ -296,7 +298,7 @@ static void trace_packet(const struct sk_buff *skb, | |||
296 | &chainname, &comment, &rulenum) != 0) | 298 | &chainname, &comment, &rulenum) != 0) |
297 | break; | 299 | break; |
298 | 300 | ||
299 | nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, | 301 | nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo, |
300 | "TRACE: %s:%s:%s:%u ", | 302 | "TRACE: %s:%s:%s:%u ", |
301 | tablename, chainname, comment, rulenum); | 303 | tablename, chainname, comment, rulenum); |
302 | } | 304 | } |
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index cb631143721c..590f767db5d4 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
@@ -18,9 +18,8 @@ | |||
18 | static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) | 18 | static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) |
19 | { | 19 | { |
20 | struct ip6t_npt_tginfo *npt = par->targinfo; | 20 | struct ip6t_npt_tginfo *npt = par->targinfo; |
21 | __wsum src_sum = 0, dst_sum = 0; | ||
22 | struct in6_addr pfx; | 21 | struct in6_addr pfx; |
23 | unsigned int i; | 22 | __wsum src_sum, dst_sum; |
24 | 23 | ||
25 | if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) | 24 | if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) |
26 | return -EINVAL; | 25 | return -EINVAL; |
@@ -33,12 +32,8 @@ static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) | |||
33 | if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6)) | 32 | if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6)) |
34 | return -EINVAL; | 33 | return -EINVAL; |
35 | 34 | ||
36 | for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) { | 35 | src_sum = csum_partial(&npt->src_pfx.in6, sizeof(npt->src_pfx.in6), 0); |
37 | src_sum = csum_add(src_sum, | 36 | dst_sum = csum_partial(&npt->dst_pfx.in6, sizeof(npt->dst_pfx.in6), 0); |
38 | (__force __wsum)npt->src_pfx.in6.s6_addr16[i]); | ||
39 | dst_sum = csum_add(dst_sum, | ||
40 | (__force __wsum)npt->dst_pfx.in6.s6_addr16[i]); | ||
41 | } | ||
42 | 37 | ||
43 | npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum)); | 38 | npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum)); |
44 | return 0; | 39 | return 0; |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index ed3b427b2841..70f9abc0efe9 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * Authors: | 7 | * Authors: |
8 | * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> | 8 | * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> |
9 | * | 9 | * |
10 | * Copyright (c) 2005-2007 Patrick McHardy <kaber@trash.net> | ||
11 | * | ||
10 | * Based on net/ipv4/netfilter/ipt_REJECT.c | 12 | * Based on net/ipv4/netfilter/ipt_REJECT.c |
11 | * | 13 | * |
12 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 6134a1ebfb1b..e075399d8b72 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -38,7 +38,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) | |||
38 | struct in6_addr saddr, daddr; | 38 | struct in6_addr saddr, daddr; |
39 | u_int8_t hop_limit; | 39 | u_int8_t hop_limit; |
40 | u_int32_t flowlabel, mark; | 40 | u_int32_t flowlabel, mark; |
41 | 41 | int err; | |
42 | #if 0 | 42 | #if 0 |
43 | /* root is playing with raw sockets. */ | 43 | /* root is playing with raw sockets. */ |
44 | if (skb->len < sizeof(struct iphdr) || | 44 | if (skb->len < sizeof(struct iphdr) || |
@@ -65,8 +65,11 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) | |||
65 | !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || | 65 | !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || |
66 | skb->mark != mark || | 66 | skb->mark != mark || |
67 | ipv6_hdr(skb)->hop_limit != hop_limit || | 67 | ipv6_hdr(skb)->hop_limit != hop_limit || |
68 | flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) | 68 | flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { |
69 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; | 69 | err = ip6_route_me_harder(skb); |
70 | if (err < 0) | ||
71 | ret = NF_DROP_ERR(err); | ||
72 | } | ||
70 | 73 | ||
71 | return ret; | 74 | return ret; |
72 | } | 75 | } |
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e0e788d25b14..6383f90efda8 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c | |||
@@ -179,6 +179,7 @@ nf_nat_ipv6_out(unsigned int hooknum, | |||
179 | #ifdef CONFIG_XFRM | 179 | #ifdef CONFIG_XFRM |
180 | const struct nf_conn *ct; | 180 | const struct nf_conn *ct; |
181 | enum ip_conntrack_info ctinfo; | 181 | enum ip_conntrack_info ctinfo; |
182 | int err; | ||
182 | #endif | 183 | #endif |
183 | unsigned int ret; | 184 | unsigned int ret; |
184 | 185 | ||
@@ -197,9 +198,11 @@ nf_nat_ipv6_out(unsigned int hooknum, | |||
197 | &ct->tuplehash[!dir].tuple.dst.u3) || | 198 | &ct->tuplehash[!dir].tuple.dst.u3) || |
198 | (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && | 199 | (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && |
199 | ct->tuplehash[dir].tuple.src.u.all != | 200 | ct->tuplehash[dir].tuple.src.u.all != |
200 | ct->tuplehash[!dir].tuple.dst.u.all)) | 201 | ct->tuplehash[!dir].tuple.dst.u.all)) { |
201 | if (nf_xfrm_me_harder(skb, AF_INET6) < 0) | 202 | err = nf_xfrm_me_harder(skb, AF_INET6); |
202 | ret = NF_DROP; | 203 | if (err < 0) |
204 | ret = NF_DROP_ERR(err); | ||
205 | } | ||
203 | } | 206 | } |
204 | #endif | 207 | #endif |
205 | return ret; | 208 | return ret; |
@@ -215,6 +218,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum, | |||
215 | const struct nf_conn *ct; | 218 | const struct nf_conn *ct; |
216 | enum ip_conntrack_info ctinfo; | 219 | enum ip_conntrack_info ctinfo; |
217 | unsigned int ret; | 220 | unsigned int ret; |
221 | int err; | ||
218 | 222 | ||
219 | /* root is playing with raw sockets. */ | 223 | /* root is playing with raw sockets. */ |
220 | if (skb->len < sizeof(struct ipv6hdr)) | 224 | if (skb->len < sizeof(struct ipv6hdr)) |
@@ -227,16 +231,19 @@ nf_nat_ipv6_local_fn(unsigned int hooknum, | |||
227 | 231 | ||
228 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, | 232 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, |
229 | &ct->tuplehash[!dir].tuple.src.u3)) { | 233 | &ct->tuplehash[!dir].tuple.src.u3)) { |
230 | if (ip6_route_me_harder(skb)) | 234 | err = ip6_route_me_harder(skb); |
231 | ret = NF_DROP; | 235 | if (err < 0) |
236 | ret = NF_DROP_ERR(err); | ||
232 | } | 237 | } |
233 | #ifdef CONFIG_XFRM | 238 | #ifdef CONFIG_XFRM |
234 | else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 239 | else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
235 | ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && | 240 | ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && |
236 | ct->tuplehash[dir].tuple.dst.u.all != | 241 | ct->tuplehash[dir].tuple.dst.u.all != |
237 | ct->tuplehash[!dir].tuple.src.u.all) | 242 | ct->tuplehash[!dir].tuple.src.u.all) { |
238 | if (nf_xfrm_me_harder(skb, AF_INET6)) | 243 | err = nf_xfrm_me_harder(skb, AF_INET6); |
239 | ret = NF_DROP; | 244 | if (err < 0) |
245 | ret = NF_DROP_ERR(err); | ||
246 | } | ||
240 | #endif | 247 | #endif |
241 | } | 248 | } |
242 | return ret; | 249 | return ret; |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 2b6c226f5198..97bcf2bae857 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -330,12 +330,8 @@ ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
330 | sizeof(sin6.sin6_addr)); | 330 | sizeof(sin6.sin6_addr)); |
331 | 331 | ||
332 | nf_ct_put(ct); | 332 | nf_ct_put(ct); |
333 | 333 | sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, | |
334 | if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | 334 | sk->sk_bound_dev_if); |
335 | sin6.sin6_scope_id = sk->sk_bound_dev_if; | ||
336 | else | ||
337 | sin6.sin6_scope_id = 0; | ||
338 | |||
339 | return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; | 335 | return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0; |
340 | } | 336 | } |
341 | 337 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 24df3dde0076..b3807c5cb888 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -131,7 +131,8 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
131 | type + 128); | 131 | type + 128); |
132 | nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); | 132 | nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); |
133 | if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) | 133 | if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) |
134 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 134 | nf_log_packet(nf_ct_net(ct), PF_INET6, 0, skb, NULL, |
135 | NULL, NULL, | ||
135 | "nf_ct_icmpv6: invalid new with type %d ", | 136 | "nf_ct_icmpv6: invalid new with type %d ", |
136 | type + 128); | 137 | type + 128); |
137 | return false; | 138 | return false; |
@@ -203,7 +204,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, | |||
203 | icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); | 204 | icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); |
204 | if (icmp6h == NULL) { | 205 | if (icmp6h == NULL) { |
205 | if (LOG_INVALID(net, IPPROTO_ICMPV6)) | 206 | if (LOG_INVALID(net, IPPROTO_ICMPV6)) |
206 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 207 | nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, |
207 | "nf_ct_icmpv6: short packet "); | 208 | "nf_ct_icmpv6: short packet "); |
208 | return -NF_ACCEPT; | 209 | return -NF_ACCEPT; |
209 | } | 210 | } |
@@ -211,7 +212,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, | |||
211 | if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | 212 | if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && |
212 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { | 213 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { |
213 | if (LOG_INVALID(net, IPPROTO_ICMPV6)) | 214 | if (LOG_INVALID(net, IPPROTO_ICMPV6)) |
214 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 215 | nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, |
215 | "nf_ct_icmpv6: ICMPv6 checksum failed "); | 216 | "nf_ct_icmpv6: ICMPv6 checksum failed "); |
216 | return -NF_ACCEPT; | 217 | return -NF_ACCEPT; |
217 | } | 218 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6700069949dd..dffdc1a389c5 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <net/rawv6.h> | 41 | #include <net/rawv6.h> |
42 | #include <net/ndisc.h> | 42 | #include <net/ndisc.h> |
43 | #include <net/addrconf.h> | 43 | #include <net/addrconf.h> |
44 | #include <net/inet_ecn.h> | ||
44 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 45 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
45 | #include <linux/sysctl.h> | 46 | #include <linux/sysctl.h> |
46 | #include <linux/netfilter.h> | 47 | #include <linux/netfilter.h> |
@@ -138,6 +139,11 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) | |||
138 | } | 139 | } |
139 | #endif | 140 | #endif |
140 | 141 | ||
142 | static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h) | ||
143 | { | ||
144 | return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK); | ||
145 | } | ||
146 | |||
141 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 147 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
142 | { | 148 | { |
143 | const struct frag_queue *nq; | 149 | const struct frag_queue *nq; |
@@ -166,7 +172,7 @@ static void nf_ct_frag6_expire(unsigned long data) | |||
166 | /* Creation primitives. */ | 172 | /* Creation primitives. */ |
167 | static inline struct frag_queue *fq_find(struct net *net, __be32 id, | 173 | static inline struct frag_queue *fq_find(struct net *net, __be32 id, |
168 | u32 user, struct in6_addr *src, | 174 | u32 user, struct in6_addr *src, |
169 | struct in6_addr *dst) | 175 | struct in6_addr *dst, u8 ecn) |
170 | { | 176 | { |
171 | struct inet_frag_queue *q; | 177 | struct inet_frag_queue *q; |
172 | struct ip6_create_arg arg; | 178 | struct ip6_create_arg arg; |
@@ -176,6 +182,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |||
176 | arg.user = user; | 182 | arg.user = user; |
177 | arg.src = src; | 183 | arg.src = src; |
178 | arg.dst = dst; | 184 | arg.dst = dst; |
185 | arg.ecn = ecn; | ||
179 | 186 | ||
180 | read_lock_bh(&nf_frags.lock); | 187 | read_lock_bh(&nf_frags.lock); |
181 | hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); | 188 | hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); |
@@ -196,6 +203,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
196 | struct sk_buff *prev, *next; | 203 | struct sk_buff *prev, *next; |
197 | unsigned int payload_len; | 204 | unsigned int payload_len; |
198 | int offset, end; | 205 | int offset, end; |
206 | u8 ecn; | ||
199 | 207 | ||
200 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 208 | if (fq->q.last_in & INET_FRAG_COMPLETE) { |
201 | pr_debug("Already completed\n"); | 209 | pr_debug("Already completed\n"); |
@@ -213,6 +221,8 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
213 | return -1; | 221 | return -1; |
214 | } | 222 | } |
215 | 223 | ||
224 | ecn = ip6_frag_ecn(ipv6_hdr(skb)); | ||
225 | |||
216 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 226 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
217 | const unsigned char *nh = skb_network_header(skb); | 227 | const unsigned char *nh = skb_network_header(skb); |
218 | skb->csum = csum_sub(skb->csum, | 228 | skb->csum = csum_sub(skb->csum, |
@@ -317,6 +327,7 @@ found: | |||
317 | } | 327 | } |
318 | fq->q.stamp = skb->tstamp; | 328 | fq->q.stamp = skb->tstamp; |
319 | fq->q.meat += skb->len; | 329 | fq->q.meat += skb->len; |
330 | fq->ecn |= ecn; | ||
320 | if (payload_len > fq->q.max_size) | 331 | if (payload_len > fq->q.max_size) |
321 | fq->q.max_size = payload_len; | 332 | fq->q.max_size = payload_len; |
322 | add_frag_mem_limit(&fq->q, skb->truesize); | 333 | add_frag_mem_limit(&fq->q, skb->truesize); |
@@ -352,12 +363,17 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
352 | { | 363 | { |
353 | struct sk_buff *fp, *op, *head = fq->q.fragments; | 364 | struct sk_buff *fp, *op, *head = fq->q.fragments; |
354 | int payload_len; | 365 | int payload_len; |
366 | u8 ecn; | ||
355 | 367 | ||
356 | inet_frag_kill(&fq->q, &nf_frags); | 368 | inet_frag_kill(&fq->q, &nf_frags); |
357 | 369 | ||
358 | WARN_ON(head == NULL); | 370 | WARN_ON(head == NULL); |
359 | WARN_ON(NFCT_FRAG6_CB(head)->offset != 0); | 371 | WARN_ON(NFCT_FRAG6_CB(head)->offset != 0); |
360 | 372 | ||
373 | ecn = ip_frag_ecn_table[fq->ecn]; | ||
374 | if (unlikely(ecn == 0xff)) | ||
375 | goto out_fail; | ||
376 | |||
361 | /* Unfragmented part is taken from the first segment. */ | 377 | /* Unfragmented part is taken from the first segment. */ |
362 | payload_len = ((head->data - skb_network_header(head)) - | 378 | payload_len = ((head->data - skb_network_header(head)) - |
363 | sizeof(struct ipv6hdr) + fq->q.len - | 379 | sizeof(struct ipv6hdr) + fq->q.len - |
@@ -428,6 +444,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) | |||
428 | head->dev = dev; | 444 | head->dev = dev; |
429 | head->tstamp = fq->q.stamp; | 445 | head->tstamp = fq->q.stamp; |
430 | ipv6_hdr(head)->payload_len = htons(payload_len); | 446 | ipv6_hdr(head)->payload_len = htons(payload_len); |
447 | ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn); | ||
431 | IP6CB(head)->frag_max_size = sizeof(struct ipv6hdr) + fq->q.max_size; | 448 | IP6CB(head)->frag_max_size = sizeof(struct ipv6hdr) + fq->q.max_size; |
432 | 449 | ||
433 | /* Yes, and fold redundant checksum back. 8) */ | 450 | /* Yes, and fold redundant checksum back. 8) */ |
@@ -572,7 +589,8 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
572 | inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false); | 589 | inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false); |
573 | local_bh_enable(); | 590 | local_bh_enable(); |
574 | 591 | ||
575 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr); | 592 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, |
593 | ip6_frag_ecn(hdr)); | ||
576 | if (fq == NULL) { | 594 | if (fq == NULL) { |
577 | pr_debug("Can't find and can't create new queue\n"); | 595 | pr_debug("Can't find and can't create new queue\n"); |
578 | goto ret_orig; | 596 | goto ret_orig; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index bbbe53a99b57..f3c1ff4357ff 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -90,6 +90,7 @@ static const struct snmp_mib snmp6_ipstats_list[] = { | |||
90 | SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), | 90 | SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), |
91 | SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), | 91 | SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), |
92 | SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), | 92 | SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), |
93 | SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS), | ||
93 | SNMP_MIB_SENTINEL | 94 | SNMP_MIB_SENTINEL |
94 | }; | 95 | }; |
95 | 96 | ||
@@ -99,6 +100,7 @@ static const struct snmp_mib snmp6_icmp6_list[] = { | |||
99 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), | 100 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), |
100 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), | 101 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), |
101 | SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), | 102 | SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), |
103 | SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS), | ||
102 | SNMP_MIB_SENTINEL | 104 | SNMP_MIB_SENTINEL |
103 | }; | 105 | }; |
104 | 106 | ||
@@ -129,6 +131,7 @@ static const struct snmp_mib snmp6_udp6_list[] = { | |||
129 | SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS), | 131 | SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS), |
130 | SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), | 132 | SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), |
131 | SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), | 133 | SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), |
134 | SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), | ||
132 | SNMP_MIB_SENTINEL | 135 | SNMP_MIB_SENTINEL |
133 | }; | 136 | }; |
134 | 137 | ||
@@ -139,6 +142,7 @@ static const struct snmp_mib snmp6_udplite6_list[] = { | |||
139 | SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), | 142 | SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), |
140 | SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS), | 143 | SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS), |
141 | SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS), | 144 | SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS), |
145 | SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS), | ||
142 | SNMP_MIB_SENTINEL | 146 | SNMP_MIB_SENTINEL |
143 | }; | 147 | }; |
144 | 148 | ||
@@ -247,7 +251,7 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v) | |||
247 | 251 | ||
248 | static int snmp6_dev_seq_open(struct inode *inode, struct file *file) | 252 | static int snmp6_dev_seq_open(struct inode *inode, struct file *file) |
249 | { | 253 | { |
250 | return single_open(file, snmp6_dev_seq_show, PDE(inode)->data); | 254 | return single_open(file, snmp6_dev_seq_show, PDE_DATA(inode)); |
251 | } | 255 | } |
252 | 256 | ||
253 | static const struct file_operations snmp6_dev_seq_fops = { | 257 | static const struct file_operations snmp6_dev_seq_fops = { |
@@ -287,8 +291,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) | |||
287 | return -ENOENT; | 291 | return -ENOENT; |
288 | if (!idev->stats.proc_dir_entry) | 292 | if (!idev->stats.proc_dir_entry) |
289 | return -EINVAL; | 293 | return -EINVAL; |
290 | remove_proc_entry(idev->stats.proc_dir_entry->name, | 294 | proc_remove(idev->stats.proc_dir_entry); |
291 | net->mib.proc_net_devsnmp6); | ||
292 | idev->stats.proc_dir_entry = NULL; | 295 | idev->stats.proc_dir_entry = NULL; |
293 | return 0; | 296 | return 0; |
294 | } | 297 | } |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 330b5e7b7df6..eedff8ccded5 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -263,7 +263,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
263 | if (addr_type != IPV6_ADDR_ANY) { | 263 | if (addr_type != IPV6_ADDR_ANY) { |
264 | struct net_device *dev = NULL; | 264 | struct net_device *dev = NULL; |
265 | 265 | ||
266 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 266 | if (__ipv6_addr_needs_scope_id(addr_type)) { |
267 | if (addr_len >= sizeof(struct sockaddr_in6) && | 267 | if (addr_len >= sizeof(struct sockaddr_in6) && |
268 | addr->sin6_scope_id) { | 268 | addr->sin6_scope_id) { |
269 | /* Override any existing binding, if another | 269 | /* Override any existing binding, if another |
@@ -498,9 +498,8 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
498 | sin6->sin6_port = 0; | 498 | sin6->sin6_port = 0; |
499 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 499 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
500 | sin6->sin6_flowinfo = 0; | 500 | sin6->sin6_flowinfo = 0; |
501 | sin6->sin6_scope_id = 0; | 501 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, |
502 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 502 | IP6CB(skb)->iif); |
503 | sin6->sin6_scope_id = IP6CB(skb)->iif; | ||
504 | } | 503 | } |
505 | 504 | ||
506 | sock_recv_ts_and_drops(msg, sk, skb); | 505 | sock_recv_ts_and_drops(msg, sk, skb); |
@@ -802,7 +801,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
802 | 801 | ||
803 | if (addr_len >= sizeof(struct sockaddr_in6) && | 802 | if (addr_len >= sizeof(struct sockaddr_in6) && |
804 | sin6->sin6_scope_id && | 803 | sin6->sin6_scope_id && |
805 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 804 | __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr))) |
806 | fl6.flowi6_oif = sin6->sin6_scope_id; | 805 | fl6.flowi6_oif = sin6->sin6_scope_id; |
807 | } else { | 806 | } else { |
808 | if (sk->sk_state != TCP_ESTABLISHED) | 807 | if (sk->sk_state != TCP_ESTABLISHED) |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 0ba10e53a629..790d9f4b8b0b 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <net/ndisc.h> | 58 | #include <net/ndisc.h> |
59 | #include <net/addrconf.h> | 59 | #include <net/addrconf.h> |
60 | #include <net/inet_frag.h> | 60 | #include <net/inet_frag.h> |
61 | #include <net/inet_ecn.h> | ||
61 | 62 | ||
62 | struct ip6frag_skb_cb | 63 | struct ip6frag_skb_cb |
63 | { | 64 | { |
@@ -67,6 +68,10 @@ struct ip6frag_skb_cb | |||
67 | 68 | ||
68 | #define FRAG6_CB(skb) ((struct ip6frag_skb_cb*)((skb)->cb)) | 69 | #define FRAG6_CB(skb) ((struct ip6frag_skb_cb*)((skb)->cb)) |
69 | 70 | ||
71 | static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h) | ||
72 | { | ||
73 | return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK); | ||
74 | } | ||
70 | 75 | ||
71 | static struct inet_frags ip6_frags; | 76 | static struct inet_frags ip6_frags; |
72 | 77 | ||
@@ -119,6 +124,7 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a) | |||
119 | fq->user = arg->user; | 124 | fq->user = arg->user; |
120 | fq->saddr = *arg->src; | 125 | fq->saddr = *arg->src; |
121 | fq->daddr = *arg->dst; | 126 | fq->daddr = *arg->dst; |
127 | fq->ecn = arg->ecn; | ||
122 | } | 128 | } |
123 | EXPORT_SYMBOL(ip6_frag_init); | 129 | EXPORT_SYMBOL(ip6_frag_init); |
124 | 130 | ||
@@ -173,7 +179,8 @@ static void ip6_frag_expire(unsigned long data) | |||
173 | } | 179 | } |
174 | 180 | ||
175 | static __inline__ struct frag_queue * | 181 | static __inline__ struct frag_queue * |
176 | fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6_addr *dst) | 182 | fq_find(struct net *net, __be32 id, const struct in6_addr *src, |
183 | const struct in6_addr *dst, u8 ecn) | ||
177 | { | 184 | { |
178 | struct inet_frag_queue *q; | 185 | struct inet_frag_queue *q; |
179 | struct ip6_create_arg arg; | 186 | struct ip6_create_arg arg; |
@@ -183,6 +190,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6 | |||
183 | arg.user = IP6_DEFRAG_LOCAL_DELIVER; | 190 | arg.user = IP6_DEFRAG_LOCAL_DELIVER; |
184 | arg.src = src; | 191 | arg.src = src; |
185 | arg.dst = dst; | 192 | arg.dst = dst; |
193 | arg.ecn = ecn; | ||
186 | 194 | ||
187 | read_lock(&ip6_frags.lock); | 195 | read_lock(&ip6_frags.lock); |
188 | hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); | 196 | hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); |
@@ -202,6 +210,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
202 | struct net_device *dev; | 210 | struct net_device *dev; |
203 | int offset, end; | 211 | int offset, end; |
204 | struct net *net = dev_net(skb_dst(skb)->dev); | 212 | struct net *net = dev_net(skb_dst(skb)->dev); |
213 | u8 ecn; | ||
205 | 214 | ||
206 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 215 | if (fq->q.last_in & INET_FRAG_COMPLETE) |
207 | goto err; | 216 | goto err; |
@@ -219,6 +228,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
219 | return -1; | 228 | return -1; |
220 | } | 229 | } |
221 | 230 | ||
231 | ecn = ip6_frag_ecn(ipv6_hdr(skb)); | ||
232 | |||
222 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 233 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
223 | const unsigned char *nh = skb_network_header(skb); | 234 | const unsigned char *nh = skb_network_header(skb); |
224 | skb->csum = csum_sub(skb->csum, | 235 | skb->csum = csum_sub(skb->csum, |
@@ -319,6 +330,7 @@ found: | |||
319 | } | 330 | } |
320 | fq->q.stamp = skb->tstamp; | 331 | fq->q.stamp = skb->tstamp; |
321 | fq->q.meat += skb->len; | 332 | fq->q.meat += skb->len; |
333 | fq->ecn |= ecn; | ||
322 | add_frag_mem_limit(&fq->q, skb->truesize); | 334 | add_frag_mem_limit(&fq->q, skb->truesize); |
323 | 335 | ||
324 | /* The first fragment. | 336 | /* The first fragment. |
@@ -370,9 +382,14 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
370 | int payload_len; | 382 | int payload_len; |
371 | unsigned int nhoff; | 383 | unsigned int nhoff; |
372 | int sum_truesize; | 384 | int sum_truesize; |
385 | u8 ecn; | ||
373 | 386 | ||
374 | inet_frag_kill(&fq->q, &ip6_frags); | 387 | inet_frag_kill(&fq->q, &ip6_frags); |
375 | 388 | ||
389 | ecn = ip_frag_ecn_table[fq->ecn]; | ||
390 | if (unlikely(ecn == 0xff)) | ||
391 | goto out_fail; | ||
392 | |||
376 | /* Make the one we just received the head. */ | 393 | /* Make the one we just received the head. */ |
377 | if (prev) { | 394 | if (prev) { |
378 | head = prev->next; | 395 | head = prev->next; |
@@ -471,6 +488,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
471 | head->dev = dev; | 488 | head->dev = dev; |
472 | head->tstamp = fq->q.stamp; | 489 | head->tstamp = fq->q.stamp; |
473 | ipv6_hdr(head)->payload_len = htons(payload_len); | 490 | ipv6_hdr(head)->payload_len = htons(payload_len); |
491 | ipv6_change_dsfield(ipv6_hdr(head), 0xff, ecn); | ||
474 | IP6CB(head)->nhoff = nhoff; | 492 | IP6CB(head)->nhoff = nhoff; |
475 | 493 | ||
476 | /* Yes, and fold redundant checksum back. 8) */ | 494 | /* Yes, and fold redundant checksum back. 8) */ |
@@ -534,7 +552,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
534 | IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), | 552 | IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), |
535 | IPSTATS_MIB_REASMFAILS, evicted); | 553 | IPSTATS_MIB_REASMFAILS, evicted); |
536 | 554 | ||
537 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr); | 555 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, |
556 | ip6_frag_ecn(hdr)); | ||
538 | if (fq != NULL) { | 557 | if (fq != NULL) { |
539 | int ret; | 558 | int ret; |
540 | 559 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e5fe0041adfa..ad0aa6b0b86a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2355,7 +2355,7 @@ beginning: | |||
2355 | return last_err; | 2355 | return last_err; |
2356 | } | 2356 | } |
2357 | 2357 | ||
2358 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2358 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh) |
2359 | { | 2359 | { |
2360 | struct fib6_config cfg; | 2360 | struct fib6_config cfg; |
2361 | int err; | 2361 | int err; |
@@ -2370,7 +2370,7 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a | |||
2370 | return ip6_route_del(&cfg); | 2370 | return ip6_route_del(&cfg); |
2371 | } | 2371 | } |
2372 | 2372 | ||
2373 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2373 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh) |
2374 | { | 2374 | { |
2375 | struct fib6_config cfg; | 2375 | struct fib6_config cfg; |
2376 | int err; | 2376 | int err; |
@@ -2562,7 +2562,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2562 | prefix, 0, NLM_F_MULTI); | 2562 | prefix, 0, NLM_F_MULTI); |
2563 | } | 2563 | } |
2564 | 2564 | ||
2565 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | 2565 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh) |
2566 | { | 2566 | { |
2567 | struct net *net = sock_net(in_skb->sk); | 2567 | struct net *net = sock_net(in_skb->sk); |
2568 | struct nlattr *tb[RTA_MAX+1]; | 2568 | struct nlattr *tb[RTA_MAX+1]; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 02f96dcbcf02..335363478bbf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include <net/ip.h> | 49 | #include <net/ip.h> |
50 | #include <net/udp.h> | 50 | #include <net/udp.h> |
51 | #include <net/icmp.h> | 51 | #include <net/icmp.h> |
52 | #include <net/ipip.h> | 52 | #include <net/ip_tunnels.h> |
53 | #include <net/inet_ecn.h> | 53 | #include <net/inet_ecn.h> |
54 | #include <net/xfrm.h> | 54 | #include <net/xfrm.h> |
55 | #include <net/dsfield.h> | 55 | #include <net/dsfield.h> |
@@ -87,41 +87,6 @@ struct sit_net { | |||
87 | struct net_device *fb_tunnel_dev; | 87 | struct net_device *fb_tunnel_dev; |
88 | }; | 88 | }; |
89 | 89 | ||
90 | static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev, | ||
91 | struct rtnl_link_stats64 *tot) | ||
92 | { | ||
93 | int i; | ||
94 | |||
95 | for_each_possible_cpu(i) { | ||
96 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | ||
97 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
98 | unsigned int start; | ||
99 | |||
100 | do { | ||
101 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
102 | rx_packets = tstats->rx_packets; | ||
103 | tx_packets = tstats->tx_packets; | ||
104 | rx_bytes = tstats->rx_bytes; | ||
105 | tx_bytes = tstats->tx_bytes; | ||
106 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
107 | |||
108 | tot->rx_packets += rx_packets; | ||
109 | tot->tx_packets += tx_packets; | ||
110 | tot->rx_bytes += rx_bytes; | ||
111 | tot->tx_bytes += tx_bytes; | ||
112 | } | ||
113 | |||
114 | tot->rx_errors = dev->stats.rx_errors; | ||
115 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
116 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
117 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
118 | tot->tx_dropped = dev->stats.tx_dropped; | ||
119 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
120 | tot->tx_errors = dev->stats.tx_errors; | ||
121 | |||
122 | return tot; | ||
123 | } | ||
124 | |||
125 | /* | 90 | /* |
126 | * Must be invoked with rcu_read_lock | 91 | * Must be invoked with rcu_read_lock |
127 | */ | 92 | */ |
@@ -899,6 +864,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
899 | if ((iph->ttl = tiph->ttl) == 0) | 864 | if ((iph->ttl = tiph->ttl) == 0) |
900 | iph->ttl = iph6->hop_limit; | 865 | iph->ttl = iph6->hop_limit; |
901 | 866 | ||
867 | skb->ip_summed = CHECKSUM_NONE; | ||
868 | ip_select_ident(iph, skb_dst(skb), NULL); | ||
902 | iptunnel_xmit(skb, dev); | 869 | iptunnel_xmit(skb, dev); |
903 | return NETDEV_TX_OK; | 870 | return NETDEV_TX_OK; |
904 | 871 | ||
@@ -1200,7 +1167,7 @@ static const struct net_device_ops ipip6_netdev_ops = { | |||
1200 | .ndo_start_xmit = ipip6_tunnel_xmit, | 1167 | .ndo_start_xmit = ipip6_tunnel_xmit, |
1201 | .ndo_do_ioctl = ipip6_tunnel_ioctl, | 1168 | .ndo_do_ioctl = ipip6_tunnel_ioctl, |
1202 | .ndo_change_mtu = ipip6_tunnel_change_mtu, | 1169 | .ndo_change_mtu = ipip6_tunnel_change_mtu, |
1203 | .ndo_get_stats64= ipip6_get_stats64, | 1170 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1204 | }; | 1171 | }; |
1205 | 1172 | ||
1206 | static void ipip6_dev_free(struct net_device *dev) | 1173 | static void ipip6_dev_free(struct net_device *dev) |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 8a0848b60b35..d5dda20bd717 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -149,7 +149,6 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie) | |||
149 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 149 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) |
150 | { | 150 | { |
151 | struct tcp_options_received tcp_opt; | 151 | struct tcp_options_received tcp_opt; |
152 | const u8 *hash_location; | ||
153 | struct inet_request_sock *ireq; | 152 | struct inet_request_sock *ireq; |
154 | struct inet6_request_sock *ireq6; | 153 | struct inet6_request_sock *ireq6; |
155 | struct tcp_request_sock *treq; | 154 | struct tcp_request_sock *treq; |
@@ -177,7 +176,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
177 | 176 | ||
178 | /* check for timestamp cookie support */ | 177 | /* check for timestamp cookie support */ |
179 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 178 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
180 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL); | 179 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
181 | 180 | ||
182 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) | 181 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) |
183 | goto out; | 182 | goto out; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 46a5be85be87..71167069b394 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -462,7 +462,6 @@ out: | |||
462 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | 462 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, |
463 | struct flowi6 *fl6, | 463 | struct flowi6 *fl6, |
464 | struct request_sock *req, | 464 | struct request_sock *req, |
465 | struct request_values *rvp, | ||
466 | u16 queue_mapping) | 465 | u16 queue_mapping) |
467 | { | 466 | { |
468 | struct inet6_request_sock *treq = inet6_rsk(req); | 467 | struct inet6_request_sock *treq = inet6_rsk(req); |
@@ -474,7 +473,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | |||
474 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) | 473 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) |
475 | goto done; | 474 | goto done; |
476 | 475 | ||
477 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); | 476 | skb = tcp_make_synack(sk, dst, req, NULL); |
478 | 477 | ||
479 | if (skb) { | 478 | if (skb) { |
480 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 479 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
@@ -489,13 +488,12 @@ done: | |||
489 | return err; | 488 | return err; |
490 | } | 489 | } |
491 | 490 | ||
492 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | 491 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req) |
493 | struct request_values *rvp) | ||
494 | { | 492 | { |
495 | struct flowi6 fl6; | 493 | struct flowi6 fl6; |
496 | int res; | 494 | int res; |
497 | 495 | ||
498 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0); | 496 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0); |
499 | if (!res) | 497 | if (!res) |
500 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | 498 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
501 | return res; | 499 | return res; |
@@ -948,9 +946,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
948 | */ | 946 | */ |
949 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 947 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
950 | { | 948 | { |
951 | struct tcp_extend_values tmp_ext; | ||
952 | struct tcp_options_received tmp_opt; | 949 | struct tcp_options_received tmp_opt; |
953 | const u8 *hash_location; | ||
954 | struct request_sock *req; | 950 | struct request_sock *req; |
955 | struct inet6_request_sock *treq; | 951 | struct inet6_request_sock *treq; |
956 | struct ipv6_pinfo *np = inet6_sk(sk); | 952 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -988,50 +984,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
988 | tcp_clear_options(&tmp_opt); | 984 | tcp_clear_options(&tmp_opt); |
989 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 985 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
990 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 986 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
991 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 987 | tcp_parse_options(skb, &tmp_opt, 0, NULL); |
992 | |||
993 | if (tmp_opt.cookie_plus > 0 && | ||
994 | tmp_opt.saw_tstamp && | ||
995 | !tp->rx_opt.cookie_out_never && | ||
996 | (sysctl_tcp_cookie_size > 0 || | ||
997 | (tp->cookie_values != NULL && | ||
998 | tp->cookie_values->cookie_desired > 0))) { | ||
999 | u8 *c; | ||
1000 | u32 *d; | ||
1001 | u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
1002 | int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE; | ||
1003 | |||
1004 | if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0) | ||
1005 | goto drop_and_free; | ||
1006 | |||
1007 | /* Secret recipe starts with IP addresses */ | ||
1008 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; | ||
1009 | *mess++ ^= *d++; | ||
1010 | *mess++ ^= *d++; | ||
1011 | *mess++ ^= *d++; | ||
1012 | *mess++ ^= *d++; | ||
1013 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; | ||
1014 | *mess++ ^= *d++; | ||
1015 | *mess++ ^= *d++; | ||
1016 | *mess++ ^= *d++; | ||
1017 | *mess++ ^= *d++; | ||
1018 | |||
1019 | /* plus variable length Initiator Cookie */ | ||
1020 | c = (u8 *)mess; | ||
1021 | while (l-- > 0) | ||
1022 | *c++ ^= *hash_location++; | ||
1023 | |||
1024 | want_cookie = false; /* not our kind of cookie */ | ||
1025 | tmp_ext.cookie_out_never = 0; /* false */ | ||
1026 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | ||
1027 | } else if (!tp->rx_opt.cookie_in_always) { | ||
1028 | /* redundant indications, but ensure initialization. */ | ||
1029 | tmp_ext.cookie_out_never = 1; /* true */ | ||
1030 | tmp_ext.cookie_plus = 0; | ||
1031 | } else { | ||
1032 | goto drop_and_free; | ||
1033 | } | ||
1034 | tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always; | ||
1035 | 988 | ||
1036 | if (want_cookie && !tmp_opt.saw_tstamp) | 989 | if (want_cookie && !tmp_opt.saw_tstamp) |
1037 | tcp_clear_options(&tmp_opt); | 990 | tcp_clear_options(&tmp_opt); |
@@ -1109,7 +1062,6 @@ have_isn: | |||
1109 | goto drop_and_release; | 1062 | goto drop_and_release; |
1110 | 1063 | ||
1111 | if (tcp_v6_send_synack(sk, dst, &fl6, req, | 1064 | if (tcp_v6_send_synack(sk, dst, &fl6, req, |
1112 | (struct request_values *)&tmp_ext, | ||
1113 | skb_get_queue_mapping(skb)) || | 1065 | skb_get_queue_mapping(skb)) || |
1114 | want_cookie) | 1066 | want_cookie) |
1115 | goto drop_and_free; | 1067 | goto drop_and_free; |
@@ -1453,6 +1405,7 @@ discard: | |||
1453 | kfree_skb(skb); | 1405 | kfree_skb(skb); |
1454 | return 0; | 1406 | return 0; |
1455 | csum_err: | 1407 | csum_err: |
1408 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS); | ||
1456 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | 1409 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); |
1457 | goto discard; | 1410 | goto discard; |
1458 | 1411 | ||
@@ -1514,7 +1467,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1514 | goto discard_it; | 1467 | goto discard_it; |
1515 | 1468 | ||
1516 | if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb)) | 1469 | if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb)) |
1517 | goto bad_packet; | 1470 | goto csum_error; |
1518 | 1471 | ||
1519 | th = tcp_hdr(skb); | 1472 | th = tcp_hdr(skb); |
1520 | hdr = ipv6_hdr(skb); | 1473 | hdr = ipv6_hdr(skb); |
@@ -1578,6 +1531,8 @@ no_tcp_socket: | |||
1578 | goto discard_it; | 1531 | goto discard_it; |
1579 | 1532 | ||
1580 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1533 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1534 | csum_error: | ||
1535 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); | ||
1581 | bad_packet: | 1536 | bad_packet: |
1582 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); | 1537 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); |
1583 | } else { | 1538 | } else { |
@@ -1585,11 +1540,6 @@ bad_packet: | |||
1585 | } | 1540 | } |
1586 | 1541 | ||
1587 | discard_it: | 1542 | discard_it: |
1588 | |||
1589 | /* | ||
1590 | * Discard frame | ||
1591 | */ | ||
1592 | |||
1593 | kfree_skb(skb); | 1543 | kfree_skb(skb); |
1594 | return 0; | 1544 | return 0; |
1595 | 1545 | ||
@@ -1603,10 +1553,13 @@ do_time_wait: | |||
1603 | goto discard_it; | 1553 | goto discard_it; |
1604 | } | 1554 | } |
1605 | 1555 | ||
1606 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1556 | if (skb->len < (th->doff<<2)) { |
1607 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); | ||
1608 | inet_twsk_put(inet_twsk(sk)); | 1557 | inet_twsk_put(inet_twsk(sk)); |
1609 | goto discard_it; | 1558 | goto bad_packet; |
1559 | } | ||
1560 | if (tcp_checksum_complete(skb)) { | ||
1561 | inet_twsk_put(inet_twsk(sk)); | ||
1562 | goto csum_error; | ||
1610 | } | 1563 | } |
1611 | 1564 | ||
1612 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { | 1565 | switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d8e5e852fc7a..d4defdd44937 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -450,15 +450,16 @@ try_again: | |||
450 | sin6->sin6_family = AF_INET6; | 450 | sin6->sin6_family = AF_INET6; |
451 | sin6->sin6_port = udp_hdr(skb)->source; | 451 | sin6->sin6_port = udp_hdr(skb)->source; |
452 | sin6->sin6_flowinfo = 0; | 452 | sin6->sin6_flowinfo = 0; |
453 | sin6->sin6_scope_id = 0; | ||
454 | 453 | ||
455 | if (is_udp4) | 454 | if (is_udp4) { |
456 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 455 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
457 | &sin6->sin6_addr); | 456 | &sin6->sin6_addr); |
458 | else { | 457 | sin6->sin6_scope_id = 0; |
458 | } else { | ||
459 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 459 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
460 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 460 | sin6->sin6_scope_id = |
461 | sin6->sin6_scope_id = IP6CB(skb)->iif; | 461 | ipv6_iface_scope_id(&sin6->sin6_addr, |
462 | IP6CB(skb)->iif); | ||
462 | } | 463 | } |
463 | 464 | ||
464 | } | 465 | } |
@@ -482,12 +483,17 @@ out: | |||
482 | csum_copy_err: | 483 | csum_copy_err: |
483 | slow = lock_sock_fast(sk); | 484 | slow = lock_sock_fast(sk); |
484 | if (!skb_kill_datagram(sk, skb, flags)) { | 485 | if (!skb_kill_datagram(sk, skb, flags)) { |
485 | if (is_udp4) | 486 | if (is_udp4) { |
487 | UDP_INC_STATS_USER(sock_net(sk), | ||
488 | UDP_MIB_CSUMERRORS, is_udplite); | ||
486 | UDP_INC_STATS_USER(sock_net(sk), | 489 | UDP_INC_STATS_USER(sock_net(sk), |
487 | UDP_MIB_INERRORS, is_udplite); | 490 | UDP_MIB_INERRORS, is_udplite); |
488 | else | 491 | } else { |
492 | UDP6_INC_STATS_USER(sock_net(sk), | ||
493 | UDP_MIB_CSUMERRORS, is_udplite); | ||
489 | UDP6_INC_STATS_USER(sock_net(sk), | 494 | UDP6_INC_STATS_USER(sock_net(sk), |
490 | UDP_MIB_INERRORS, is_udplite); | 495 | UDP_MIB_INERRORS, is_udplite); |
496 | } | ||
491 | } | 497 | } |
492 | unlock_sock_fast(sk, slow); | 498 | unlock_sock_fast(sk, slow); |
493 | 499 | ||
@@ -636,7 +642,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
636 | 642 | ||
637 | if (rcu_access_pointer(sk->sk_filter)) { | 643 | if (rcu_access_pointer(sk->sk_filter)) { |
638 | if (udp_lib_checksum_complete(skb)) | 644 | if (udp_lib_checksum_complete(skb)) |
639 | goto drop; | 645 | goto csum_error; |
640 | } | 646 | } |
641 | 647 | ||
642 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) | 648 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) |
@@ -655,6 +661,8 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
655 | bh_unlock_sock(sk); | 661 | bh_unlock_sock(sk); |
656 | 662 | ||
657 | return rc; | 663 | return rc; |
664 | csum_error: | ||
665 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); | ||
658 | drop: | 666 | drop: |
659 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 667 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
660 | atomic_inc(&sk->sk_drops); | 668 | atomic_inc(&sk->sk_drops); |
@@ -816,7 +824,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
816 | } | 824 | } |
817 | 825 | ||
818 | if (udp6_csum_init(skb, uh, proto)) | 826 | if (udp6_csum_init(skb, uh, proto)) |
819 | goto discard; | 827 | goto csum_error; |
820 | 828 | ||
821 | /* | 829 | /* |
822 | * Multicast receive code | 830 | * Multicast receive code |
@@ -849,7 +857,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
849 | goto discard; | 857 | goto discard; |
850 | 858 | ||
851 | if (udp_lib_checksum_complete(skb)) | 859 | if (udp_lib_checksum_complete(skb)) |
852 | goto discard; | 860 | goto csum_error; |
853 | 861 | ||
854 | UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); | 862 | UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); |
855 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | 863 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); |
@@ -866,7 +874,9 @@ short_packet: | |||
866 | skb->len, | 874 | skb->len, |
867 | daddr, | 875 | daddr, |
868 | ntohs(uh->dest)); | 876 | ntohs(uh->dest)); |
869 | 877 | goto discard; | |
878 | csum_error: | ||
879 | UDP6_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); | ||
870 | discard: | 880 | discard: |
871 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 881 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
872 | kfree_skb(skb); | 882 | kfree_skb(skb); |
@@ -1118,7 +1128,7 @@ do_udp_sendmsg: | |||
1118 | 1128 | ||
1119 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1129 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1120 | sin6->sin6_scope_id && | 1130 | sin6->sin6_scope_id && |
1121 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 1131 | __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr))) |
1122 | fl6.flowi6_oif = sin6->sin6_scope_id; | 1132 | fl6.flowi6_oif = sin6->sin6_scope_id; |
1123 | } else { | 1133 | } else { |
1124 | if (sk->sk_state != TCP_ESTABLISHED) | 1134 | if (sk->sk_state != TCP_ESTABLISHED) |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index cf05cf073c51..3bb3a891a424 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
@@ -21,6 +21,10 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
21 | const struct ipv6hdr *ipv6h; | 21 | const struct ipv6hdr *ipv6h; |
22 | struct udphdr *uh; | 22 | struct udphdr *uh; |
23 | 23 | ||
24 | /* UDP Tunnel offload on ipv6 is not yet supported. */ | ||
25 | if (skb->encapsulation) | ||
26 | return -EINVAL; | ||
27 | |||
24 | if (!pskb_may_pull(skb, sizeof(*uh))) | 28 | if (!pskb_may_pull(skb, sizeof(*uh))) |
25 | return -EINVAL; | 29 | return -EINVAL; |
26 | 30 | ||
@@ -56,7 +60,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
56 | /* Packet is from an untrusted source, reset gso_segs. */ | 60 | /* Packet is from an untrusted source, reset gso_segs. */ |
57 | int type = skb_shinfo(skb)->gso_type; | 61 | int type = skb_shinfo(skb)->gso_type; |
58 | 62 | ||
59 | if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | | 63 | if (unlikely(type & ~(SKB_GSO_UDP | |
64 | SKB_GSO_DODGY | | ||
65 | SKB_GSO_UDP_TUNNEL | | ||
60 | SKB_GSO_GRE) || | 66 | SKB_GSO_GRE) || |
61 | !(type & (SKB_GSO_UDP)))) | 67 | !(type & (SKB_GSO_UDP)))) |
62 | goto out; | 68 | goto out; |
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 9bf6a74a71d2..4770d515c2c8 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -49,8 +49,11 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
49 | sizeof(top_iph->flow_lbl)); | 49 | sizeof(top_iph->flow_lbl)); |
50 | top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family); | 50 | top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family); |
51 | 51 | ||
52 | dsfield = XFRM_MODE_SKB_CB(skb)->tos; | 52 | if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP) |
53 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); | 53 | dsfield = 0; |
54 | else | ||
55 | dsfield = XFRM_MODE_SKB_CB(skb)->tos; | ||
56 | dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos); | ||
54 | if (x->props.flags & XFRM_STATE_NOECN) | 57 | if (x->props.flags & XFRM_STATE_NOECN) |
55 | dsfield &= ~INET_ECN_MASK; | 58 | dsfield &= ~INET_ECN_MASK; |
56 | ipv6_change_dsfield(top_iph, 0, dsfield); | 59 | ipv6_change_dsfield(top_iph, 0, dsfield); |