diff options
Diffstat (limited to 'net/ipv6')
51 files changed, 1742 insertions, 1310 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 79682efb14be..8e5d54f23b49 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -57,6 +57,16 @@ config IPV6_ROUTE_INFO | |||
57 | 57 | ||
58 | If unsure, say N. | 58 | If unsure, say N. |
59 | 59 | ||
60 | config IPV6_OPTIMISTIC_DAD | ||
61 | bool "IPv6: Enable RFC 4429 Optimistic DAD (EXPERIMENTAL)" | ||
62 | depends on IPV6 && EXPERIMENTAL | ||
63 | ---help--- | ||
64 | This is experimental support for optimistic Duplicate | ||
65 | Address Detection. It allows for autoconfigured addresses | ||
66 | to be used more quickly. | ||
67 | |||
68 | If unsure, say N. | ||
69 | |||
60 | config INET6_AH | 70 | config INET6_AH |
61 | tristate "IPv6: AH transformation" | 71 | tristate "IPv6: AH transformation" |
62 | depends on IPV6 | 72 | depends on IPV6 |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index d460017bb353..bb33309044c9 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -7,14 +7,15 @@ obj-$(CONFIG_IPV6) += ipv6.o | |||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ | 7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ |
8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ | 8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ |
9 | raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 9 | raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ |
10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ | 10 | exthdrs.o sysctl_net_ipv6.o datagram.o \ |
11 | ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o | 11 | ip6_flowlabel.o inet6_connection_sock.o |
12 | 12 | ||
13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | 13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ |
14 | xfrm6_output.o | 14 | xfrm6_output.o |
15 | ipv6-$(CONFIG_NETFILTER) += netfilter.o | 15 | ipv6-$(CONFIG_NETFILTER) += netfilter.o |
16 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o | 16 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o |
17 | ipv6-$(CONFIG_IPV6_MIP6) += mip6.o | 17 | ipv6-$(CONFIG_IPV6_MIP6) += mip6.o |
18 | ipv6-$(CONFIG_PROC_FS) += proc.o | ||
18 | 19 | ||
19 | ipv6-objs += $(ipv6-y) | 20 | ipv6-objs += $(ipv6-y) |
20 | 21 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 452a82ce4796..e04e49373505 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | #include <asm/uaccess.h> | 83 | #include <asm/uaccess.h> |
84 | #include <asm/unaligned.h> | ||
84 | 85 | ||
85 | #include <linux/proc_fs.h> | 86 | #include <linux/proc_fs.h> |
86 | #include <linux/seq_file.h> | 87 | #include <linux/seq_file.h> |
@@ -208,9 +209,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
208 | }; | 209 | }; |
209 | 210 | ||
210 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | 211 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ |
211 | #if 0 | ||
212 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | 212 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; |
213 | #endif | ||
214 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | 213 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; |
215 | 214 | ||
216 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 215 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
@@ -246,6 +245,37 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
246 | add_timer(&ifp->timer); | 245 | add_timer(&ifp->timer); |
247 | } | 246 | } |
248 | 247 | ||
248 | static int snmp6_alloc_dev(struct inet6_dev *idev) | ||
249 | { | ||
250 | int err = -ENOMEM; | ||
251 | |||
252 | if (!idev || !idev->dev) | ||
253 | return -EINVAL; | ||
254 | |||
255 | if (snmp_mib_init((void **)idev->stats.ipv6, | ||
256 | sizeof(struct ipstats_mib), | ||
257 | __alignof__(struct ipstats_mib)) < 0) | ||
258 | goto err_ip; | ||
259 | if (snmp_mib_init((void **)idev->stats.icmpv6, | ||
260 | sizeof(struct icmpv6_mib), | ||
261 | __alignof__(struct icmpv6_mib)) < 0) | ||
262 | goto err_icmp; | ||
263 | |||
264 | return 0; | ||
265 | |||
266 | err_icmp: | ||
267 | snmp_mib_free((void **)idev->stats.ipv6); | ||
268 | err_ip: | ||
269 | return err; | ||
270 | } | ||
271 | |||
272 | static int snmp6_free_dev(struct inet6_dev *idev) | ||
273 | { | ||
274 | snmp_mib_free((void **)idev->stats.icmpv6); | ||
275 | snmp_mib_free((void **)idev->stats.ipv6); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
249 | /* Nobody refers to this device, we may destroy it. */ | 279 | /* Nobody refers to this device, we may destroy it. */ |
250 | 280 | ||
251 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) | 281 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) |
@@ -271,6 +301,8 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
271 | call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); | 301 | call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); |
272 | } | 302 | } |
273 | 303 | ||
304 | EXPORT_SYMBOL(in6_dev_finish_destroy); | ||
305 | |||
274 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | 306 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) |
275 | { | 307 | { |
276 | struct inet6_dev *ndev; | 308 | struct inet6_dev *ndev; |
@@ -528,6 +560,16 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
528 | 560 | ||
529 | ifa->rt = rt; | 561 | ifa->rt = rt; |
530 | 562 | ||
563 | /* | ||
564 | * part one of RFC 4429, section 3.3 | ||
565 | * We should not configure an address as | ||
566 | * optimistic if we do not yet know the link | ||
567 | * layer address of our nexhop router | ||
568 | */ | ||
569 | |||
570 | if (rt->rt6i_nexthop == NULL) | ||
571 | ifa->flags &= ~IFA_F_OPTIMISTIC; | ||
572 | |||
531 | ifa->idev = idev; | 573 | ifa->idev = idev; |
532 | in6_dev_hold(idev); | 574 | in6_dev_hold(idev); |
533 | /* For caller */ | 575 | /* For caller */ |
@@ -704,6 +746,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
704 | int tmp_plen; | 746 | int tmp_plen; |
705 | int ret = 0; | 747 | int ret = 0; |
706 | int max_addresses; | 748 | int max_addresses; |
749 | u32 addr_flags; | ||
707 | 750 | ||
708 | write_lock(&idev->lock); | 751 | write_lock(&idev->lock); |
709 | if (ift) { | 752 | if (ift) { |
@@ -761,10 +804,17 @@ retry: | |||
761 | spin_unlock_bh(&ifp->lock); | 804 | spin_unlock_bh(&ifp->lock); |
762 | 805 | ||
763 | write_unlock(&idev->lock); | 806 | write_unlock(&idev->lock); |
807 | |||
808 | addr_flags = IFA_F_TEMPORARY; | ||
809 | /* set in addrconf_prefix_rcv() */ | ||
810 | if (ifp->flags & IFA_F_OPTIMISTIC) | ||
811 | addr_flags |= IFA_F_OPTIMISTIC; | ||
812 | |||
764 | ift = !max_addresses || | 813 | ift = !max_addresses || |
765 | ipv6_count_addresses(idev) < max_addresses ? | 814 | ipv6_count_addresses(idev) < max_addresses ? |
766 | ipv6_add_addr(idev, &addr, tmp_plen, | 815 | ipv6_add_addr(idev, &addr, tmp_plen, |
767 | ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : NULL; | 816 | ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, |
817 | addr_flags) : NULL; | ||
768 | if (!ift || IS_ERR(ift)) { | 818 | if (!ift || IS_ERR(ift)) { |
769 | in6_ifa_put(ifp); | 819 | in6_ifa_put(ifp); |
770 | in6_dev_put(idev); | 820 | in6_dev_put(idev); |
@@ -896,13 +946,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
896 | * - Tentative Address (RFC2462 section 5.4) | 946 | * - Tentative Address (RFC2462 section 5.4) |
897 | * - A tentative address is not considered | 947 | * - A tentative address is not considered |
898 | * "assigned to an interface" in the traditional | 948 | * "assigned to an interface" in the traditional |
899 | * sense. | 949 | * sense, unless it is also flagged as optimistic. |
900 | * - Candidate Source Address (section 4) | 950 | * - Candidate Source Address (section 4) |
901 | * - In any case, anycast addresses, multicast | 951 | * - In any case, anycast addresses, multicast |
902 | * addresses, and the unspecified address MUST | 952 | * addresses, and the unspecified address MUST |
903 | * NOT be included in a candidate set. | 953 | * NOT be included in a candidate set. |
904 | */ | 954 | */ |
905 | if (ifa->flags & IFA_F_TENTATIVE) | 955 | if ((ifa->flags & IFA_F_TENTATIVE) && |
956 | (!(ifa->flags & IFA_F_OPTIMISTIC))) | ||
906 | continue; | 957 | continue; |
907 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 958 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || |
908 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 959 | score.addr_type & IPV6_ADDR_MULTICAST)) { |
@@ -961,15 +1012,17 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
961 | } | 1012 | } |
962 | } | 1013 | } |
963 | 1014 | ||
964 | /* Rule 3: Avoid deprecated address */ | 1015 | /* Rule 3: Avoid deprecated and optimistic addresses */ |
965 | if (hiscore.rule < 3) { | 1016 | if (hiscore.rule < 3) { |
966 | if (ipv6_saddr_preferred(hiscore.addr_type) || | 1017 | if (ipv6_saddr_preferred(hiscore.addr_type) || |
967 | !(ifa_result->flags & IFA_F_DEPRECATED)) | 1018 | (((ifa_result->flags & |
1019 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) | ||
968 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | 1020 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; |
969 | hiscore.rule++; | 1021 | hiscore.rule++; |
970 | } | 1022 | } |
971 | if (ipv6_saddr_preferred(score.addr_type) || | 1023 | if (ipv6_saddr_preferred(score.addr_type) || |
972 | !(ifa->flags & IFA_F_DEPRECATED)) { | 1024 | (((ifa_result->flags & |
1025 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { | ||
973 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | 1026 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; |
974 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | 1027 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { |
975 | score.rule = 3; | 1028 | score.rule = 3; |
@@ -1107,8 +1160,10 @@ int ipv6_get_saddr(struct dst_entry *dst, | |||
1107 | return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); | 1160 | return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); |
1108 | } | 1161 | } |
1109 | 1162 | ||
1163 | EXPORT_SYMBOL(ipv6_get_saddr); | ||
1110 | 1164 | ||
1111 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) | 1165 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1166 | unsigned char banned_flags) | ||
1112 | { | 1167 | { |
1113 | struct inet6_dev *idev; | 1168 | struct inet6_dev *idev; |
1114 | int err = -EADDRNOTAVAIL; | 1169 | int err = -EADDRNOTAVAIL; |
@@ -1119,7 +1174,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) | |||
1119 | 1174 | ||
1120 | read_lock_bh(&idev->lock); | 1175 | read_lock_bh(&idev->lock); |
1121 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1176 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { |
1122 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1177 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { |
1123 | ipv6_addr_copy(addr, &ifp->addr); | 1178 | ipv6_addr_copy(addr, &ifp->addr); |
1124 | err = 0; | 1179 | err = 0; |
1125 | break; | 1180 | break; |
@@ -1161,6 +1216,8 @@ int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict) | |||
1161 | return ifp != NULL; | 1216 | return ifp != NULL; |
1162 | } | 1217 | } |
1163 | 1218 | ||
1219 | EXPORT_SYMBOL(ipv6_chk_addr); | ||
1220 | |||
1164 | static | 1221 | static |
1165 | int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev) | 1222 | int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev) |
1166 | { | 1223 | { |
@@ -1669,6 +1726,13 @@ ok: | |||
1669 | 1726 | ||
1670 | if (ifp == NULL && valid_lft) { | 1727 | if (ifp == NULL && valid_lft) { |
1671 | int max_addresses = in6_dev->cnf.max_addresses; | 1728 | int max_addresses = in6_dev->cnf.max_addresses; |
1729 | u32 addr_flags = 0; | ||
1730 | |||
1731 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
1732 | if (in6_dev->cnf.optimistic_dad && | ||
1733 | !ipv6_devconf.forwarding) | ||
1734 | addr_flags = IFA_F_OPTIMISTIC; | ||
1735 | #endif | ||
1672 | 1736 | ||
1673 | /* Do not allow to create too much of autoconfigured | 1737 | /* Do not allow to create too much of autoconfigured |
1674 | * addresses; this would be too easy way to crash kernel. | 1738 | * addresses; this would be too easy way to crash kernel. |
@@ -1676,7 +1740,8 @@ ok: | |||
1676 | if (!max_addresses || | 1740 | if (!max_addresses || |
1677 | ipv6_count_addresses(in6_dev) < max_addresses) | 1741 | ipv6_count_addresses(in6_dev) < max_addresses) |
1678 | ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, | 1742 | ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, |
1679 | addr_type&IPV6_ADDR_SCOPE_MASK, 0); | 1743 | addr_type&IPV6_ADDR_SCOPE_MASK, |
1744 | addr_flags); | ||
1680 | 1745 | ||
1681 | if (!ifp || IS_ERR(ifp)) { | 1746 | if (!ifp || IS_ERR(ifp)) { |
1682 | in6_dev_put(in6_dev); | 1747 | in6_dev_put(in6_dev); |
@@ -1884,6 +1949,11 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1884 | 1949 | ||
1885 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, | 1950 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, |
1886 | jiffies_to_clock_t(valid_lft * HZ), flags); | 1951 | jiffies_to_clock_t(valid_lft * HZ), flags); |
1952 | /* | ||
1953 | * Note that section 3.1 of RFC 4429 indicates | ||
1954 | * that the Optimistic flag should not be set for | ||
1955 | * manually configured addresses | ||
1956 | */ | ||
1887 | addrconf_dad_start(ifp, 0); | 1957 | addrconf_dad_start(ifp, 0); |
1888 | in6_ifa_put(ifp); | 1958 | in6_ifa_put(ifp); |
1889 | addrconf_verify(0); | 1959 | addrconf_verify(0); |
@@ -2060,8 +2130,16 @@ static void init_loopback(struct net_device *dev) | |||
2060 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2130 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) |
2061 | { | 2131 | { |
2062 | struct inet6_ifaddr * ifp; | 2132 | struct inet6_ifaddr * ifp; |
2133 | u32 addr_flags = IFA_F_PERMANENT; | ||
2134 | |||
2135 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
2136 | if (idev->cnf.optimistic_dad && | ||
2137 | !ipv6_devconf.forwarding) | ||
2138 | addr_flags |= IFA_F_OPTIMISTIC; | ||
2139 | #endif | ||
2063 | 2140 | ||
2064 | ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); | 2141 | |
2142 | ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, addr_flags); | ||
2065 | if (!IS_ERR(ifp)) { | 2143 | if (!IS_ERR(ifp)) { |
2066 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); | 2144 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); |
2067 | addrconf_dad_start(ifp, 0); | 2145 | addrconf_dad_start(ifp, 0); |
@@ -2129,7 +2207,7 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | |||
2129 | { | 2207 | { |
2130 | struct in6_addr lladdr; | 2208 | struct in6_addr lladdr; |
2131 | 2209 | ||
2132 | if (!ipv6_get_lladdr(link_dev, &lladdr)) { | 2210 | if (!ipv6_get_lladdr(link_dev, &lladdr, IFA_F_TENTATIVE)) { |
2133 | addrconf_add_linklocal(idev, &lladdr); | 2211 | addrconf_add_linklocal(idev, &lladdr); |
2134 | return 0; | 2212 | return 0; |
2135 | } | 2213 | } |
@@ -2240,7 +2318,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2240 | default: | 2318 | default: |
2241 | addrconf_dev_config(dev); | 2319 | addrconf_dev_config(dev); |
2242 | break; | 2320 | break; |
2243 | }; | 2321 | } |
2244 | if (idev) { | 2322 | if (idev) { |
2245 | if (run_pending) | 2323 | if (run_pending) |
2246 | addrconf_dad_run(idev); | 2324 | addrconf_dad_run(idev); |
@@ -2293,7 +2371,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2293 | } | 2371 | } |
2294 | #endif | 2372 | #endif |
2295 | break; | 2373 | break; |
2296 | }; | 2374 | } |
2297 | 2375 | ||
2298 | return NOTIFY_OK; | 2376 | return NOTIFY_OK; |
2299 | } | 2377 | } |
@@ -2474,7 +2552,11 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | |||
2474 | unsigned long rand_num; | 2552 | unsigned long rand_num; |
2475 | struct inet6_dev *idev = ifp->idev; | 2553 | struct inet6_dev *idev = ifp->idev; |
2476 | 2554 | ||
2477 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | 2555 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2556 | rand_num = 0; | ||
2557 | else | ||
2558 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
2559 | |||
2478 | ifp->probes = idev->cnf.dad_transmits; | 2560 | ifp->probes = idev->cnf.dad_transmits; |
2479 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | 2561 | addrconf_mod_timer(ifp, AC_DAD, rand_num); |
2480 | } | 2562 | } |
@@ -2496,7 +2578,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2496 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2578 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2497 | !(ifp->flags&IFA_F_TENTATIVE) || | 2579 | !(ifp->flags&IFA_F_TENTATIVE) || |
2498 | ifp->flags & IFA_F_NODAD) { | 2580 | ifp->flags & IFA_F_NODAD) { |
2499 | ifp->flags &= ~IFA_F_TENTATIVE; | 2581 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); |
2500 | spin_unlock_bh(&ifp->lock); | 2582 | spin_unlock_bh(&ifp->lock); |
2501 | read_unlock_bh(&idev->lock); | 2583 | read_unlock_bh(&idev->lock); |
2502 | 2584 | ||
@@ -2516,6 +2598,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2516 | addrconf_dad_stop(ifp); | 2598 | addrconf_dad_stop(ifp); |
2517 | return; | 2599 | return; |
2518 | } | 2600 | } |
2601 | |||
2602 | /* | ||
2603 | * Optimistic nodes can start receiving | ||
2604 | * Frames right away | ||
2605 | */ | ||
2606 | if(ifp->flags & IFA_F_OPTIMISTIC) | ||
2607 | ip6_ins_rt(ifp->rt); | ||
2608 | |||
2519 | addrconf_dad_kick(ifp); | 2609 | addrconf_dad_kick(ifp); |
2520 | spin_unlock_bh(&ifp->lock); | 2610 | spin_unlock_bh(&ifp->lock); |
2521 | out: | 2611 | out: |
@@ -2540,7 +2630,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2540 | * DAD was successful | 2630 | * DAD was successful |
2541 | */ | 2631 | */ |
2542 | 2632 | ||
2543 | ifp->flags &= ~IFA_F_TENTATIVE; | 2633 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); |
2544 | spin_unlock_bh(&ifp->lock); | 2634 | spin_unlock_bh(&ifp->lock); |
2545 | read_unlock_bh(&idev->lock); | 2635 | read_unlock_bh(&idev->lock); |
2546 | 2636 | ||
@@ -3164,7 +3254,6 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3164 | 3254 | ||
3165 | s_idx = cb->args[0]; | 3255 | s_idx = cb->args[0]; |
3166 | s_ip_idx = ip_idx = cb->args[1]; | 3256 | s_ip_idx = ip_idx = cb->args[1]; |
3167 | read_lock(&dev_base_lock); | ||
3168 | 3257 | ||
3169 | for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { | 3258 | for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { |
3170 | if (idx < s_idx) | 3259 | if (idx < s_idx) |
@@ -3226,7 +3315,6 @@ done: | |||
3226 | read_unlock_bh(&idev->lock); | 3315 | read_unlock_bh(&idev->lock); |
3227 | in6_dev_put(idev); | 3316 | in6_dev_put(idev); |
3228 | } | 3317 | } |
3229 | read_unlock(&dev_base_lock); | ||
3230 | cb->args[0] = idx; | 3318 | cb->args[0] = idx; |
3231 | cb->args[1] = ip_idx; | 3319 | cb->args[1] = ip_idx; |
3232 | return skb->len; | 3320 | return skb->len; |
@@ -3359,6 +3447,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3359 | #endif | 3447 | #endif |
3360 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; | 3448 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; |
3361 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; | 3449 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; |
3450 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
3451 | array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad; | ||
3452 | #endif | ||
3362 | } | 3453 | } |
3363 | 3454 | ||
3364 | static inline size_t inet6_if_nlmsg_size(void) | 3455 | static inline size_t inet6_if_nlmsg_size(void) |
@@ -3372,14 +3463,44 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3372 | nla_total_size(4) /* IFLA_INET6_FLAGS */ | 3463 | nla_total_size(4) /* IFLA_INET6_FLAGS */ |
3373 | + nla_total_size(sizeof(struct ifla_cacheinfo)) | 3464 | + nla_total_size(sizeof(struct ifla_cacheinfo)) |
3374 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ | 3465 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ |
3466 | + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ | ||
3467 | + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */ | ||
3375 | ); | 3468 | ); |
3376 | } | 3469 | } |
3377 | 3470 | ||
3471 | static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | ||
3472 | int bytes) | ||
3473 | { | ||
3474 | int i; | ||
3475 | int pad = bytes - sizeof(u64) * items; | ||
3476 | BUG_ON(pad < 0); | ||
3477 | |||
3478 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
3479 | put_unaligned(items, &stats[0]); | ||
3480 | for (i = 1; i < items; i++) | ||
3481 | put_unaligned(snmp_fold_field(mib, i), &stats[i]); | ||
3482 | |||
3483 | memset(&stats[items], 0, pad); | ||
3484 | } | ||
3485 | |||
3486 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | ||
3487 | int bytes) | ||
3488 | { | ||
3489 | switch(attrtype) { | ||
3490 | case IFLA_INET6_STATS: | ||
3491 | __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | ||
3492 | break; | ||
3493 | case IFLA_INET6_ICMP6STATS: | ||
3494 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | ||
3495 | break; | ||
3496 | } | ||
3497 | } | ||
3498 | |||
3378 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3499 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
3379 | u32 pid, u32 seq, int event, unsigned int flags) | 3500 | u32 pid, u32 seq, int event, unsigned int flags) |
3380 | { | 3501 | { |
3381 | struct net_device *dev = idev->dev; | 3502 | struct net_device *dev = idev->dev; |
3382 | struct nlattr *conf; | 3503 | struct nlattr *nla; |
3383 | struct ifinfomsg *hdr; | 3504 | struct ifinfomsg *hdr; |
3384 | struct nlmsghdr *nlh; | 3505 | struct nlmsghdr *nlh; |
3385 | void *protoinfo; | 3506 | void *protoinfo; |
@@ -3419,12 +3540,22 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | |||
3419 | ci.retrans_time = idev->nd_parms->retrans_time; | 3540 | ci.retrans_time = idev->nd_parms->retrans_time; |
3420 | NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); | 3541 | NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); |
3421 | 3542 | ||
3422 | conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); | 3543 | nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); |
3423 | if (conf == NULL) | 3544 | if (nla == NULL) |
3424 | goto nla_put_failure; | 3545 | goto nla_put_failure; |
3425 | ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf)); | 3546 | ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla)); |
3426 | 3547 | ||
3427 | /* XXX - Statistics/MC not implemented */ | 3548 | /* XXX - MC not implemented */ |
3549 | |||
3550 | nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); | ||
3551 | if (nla == NULL) | ||
3552 | goto nla_put_failure; | ||
3553 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); | ||
3554 | |||
3555 | nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); | ||
3556 | if (nla == NULL) | ||
3557 | goto nla_put_failure; | ||
3558 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); | ||
3428 | 3559 | ||
3429 | nla_nest_end(skb, protoinfo); | 3560 | nla_nest_end(skb, protoinfo); |
3430 | return nlmsg_end(skb, nlh); | 3561 | return nlmsg_end(skb, nlh); |
@@ -3550,30 +3681,20 @@ errout: | |||
3550 | rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err); | 3681 | rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err); |
3551 | } | 3682 | } |
3552 | 3683 | ||
3553 | static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { | ||
3554 | [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, | ||
3555 | [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, | ||
3556 | [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, | ||
3557 | [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr, | ||
3558 | .dumpit = inet6_dump_ifaddr, }, | ||
3559 | [RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, }, | ||
3560 | [RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, }, | ||
3561 | [RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, }, | ||
3562 | [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, }, | ||
3563 | [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute, | ||
3564 | .dumpit = inet6_dump_fib, }, | ||
3565 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
3566 | [RTM_GETRULE - RTM_BASE] = { .dumpit = fib6_rules_dump, }, | ||
3567 | #endif | ||
3568 | }; | ||
3569 | |||
3570 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 3684 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
3571 | { | 3685 | { |
3572 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); | 3686 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); |
3573 | 3687 | ||
3574 | switch (event) { | 3688 | switch (event) { |
3575 | case RTM_NEWADDR: | 3689 | case RTM_NEWADDR: |
3576 | ip6_ins_rt(ifp->rt); | 3690 | /* |
3691 | * If the address was optimistic | ||
3692 | * we inserted the route at the start of | ||
3693 | * our DAD process, so we don't need | ||
3694 | * to do it again | ||
3695 | */ | ||
3696 | if (!(ifp->rt->rt6i_node)) | ||
3697 | ip6_ins_rt(ifp->rt); | ||
3577 | if (ifp->idev->cnf.forwarding) | 3698 | if (ifp->idev->cnf.forwarding) |
3578 | addrconf_join_anycast(ifp); | 3699 | addrconf_join_anycast(ifp); |
3579 | break; | 3700 | break; |
@@ -3894,6 +4015,17 @@ static struct addrconf_sysctl_table | |||
3894 | .mode = 0644, | 4015 | .mode = 0644, |
3895 | .proc_handler = &proc_dointvec, | 4016 | .proc_handler = &proc_dointvec, |
3896 | }, | 4017 | }, |
4018 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
4019 | { | ||
4020 | .ctl_name = CTL_UNNUMBERED, | ||
4021 | .procname = "optimistic_dad", | ||
4022 | .data = &ipv6_devconf.optimistic_dad, | ||
4023 | .maxlen = sizeof(int), | ||
4024 | .mode = 0644, | ||
4025 | .proc_handler = &proc_dointvec, | ||
4026 | |||
4027 | }, | ||
4028 | #endif | ||
3897 | { | 4029 | { |
3898 | .ctl_name = 0, /* sentinel */ | 4030 | .ctl_name = 0, /* sentinel */ |
3899 | } | 4031 | } |
@@ -4021,11 +4153,15 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
4021 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4153 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
4022 | } | 4154 | } |
4023 | 4155 | ||
4156 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
4157 | |||
4024 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4158 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
4025 | { | 4159 | { |
4026 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4160 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); |
4027 | } | 4161 | } |
4028 | 4162 | ||
4163 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
4164 | |||
4029 | /* | 4165 | /* |
4030 | * Init / cleanup code | 4166 | * Init / cleanup code |
4031 | */ | 4167 | */ |
@@ -4064,7 +4200,18 @@ int __init addrconf_init(void) | |||
4064 | register_netdevice_notifier(&ipv6_dev_notf); | 4200 | register_netdevice_notifier(&ipv6_dev_notf); |
4065 | 4201 | ||
4066 | addrconf_verify(0); | 4202 | addrconf_verify(0); |
4067 | rtnetlink_links[PF_INET6] = inet6_rtnetlink_table; | 4203 | |
4204 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo); | ||
4205 | if (err < 0) | ||
4206 | goto errout; | ||
4207 | |||
4208 | /* Only the first call to __rtnl_register can fail */ | ||
4209 | __rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL); | ||
4210 | __rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL); | ||
4211 | __rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr); | ||
4212 | __rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr); | ||
4213 | __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr); | ||
4214 | |||
4068 | #ifdef CONFIG_SYSCTL | 4215 | #ifdef CONFIG_SYSCTL |
4069 | addrconf_sysctl.sysctl_header = | 4216 | addrconf_sysctl.sysctl_header = |
4070 | register_sysctl_table(addrconf_sysctl.addrconf_root_dir); | 4217 | register_sysctl_table(addrconf_sysctl.addrconf_root_dir); |
@@ -4072,6 +4219,10 @@ int __init addrconf_init(void) | |||
4072 | #endif | 4219 | #endif |
4073 | 4220 | ||
4074 | return 0; | 4221 | return 0; |
4222 | errout: | ||
4223 | unregister_netdevice_notifier(&ipv6_dev_notf); | ||
4224 | |||
4225 | return err; | ||
4075 | } | 4226 | } |
4076 | 4227 | ||
4077 | void __exit addrconf_cleanup(void) | 4228 | void __exit addrconf_cleanup(void) |
@@ -4083,7 +4234,6 @@ void __exit addrconf_cleanup(void) | |||
4083 | 4234 | ||
4084 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4235 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4085 | 4236 | ||
4086 | rtnetlink_links[PF_INET6] = NULL; | ||
4087 | #ifdef CONFIG_SYSCTL | 4237 | #ifdef CONFIG_SYSCTL |
4088 | addrconf_sysctl_unregister(&ipv6_devconf_dflt); | 4238 | addrconf_sysctl_unregister(&ipv6_devconf_dflt); |
4089 | addrconf_sysctl_unregister(&ipv6_devconf); | 4239 | addrconf_sysctl_unregister(&ipv6_devconf); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 5cac14a5c778..18cb928c8d92 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -98,6 +98,11 @@ static int inet6_create(struct socket *sock, int protocol) | |||
98 | int try_loading_module = 0; | 98 | int try_loading_module = 0; |
99 | int err; | 99 | int err; |
100 | 100 | ||
101 | if (sock->type != SOCK_RAW && | ||
102 | sock->type != SOCK_DGRAM && | ||
103 | !inet_ehash_secret) | ||
104 | build_ehash_secret(); | ||
105 | |||
101 | /* Look for the requested type/protocol pair. */ | 106 | /* Look for the requested type/protocol pair. */ |
102 | answer = NULL; | 107 | answer = NULL; |
103 | lookup_protocol: | 108 | lookup_protocol: |
@@ -349,6 +354,8 @@ out: | |||
349 | return err; | 354 | return err; |
350 | } | 355 | } |
351 | 356 | ||
357 | EXPORT_SYMBOL(inet6_bind); | ||
358 | |||
352 | int inet6_release(struct socket *sock) | 359 | int inet6_release(struct socket *sock) |
353 | { | 360 | { |
354 | struct sock *sk = sock->sk; | 361 | struct sock *sk = sock->sk; |
@@ -365,6 +372,8 @@ int inet6_release(struct socket *sock) | |||
365 | return inet_release(sock); | 372 | return inet_release(sock); |
366 | } | 373 | } |
367 | 374 | ||
375 | EXPORT_SYMBOL(inet6_release); | ||
376 | |||
368 | int inet6_destroy_sock(struct sock *sk) | 377 | int inet6_destroy_sock(struct sock *sk) |
369 | { | 378 | { |
370 | struct ipv6_pinfo *np = inet6_sk(sk); | 379 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -428,6 +437,8 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
428 | return(0); | 437 | return(0); |
429 | } | 438 | } |
430 | 439 | ||
440 | EXPORT_SYMBOL(inet6_getname); | ||
441 | |||
431 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 442 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
432 | { | 443 | { |
433 | struct sock *sk = sock->sk; | 444 | struct sock *sk = sock->sk; |
@@ -437,6 +448,9 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
437 | case SIOCGSTAMP: | 448 | case SIOCGSTAMP: |
438 | return sock_get_timestamp(sk, (struct timeval __user *)arg); | 449 | return sock_get_timestamp(sk, (struct timeval __user *)arg); |
439 | 450 | ||
451 | case SIOCGSTAMPNS: | ||
452 | return sock_get_timestampns(sk, (struct timespec __user *)arg); | ||
453 | |||
440 | case SIOCADDRT: | 454 | case SIOCADDRT: |
441 | case SIOCDELRT: | 455 | case SIOCDELRT: |
442 | 456 | ||
@@ -457,6 +471,8 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
457 | return(0); | 471 | return(0); |
458 | } | 472 | } |
459 | 473 | ||
474 | EXPORT_SYMBOL(inet6_ioctl); | ||
475 | |||
460 | const struct proto_ops inet6_stream_ops = { | 476 | const struct proto_ops inet6_stream_ops = { |
461 | .family = PF_INET6, | 477 | .family = PF_INET6, |
462 | .owner = THIS_MODULE, | 478 | .owner = THIS_MODULE, |
@@ -603,6 +619,8 @@ out_illegal: | |||
603 | goto out; | 619 | goto out; |
604 | } | 620 | } |
605 | 621 | ||
622 | EXPORT_SYMBOL(inet6_register_protosw); | ||
623 | |||
606 | void | 624 | void |
607 | inet6_unregister_protosw(struct inet_protosw *p) | 625 | inet6_unregister_protosw(struct inet_protosw *p) |
608 | { | 626 | { |
@@ -619,6 +637,8 @@ inet6_unregister_protosw(struct inet_protosw *p) | |||
619 | } | 637 | } |
620 | } | 638 | } |
621 | 639 | ||
640 | EXPORT_SYMBOL(inet6_unregister_protosw); | ||
641 | |||
622 | int inet6_sk_rebuild_header(struct sock *sk) | 642 | int inet6_sk_rebuild_header(struct sock *sk) |
623 | { | 643 | { |
624 | int err; | 644 | int err; |
@@ -678,7 +698,8 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
678 | if (np->rxopt.all) { | 698 | if (np->rxopt.all) { |
679 | if ((opt->hop && (np->rxopt.bits.hopopts || | 699 | if ((opt->hop && (np->rxopt.bits.hopopts || |
680 | np->rxopt.bits.ohopopts)) || | 700 | np->rxopt.bits.ohopopts)) || |
681 | ((IPV6_FLOWINFO_MASK & *(__be32*)skb->nh.raw) && | 701 | ((IPV6_FLOWINFO_MASK & |
702 | *(__be32 *)skb_network_header(skb)) && | ||
682 | np->rxopt.bits.rxflow) || | 703 | np->rxopt.bits.rxflow) || |
683 | (opt->srcrt && (np->rxopt.bits.srcrt || | 704 | (opt->srcrt && (np->rxopt.bits.srcrt || |
684 | np->rxopt.bits.osrcrt)) || | 705 | np->rxopt.bits.osrcrt)) || |
@@ -691,61 +712,28 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
691 | 712 | ||
692 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); | 713 | EXPORT_SYMBOL_GPL(ipv6_opt_accepted); |
693 | 714 | ||
694 | int | ||
695 | snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) | ||
696 | { | ||
697 | if (ptr == NULL) | ||
698 | return -EINVAL; | ||
699 | |||
700 | ptr[0] = __alloc_percpu(mibsize); | ||
701 | if (!ptr[0]) | ||
702 | goto err0; | ||
703 | |||
704 | ptr[1] = __alloc_percpu(mibsize); | ||
705 | if (!ptr[1]) | ||
706 | goto err1; | ||
707 | |||
708 | return 0; | ||
709 | |||
710 | err1: | ||
711 | free_percpu(ptr[0]); | ||
712 | ptr[0] = NULL; | ||
713 | err0: | ||
714 | return -ENOMEM; | ||
715 | } | ||
716 | |||
717 | void | ||
718 | snmp6_mib_free(void *ptr[2]) | ||
719 | { | ||
720 | if (ptr == NULL) | ||
721 | return; | ||
722 | free_percpu(ptr[0]); | ||
723 | free_percpu(ptr[1]); | ||
724 | ptr[0] = ptr[1] = NULL; | ||
725 | } | ||
726 | |||
727 | static int __init init_ipv6_mibs(void) | 715 | static int __init init_ipv6_mibs(void) |
728 | { | 716 | { |
729 | if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib), | 717 | if (snmp_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib), |
730 | __alignof__(struct ipstats_mib)) < 0) | 718 | __alignof__(struct ipstats_mib)) < 0) |
731 | goto err_ip_mib; | 719 | goto err_ip_mib; |
732 | if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), | 720 | if (snmp_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), |
733 | __alignof__(struct icmpv6_mib)) < 0) | 721 | __alignof__(struct icmpv6_mib)) < 0) |
734 | goto err_icmp_mib; | 722 | goto err_icmp_mib; |
735 | if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), | 723 | if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), |
736 | __alignof__(struct udp_mib)) < 0) | 724 | __alignof__(struct udp_mib)) < 0) |
737 | goto err_udp_mib; | 725 | goto err_udp_mib; |
738 | if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), | 726 | if (snmp_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), |
739 | __alignof__(struct udp_mib)) < 0) | 727 | __alignof__(struct udp_mib)) < 0) |
740 | goto err_udplite_mib; | 728 | goto err_udplite_mib; |
741 | return 0; | 729 | return 0; |
742 | 730 | ||
743 | err_udplite_mib: | 731 | err_udplite_mib: |
744 | snmp6_mib_free((void **)udp_stats_in6); | 732 | snmp_mib_free((void **)udp_stats_in6); |
745 | err_udp_mib: | 733 | err_udp_mib: |
746 | snmp6_mib_free((void **)icmpv6_statistics); | 734 | snmp_mib_free((void **)icmpv6_statistics); |
747 | err_icmp_mib: | 735 | err_icmp_mib: |
748 | snmp6_mib_free((void **)ipv6_statistics); | 736 | snmp_mib_free((void **)ipv6_statistics); |
749 | err_ip_mib: | 737 | err_ip_mib: |
750 | return -ENOMEM; | 738 | return -ENOMEM; |
751 | 739 | ||
@@ -753,10 +741,10 @@ err_ip_mib: | |||
753 | 741 | ||
754 | static void cleanup_ipv6_mibs(void) | 742 | static void cleanup_ipv6_mibs(void) |
755 | { | 743 | { |
756 | snmp6_mib_free((void **)ipv6_statistics); | 744 | snmp_mib_free((void **)ipv6_statistics); |
757 | snmp6_mib_free((void **)icmpv6_statistics); | 745 | snmp_mib_free((void **)icmpv6_statistics); |
758 | snmp6_mib_free((void **)udp_stats_in6); | 746 | snmp_mib_free((void **)udp_stats_in6); |
759 | snmp6_mib_free((void **)udplite_stats_in6); | 747 | snmp_mib_free((void **)udplite_stats_in6); |
760 | } | 748 | } |
761 | 749 | ||
762 | static int __init inet6_init(void) | 750 | static int __init inet6_init(void) |
@@ -929,6 +917,8 @@ static void __exit inet6_exit(void) | |||
929 | { | 917 | { |
930 | /* First of all disallow new sockets creation. */ | 918 | /* First of all disallow new sockets creation. */ |
931 | sock_unregister(PF_INET6); | 919 | sock_unregister(PF_INET6); |
920 | /* Disallow any further netlink messages */ | ||
921 | rtnl_unregister_all(PF_INET6); | ||
932 | 922 | ||
933 | /* Cleanup code parts. */ | 923 | /* Cleanup code parts. */ |
934 | ipv6_packet_cleanup(); | 924 | ipv6_packet_cleanup(); |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index dc68b7269c3c..b696c8401200 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -238,8 +238,8 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
238 | top_iph = (struct ipv6hdr *)skb->data; | 238 | top_iph = (struct ipv6hdr *)skb->data; |
239 | top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); | 239 | top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); |
240 | 240 | ||
241 | nexthdr = *skb->nh.raw; | 241 | nexthdr = *skb_network_header(skb); |
242 | *skb->nh.raw = IPPROTO_AH; | 242 | *skb_network_header(skb) = IPPROTO_AH; |
243 | 243 | ||
244 | /* When there are no extension headers, we only need to save the first | 244 | /* When there are no extension headers, we only need to save the first |
245 | * 8 bytes of the base IP header. | 245 | * 8 bytes of the base IP header. |
@@ -247,7 +247,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
247 | memcpy(tmp_base, top_iph, sizeof(tmp_base)); | 247 | memcpy(tmp_base, top_iph, sizeof(tmp_base)); |
248 | 248 | ||
249 | tmp_ext = NULL; | 249 | tmp_ext = NULL; |
250 | extlen = skb->h.raw - (unsigned char *)(top_iph + 1); | 250 | extlen = skb_transport_offset(skb) + sizeof(struct ipv6hdr); |
251 | if (extlen) { | 251 | if (extlen) { |
252 | extlen += sizeof(*tmp_ext); | 252 | extlen += sizeof(*tmp_ext); |
253 | tmp_ext = kmalloc(extlen, GFP_ATOMIC); | 253 | tmp_ext = kmalloc(extlen, GFP_ATOMIC); |
@@ -268,7 +268,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
268 | goto error_free_iph; | 268 | goto error_free_iph; |
269 | } | 269 | } |
270 | 270 | ||
271 | ah = (struct ip_auth_hdr *)skb->h.raw; | 271 | ah = (struct ip_auth_hdr *)skb_transport_header(skb); |
272 | ah->nexthdr = nexthdr; | 272 | ah->nexthdr = nexthdr; |
273 | 273 | ||
274 | top_iph->priority = 0; | 274 | top_iph->priority = 0; |
@@ -316,8 +316,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
316 | * | 316 | * |
317 | * To erase AH: | 317 | * To erase AH: |
318 | * Keeping copy of cleared headers. After AH processing, | 318 | * Keeping copy of cleared headers. After AH processing, |
319 | * Moving the pointer of skb->nh.raw by using skb_pull as long as AH | 319 | * Moving the pointer of skb->network_header by using skb_pull as long |
320 | * header length. Then copy back the copy as long as hdr_len | 320 | * as AH header length. Then copy back the copy as long as hdr_len |
321 | * If destination header following AH exists, copy it into after [Ext2]. | 321 | * If destination header following AH exists, copy it into after [Ext2]. |
322 | * | 322 | * |
323 | * |<>|[IPv6][Ext1][Ext2][Dest][Payload] | 323 | * |<>|[IPv6][Ext1][Ext2][Dest][Payload] |
@@ -325,6 +325,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
325 | */ | 325 | */ |
326 | 326 | ||
327 | struct ipv6_auth_hdr *ah; | 327 | struct ipv6_auth_hdr *ah; |
328 | struct ipv6hdr *ip6h; | ||
328 | struct ah_data *ahp; | 329 | struct ah_data *ahp; |
329 | unsigned char *tmp_hdr = NULL; | 330 | unsigned char *tmp_hdr = NULL; |
330 | u16 hdr_len; | 331 | u16 hdr_len; |
@@ -341,7 +342,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
341 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 342 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
342 | goto out; | 343 | goto out; |
343 | 344 | ||
344 | hdr_len = skb->data - skb->nh.raw; | 345 | hdr_len = skb->data - skb_network_header(skb); |
345 | ah = (struct ipv6_auth_hdr*)skb->data; | 346 | ah = (struct ipv6_auth_hdr*)skb->data; |
346 | ahp = x->data; | 347 | ahp = x->data; |
347 | nexthdr = ah->nexthdr; | 348 | nexthdr = ah->nexthdr; |
@@ -354,16 +355,17 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
354 | if (!pskb_may_pull(skb, ah_hlen)) | 355 | if (!pskb_may_pull(skb, ah_hlen)) |
355 | goto out; | 356 | goto out; |
356 | 357 | ||
357 | tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); | 358 | tmp_hdr = kmemdup(skb_network_header(skb), hdr_len, GFP_ATOMIC); |
358 | if (!tmp_hdr) | 359 | if (!tmp_hdr) |
359 | goto out; | 360 | goto out; |
360 | if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) | 361 | ip6h = ipv6_hdr(skb); |
362 | if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN)) | ||
361 | goto free_out; | 363 | goto free_out; |
362 | skb->nh.ipv6h->priority = 0; | 364 | ip6h->priority = 0; |
363 | skb->nh.ipv6h->flow_lbl[0] = 0; | 365 | ip6h->flow_lbl[0] = 0; |
364 | skb->nh.ipv6h->flow_lbl[1] = 0; | 366 | ip6h->flow_lbl[1] = 0; |
365 | skb->nh.ipv6h->flow_lbl[2] = 0; | 367 | ip6h->flow_lbl[2] = 0; |
366 | skb->nh.ipv6h->hop_limit = 0; | 368 | ip6h->hop_limit = 0; |
367 | 369 | ||
368 | { | 370 | { |
369 | u8 auth_data[MAX_AH_AUTH_LEN]; | 371 | u8 auth_data[MAX_AH_AUTH_LEN]; |
@@ -382,7 +384,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
382 | } | 384 | } |
383 | } | 385 | } |
384 | 386 | ||
385 | skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len); | 387 | skb->network_header += ah_hlen; |
388 | memcpy(skb_network_header(skb), tmp_hdr, hdr_len); | ||
389 | skb->transport_header = skb->network_header; | ||
386 | __skb_pull(skb, ah_hlen + hdr_len); | 390 | __skb_pull(skb, ah_hlen + hdr_len); |
387 | 391 | ||
388 | kfree(tmp_hdr); | 392 | kfree(tmp_hdr); |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 3b4e8dcf4c86..403eee66b9c5 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -209,7 +209,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | |||
209 | __be16 port, u32 info, u8 *payload) | 209 | __be16 port, u32 info, u8 *payload) |
210 | { | 210 | { |
211 | struct ipv6_pinfo *np = inet6_sk(sk); | 211 | struct ipv6_pinfo *np = inet6_sk(sk); |
212 | struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; | 212 | struct icmp6hdr *icmph = icmp6_hdr(skb); |
213 | struct sock_exterr_skb *serr; | 213 | struct sock_exterr_skb *serr; |
214 | 214 | ||
215 | if (!np->recverr) | 215 | if (!np->recverr) |
@@ -227,11 +227,12 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | |||
227 | serr->ee.ee_pad = 0; | 227 | serr->ee.ee_pad = 0; |
228 | serr->ee.ee_info = info; | 228 | serr->ee.ee_info = info; |
229 | serr->ee.ee_data = 0; | 229 | serr->ee.ee_data = 0; |
230 | serr->addr_offset = (u8*)&(((struct ipv6hdr*)(icmph+1))->daddr) - skb->nh.raw; | 230 | serr->addr_offset = (u8 *)&(((struct ipv6hdr *)(icmph + 1))->daddr) - |
231 | skb_network_header(skb); | ||
231 | serr->port = port; | 232 | serr->port = port; |
232 | 233 | ||
233 | skb->h.raw = payload; | ||
234 | __skb_pull(skb, payload - skb->data); | 234 | __skb_pull(skb, payload - skb->data); |
235 | skb_reset_transport_header(skb); | ||
235 | 236 | ||
236 | if (sock_queue_err_skb(sk, skb)) | 237 | if (sock_queue_err_skb(sk, skb)) |
237 | kfree_skb(skb); | 238 | kfree_skb(skb); |
@@ -251,8 +252,9 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
251 | if (!skb) | 252 | if (!skb) |
252 | return; | 253 | return; |
253 | 254 | ||
254 | iph = (struct ipv6hdr*)skb_put(skb, sizeof(struct ipv6hdr)); | 255 | skb_put(skb, sizeof(struct ipv6hdr)); |
255 | skb->nh.ipv6h = iph; | 256 | skb_reset_network_header(skb); |
257 | iph = ipv6_hdr(skb); | ||
256 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | 258 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); |
257 | 259 | ||
258 | serr = SKB_EXT_ERR(skb); | 260 | serr = SKB_EXT_ERR(skb); |
@@ -263,11 +265,11 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
263 | serr->ee.ee_pad = 0; | 265 | serr->ee.ee_pad = 0; |
264 | serr->ee.ee_info = info; | 266 | serr->ee.ee_info = info; |
265 | serr->ee.ee_data = 0; | 267 | serr->ee.ee_data = 0; |
266 | serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw; | 268 | serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb); |
267 | serr->port = fl->fl_ip_dport; | 269 | serr->port = fl->fl_ip_dport; |
268 | 270 | ||
269 | skb->h.raw = skb->tail; | 271 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); |
270 | __skb_pull(skb, skb->tail - skb->data); | 272 | skb_reset_transport_header(skb); |
271 | 273 | ||
272 | if (sock_queue_err_skb(sk, skb)) | 274 | if (sock_queue_err_skb(sk, skb)) |
273 | kfree_skb(skb); | 275 | kfree_skb(skb); |
@@ -309,21 +311,24 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
309 | 311 | ||
310 | sin = (struct sockaddr_in6 *)msg->msg_name; | 312 | sin = (struct sockaddr_in6 *)msg->msg_name; |
311 | if (sin) { | 313 | if (sin) { |
314 | const unsigned char *nh = skb_network_header(skb); | ||
312 | sin->sin6_family = AF_INET6; | 315 | sin->sin6_family = AF_INET6; |
313 | sin->sin6_flowinfo = 0; | 316 | sin->sin6_flowinfo = 0; |
314 | sin->sin6_port = serr->port; | 317 | sin->sin6_port = serr->port; |
315 | sin->sin6_scope_id = 0; | 318 | sin->sin6_scope_id = 0; |
316 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { | 319 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { |
317 | ipv6_addr_copy(&sin->sin6_addr, | 320 | ipv6_addr_copy(&sin->sin6_addr, |
318 | (struct in6_addr *)(skb->nh.raw + serr->addr_offset)); | 321 | (struct in6_addr *)(nh + serr->addr_offset)); |
319 | if (np->sndflow) | 322 | if (np->sndflow) |
320 | sin->sin6_flowinfo = *(__be32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; | 323 | sin->sin6_flowinfo = |
324 | (*(__be32 *)(nh + serr->addr_offset - 24) & | ||
325 | IPV6_FLOWINFO_MASK); | ||
321 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 326 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
322 | sin->sin6_scope_id = IP6CB(skb)->iif; | 327 | sin->sin6_scope_id = IP6CB(skb)->iif; |
323 | } else { | 328 | } else { |
324 | ipv6_addr_set(&sin->sin6_addr, 0, 0, | 329 | ipv6_addr_set(&sin->sin6_addr, 0, 0, |
325 | htonl(0xffff), | 330 | htonl(0xffff), |
326 | *(__be32*)(skb->nh.raw + serr->addr_offset)); | 331 | *(__be32 *)(nh + serr->addr_offset)); |
327 | } | 332 | } |
328 | } | 333 | } |
329 | 334 | ||
@@ -335,7 +340,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
335 | sin->sin6_flowinfo = 0; | 340 | sin->sin6_flowinfo = 0; |
336 | sin->sin6_scope_id = 0; | 341 | sin->sin6_scope_id = 0; |
337 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { | 342 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { |
338 | ipv6_addr_copy(&sin->sin6_addr, &skb->nh.ipv6h->saddr); | 343 | ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr); |
339 | if (np->rxopt.all) | 344 | if (np->rxopt.all) |
340 | datagram_recv_ctl(sk, msg, skb); | 345 | datagram_recv_ctl(sk, msg, skb); |
341 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 346 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -344,8 +349,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
344 | struct inet_sock *inet = inet_sk(sk); | 349 | struct inet_sock *inet = inet_sk(sk); |
345 | 350 | ||
346 | ipv6_addr_set(&sin->sin6_addr, 0, 0, | 351 | ipv6_addr_set(&sin->sin6_addr, 0, 0, |
347 | htonl(0xffff), | 352 | htonl(0xffff), ip_hdr(skb)->saddr); |
348 | skb->nh.iph->saddr); | ||
349 | if (inet->cmsg_flags) | 353 | if (inet->cmsg_flags) |
350 | ip_cmsg_recv(msg, skb); | 354 | ip_cmsg_recv(msg, skb); |
351 | } | 355 | } |
@@ -381,33 +385,34 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
381 | { | 385 | { |
382 | struct ipv6_pinfo *np = inet6_sk(sk); | 386 | struct ipv6_pinfo *np = inet6_sk(sk); |
383 | struct inet6_skb_parm *opt = IP6CB(skb); | 387 | struct inet6_skb_parm *opt = IP6CB(skb); |
388 | unsigned char *nh = skb_network_header(skb); | ||
384 | 389 | ||
385 | if (np->rxopt.bits.rxinfo) { | 390 | if (np->rxopt.bits.rxinfo) { |
386 | struct in6_pktinfo src_info; | 391 | struct in6_pktinfo src_info; |
387 | 392 | ||
388 | src_info.ipi6_ifindex = opt->iif; | 393 | src_info.ipi6_ifindex = opt->iif; |
389 | ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); | 394 | ipv6_addr_copy(&src_info.ipi6_addr, &ipv6_hdr(skb)->daddr); |
390 | put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); | 395 | put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); |
391 | } | 396 | } |
392 | 397 | ||
393 | if (np->rxopt.bits.rxhlim) { | 398 | if (np->rxopt.bits.rxhlim) { |
394 | int hlim = skb->nh.ipv6h->hop_limit; | 399 | int hlim = ipv6_hdr(skb)->hop_limit; |
395 | put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); | 400 | put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); |
396 | } | 401 | } |
397 | 402 | ||
398 | if (np->rxopt.bits.rxtclass) { | 403 | if (np->rxopt.bits.rxtclass) { |
399 | int tclass = (ntohl(*(__be32 *)skb->nh.ipv6h) >> 20) & 0xff; | 404 | int tclass = (ntohl(*(__be32 *)ipv6_hdr(skb)) >> 20) & 0xff; |
400 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); | 405 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); |
401 | } | 406 | } |
402 | 407 | ||
403 | if (np->rxopt.bits.rxflow && (*(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { | 408 | if (np->rxopt.bits.rxflow && (*(__be32 *)nh & IPV6_FLOWINFO_MASK)) { |
404 | __be32 flowinfo = *(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK; | 409 | __be32 flowinfo = *(__be32 *)nh & IPV6_FLOWINFO_MASK; |
405 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); | 410 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); |
406 | } | 411 | } |
407 | 412 | ||
408 | /* HbH is allowed only once */ | 413 | /* HbH is allowed only once */ |
409 | if (np->rxopt.bits.hopopts && opt->hop) { | 414 | if (np->rxopt.bits.hopopts && opt->hop) { |
410 | u8 *ptr = skb->nh.raw + opt->hop; | 415 | u8 *ptr = nh + opt->hop; |
411 | put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); | 416 | put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); |
412 | } | 417 | } |
413 | 418 | ||
@@ -423,11 +428,11 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
423 | * IPV6_RECVDSTOPTS is more generic. --yoshfuji | 428 | * IPV6_RECVDSTOPTS is more generic. --yoshfuji |
424 | */ | 429 | */ |
425 | unsigned int off = sizeof(struct ipv6hdr); | 430 | unsigned int off = sizeof(struct ipv6hdr); |
426 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | 431 | u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
427 | 432 | ||
428 | while (off <= opt->lastopt) { | 433 | while (off <= opt->lastopt) { |
429 | unsigned len; | 434 | unsigned len; |
430 | u8 *ptr = skb->nh.raw + off; | 435 | u8 *ptr = nh + off; |
431 | 436 | ||
432 | switch(nexthdr) { | 437 | switch(nexthdr) { |
433 | case IPPROTO_DSTOPTS: | 438 | case IPPROTO_DSTOPTS: |
@@ -461,27 +466,27 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
461 | struct in6_pktinfo src_info; | 466 | struct in6_pktinfo src_info; |
462 | 467 | ||
463 | src_info.ipi6_ifindex = opt->iif; | 468 | src_info.ipi6_ifindex = opt->iif; |
464 | ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); | 469 | ipv6_addr_copy(&src_info.ipi6_addr, &ipv6_hdr(skb)->daddr); |
465 | put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); | 470 | put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); |
466 | } | 471 | } |
467 | if (np->rxopt.bits.rxohlim) { | 472 | if (np->rxopt.bits.rxohlim) { |
468 | int hlim = skb->nh.ipv6h->hop_limit; | 473 | int hlim = ipv6_hdr(skb)->hop_limit; |
469 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); | 474 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); |
470 | } | 475 | } |
471 | if (np->rxopt.bits.ohopopts && opt->hop) { | 476 | if (np->rxopt.bits.ohopopts && opt->hop) { |
472 | u8 *ptr = skb->nh.raw + opt->hop; | 477 | u8 *ptr = nh + opt->hop; |
473 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); | 478 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); |
474 | } | 479 | } |
475 | if (np->rxopt.bits.odstopts && opt->dst0) { | 480 | if (np->rxopt.bits.odstopts && opt->dst0) { |
476 | u8 *ptr = skb->nh.raw + opt->dst0; | 481 | u8 *ptr = nh + opt->dst0; |
477 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); | 482 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
478 | } | 483 | } |
479 | if (np->rxopt.bits.osrcrt && opt->srcrt) { | 484 | if (np->rxopt.bits.osrcrt && opt->srcrt) { |
480 | struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt); | 485 | struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(nh + opt->srcrt); |
481 | put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr); | 486 | put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr); |
482 | } | 487 | } |
483 | if (np->rxopt.bits.odstopts && opt->dst1) { | 488 | if (np->rxopt.bits.odstopts && opt->dst1) { |
484 | u8 *ptr = skb->nh.raw + opt->dst1; | 489 | u8 *ptr = nh + opt->dst1; |
485 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); | 490 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
486 | } | 491 | } |
487 | return 0; | 492 | return 0; |
@@ -718,7 +723,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
718 | cmsg->cmsg_type); | 723 | cmsg->cmsg_type); |
719 | err = -EINVAL; | 724 | err = -EINVAL; |
720 | break; | 725 | break; |
721 | }; | 726 | } |
722 | } | 727 | } |
723 | 728 | ||
724 | exit_f: | 729 | exit_f: |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 363e63ffecca..7107bb7e2e62 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -42,21 +42,19 @@ | |||
42 | static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | 42 | static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) |
43 | { | 43 | { |
44 | int err; | 44 | int err; |
45 | int hdr_len; | ||
46 | struct ipv6hdr *top_iph; | 45 | struct ipv6hdr *top_iph; |
47 | struct ipv6_esp_hdr *esph; | 46 | struct ipv6_esp_hdr *esph; |
48 | struct crypto_blkcipher *tfm; | 47 | struct crypto_blkcipher *tfm; |
49 | struct blkcipher_desc desc; | 48 | struct blkcipher_desc desc; |
50 | struct esp_data *esp; | ||
51 | struct sk_buff *trailer; | 49 | struct sk_buff *trailer; |
52 | int blksize; | 50 | int blksize; |
53 | int clen; | 51 | int clen; |
54 | int alen; | 52 | int alen; |
55 | int nfrags; | 53 | int nfrags; |
56 | 54 | u8 *tail; | |
57 | esp = x->data; | 55 | struct esp_data *esp = x->data; |
58 | hdr_len = skb->h.raw - skb->data + | 56 | int hdr_len = (skb_transport_offset(skb) + |
59 | sizeof(*esph) + esp->conf.ivlen; | 57 | sizeof(*esph) + esp->conf.ivlen); |
60 | 58 | ||
61 | /* Strip IP+ESP header. */ | 59 | /* Strip IP+ESP header. */ |
62 | __skb_pull(skb, hdr_len); | 60 | __skb_pull(skb, hdr_len); |
@@ -81,19 +79,20 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
81 | } | 79 | } |
82 | 80 | ||
83 | /* Fill padding... */ | 81 | /* Fill padding... */ |
82 | tail = skb_tail_pointer(trailer); | ||
84 | do { | 83 | do { |
85 | int i; | 84 | int i; |
86 | for (i=0; i<clen-skb->len - 2; i++) | 85 | for (i=0; i<clen-skb->len - 2; i++) |
87 | *(u8*)(trailer->tail + i) = i+1; | 86 | tail[i] = i + 1; |
88 | } while (0); | 87 | } while (0); |
89 | *(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2; | 88 | tail[clen-skb->len - 2] = (clen - skb->len) - 2; |
90 | pskb_put(skb, trailer, clen - skb->len); | 89 | pskb_put(skb, trailer, clen - skb->len); |
91 | 90 | ||
92 | top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len); | 91 | top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len); |
93 | esph = (struct ipv6_esp_hdr *)skb->h.raw; | 92 | esph = (struct ipv6_esp_hdr *)skb_transport_header(skb); |
94 | top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph)); | 93 | top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph)); |
95 | *(u8*)(trailer->tail - 1) = *skb->nh.raw; | 94 | *(skb_tail_pointer(trailer) - 1) = *skb_network_header(skb); |
96 | *skb->nh.raw = IPPROTO_ESP; | 95 | *skb_network_header(skb) = IPPROTO_ESP; |
97 | 96 | ||
98 | esph->spi = x->id.spi; | 97 | esph->spi = x->id.spi; |
99 | esph->seq_no = htonl(++x->replay.oseq); | 98 | esph->seq_no = htonl(++x->replay.oseq); |
@@ -150,8 +149,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
150 | int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); | 149 | int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); |
151 | int alen = esp->auth.icv_trunc_len; | 150 | int alen = esp->auth.icv_trunc_len; |
152 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; | 151 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; |
153 | 152 | int hdr_len = skb_network_header_len(skb); | |
154 | int hdr_len = skb->h.raw - skb->nh.raw; | ||
155 | int nfrags; | 153 | int nfrags; |
156 | int ret = 0; | 154 | int ret = 0; |
157 | 155 | ||
@@ -191,7 +189,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
191 | skb->ip_summed = CHECKSUM_NONE; | 189 | skb->ip_summed = CHECKSUM_NONE; |
192 | 190 | ||
193 | esph = (struct ipv6_esp_hdr*)skb->data; | 191 | esph = (struct ipv6_esp_hdr*)skb->data; |
194 | iph = skb->nh.ipv6h; | 192 | iph = ipv6_hdr(skb); |
195 | 193 | ||
196 | /* Get ivec. This can be wrong, check against another impls. */ | 194 | /* Get ivec. This can be wrong, check against another impls. */ |
197 | if (esp->conf.ivlen) | 195 | if (esp->conf.ivlen) |
@@ -231,28 +229,30 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
231 | ret = nexthdr[1]; | 229 | ret = nexthdr[1]; |
232 | } | 230 | } |
233 | 231 | ||
234 | skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len; | 232 | __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen); |
235 | 233 | skb_set_transport_header(skb, -hdr_len); | |
236 | out: | 234 | out: |
237 | return ret; | 235 | return ret; |
238 | } | 236 | } |
239 | 237 | ||
240 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) | 238 | static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) |
241 | { | 239 | { |
242 | struct esp_data *esp = x->data; | 240 | struct esp_data *esp = x->data; |
243 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); | 241 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
242 | u32 align = max_t(u32, blksize, esp->conf.padlen); | ||
243 | u32 rem; | ||
244 | |||
245 | mtu -= x->props.header_len + esp->auth.icv_trunc_len; | ||
246 | rem = mtu & (align - 1); | ||
247 | mtu &= ~(align - 1); | ||
244 | 248 | ||
245 | if (x->props.mode == XFRM_MODE_TUNNEL) { | 249 | if (x->props.mode != XFRM_MODE_TUNNEL) { |
246 | mtu = ALIGN(mtu + 2, blksize); | ||
247 | } else { | ||
248 | /* The worst case. */ | ||
249 | u32 padsize = ((blksize - 1) & 7) + 1; | 250 | u32 padsize = ((blksize - 1) & 7) + 1; |
250 | mtu = ALIGN(mtu + 2, padsize) + blksize - padsize; | 251 | mtu -= blksize - padsize; |
252 | mtu += min_t(u32, blksize - padsize, rem); | ||
251 | } | 253 | } |
252 | if (esp->conf.padlen) | ||
253 | mtu = ALIGN(mtu, esp->conf.padlen); | ||
254 | 254 | ||
255 | return mtu + x->props.header_len + esp->auth.icv_trunc_len; | 255 | return mtu - 2; |
256 | } | 256 | } |
257 | 257 | ||
258 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 258 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
@@ -382,7 +382,7 @@ static struct xfrm_type esp6_type = | |||
382 | .proto = IPPROTO_ESP, | 382 | .proto = IPPROTO_ESP, |
383 | .init_state = esp6_init_state, | 383 | .init_state = esp6_init_state, |
384 | .destructor = esp6_destroy, | 384 | .destructor = esp6_destroy, |
385 | .get_max_size = esp6_get_max_size, | 385 | .get_mtu = esp6_get_mtu, |
386 | .input = esp6_input, | 386 | .input = esp6_input, |
387 | .output = esp6_output, | 387 | .output = esp6_output, |
388 | .hdr_offset = xfrm6_find_1stfragopt, | 388 | .hdr_offset = xfrm6_find_1stfragopt, |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index fb39604c3d09..6d8e4ac7bdad 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -50,13 +50,14 @@ | |||
50 | 50 | ||
51 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | 51 | int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) |
52 | { | 52 | { |
53 | int packet_len = skb->tail - skb->nh.raw; | 53 | const unsigned char *nh = skb_network_header(skb); |
54 | int packet_len = skb->tail - skb->network_header; | ||
54 | struct ipv6_opt_hdr *hdr; | 55 | struct ipv6_opt_hdr *hdr; |
55 | int len; | 56 | int len; |
56 | 57 | ||
57 | if (offset + 2 > packet_len) | 58 | if (offset + 2 > packet_len) |
58 | goto bad; | 59 | goto bad; |
59 | hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 60 | hdr = (struct ipv6_opt_hdr *)(nh + offset); |
60 | len = ((hdr->hdrlen + 1) << 3); | 61 | len = ((hdr->hdrlen + 1) << 3); |
61 | 62 | ||
62 | if (offset + len > packet_len) | 63 | if (offset + len > packet_len) |
@@ -66,7 +67,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
66 | len -= 2; | 67 | len -= 2; |
67 | 68 | ||
68 | while (len > 0) { | 69 | while (len > 0) { |
69 | int opttype = skb->nh.raw[offset]; | 70 | int opttype = nh[offset]; |
70 | int optlen; | 71 | int optlen; |
71 | 72 | ||
72 | if (opttype == type) | 73 | if (opttype == type) |
@@ -77,7 +78,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) | |||
77 | optlen = 1; | 78 | optlen = 1; |
78 | break; | 79 | break; |
79 | default: | 80 | default: |
80 | optlen = skb->nh.raw[offset + 1] + 2; | 81 | optlen = nh[offset + 1] + 2; |
81 | if (optlen > len) | 82 | if (optlen > len) |
82 | goto bad; | 83 | goto bad; |
83 | break; | 84 | break; |
@@ -113,7 +114,7 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | |||
113 | { | 114 | { |
114 | struct sk_buff *skb = *skbp; | 115 | struct sk_buff *skb = *skbp; |
115 | 116 | ||
116 | switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { | 117 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { |
117 | case 0: /* ignore */ | 118 | case 0: /* ignore */ |
118 | return 1; | 119 | return 1; |
119 | 120 | ||
@@ -124,12 +125,12 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | |||
124 | /* Actually, it is redundant check. icmp_send | 125 | /* Actually, it is redundant check. icmp_send |
125 | will recheck in any case. | 126 | will recheck in any case. |
126 | */ | 127 | */ |
127 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) | 128 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) |
128 | break; | 129 | break; |
129 | case 2: /* send ICMP PARM PROB regardless and drop packet */ | 130 | case 2: /* send ICMP PARM PROB regardless and drop packet */ |
130 | icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff); | 131 | icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff); |
131 | return 0; | 132 | return 0; |
132 | }; | 133 | } |
133 | 134 | ||
134 | kfree_skb(skb); | 135 | kfree_skb(skb); |
135 | return 0; | 136 | return 0; |
@@ -141,19 +142,20 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
141 | { | 142 | { |
142 | struct sk_buff *skb = *skbp; | 143 | struct sk_buff *skb = *skbp; |
143 | struct tlvtype_proc *curr; | 144 | struct tlvtype_proc *curr; |
144 | int off = skb->h.raw - skb->nh.raw; | 145 | const unsigned char *nh = skb_network_header(skb); |
145 | int len = ((skb->h.raw[1]+1)<<3); | 146 | int off = skb_network_header_len(skb); |
147 | int len = (skb_transport_header(skb)[1] + 1) << 3; | ||
146 | 148 | ||
147 | if ((skb->h.raw + len) - skb->data > skb_headlen(skb)) | 149 | if (skb_transport_offset(skb) + len > skb_headlen(skb)) |
148 | goto bad; | 150 | goto bad; |
149 | 151 | ||
150 | off += 2; | 152 | off += 2; |
151 | len -= 2; | 153 | len -= 2; |
152 | 154 | ||
153 | while (len > 0) { | 155 | while (len > 0) { |
154 | int optlen = skb->nh.raw[off+1]+2; | 156 | int optlen = nh[off + 1] + 2; |
155 | 157 | ||
156 | switch (skb->nh.raw[off]) { | 158 | switch (nh[off]) { |
157 | case IPV6_TLV_PAD0: | 159 | case IPV6_TLV_PAD0: |
158 | optlen = 1; | 160 | optlen = 1; |
159 | break; | 161 | break; |
@@ -165,7 +167,7 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
165 | if (optlen > len) | 167 | if (optlen > len) |
166 | goto bad; | 168 | goto bad; |
167 | for (curr=procs; curr->type >= 0; curr++) { | 169 | for (curr=procs; curr->type >= 0; curr++) { |
168 | if (curr->type == skb->nh.raw[off]) { | 170 | if (curr->type == nh[off]) { |
169 | /* type specific length/alignment | 171 | /* type specific length/alignment |
170 | checks will be performed in the | 172 | checks will be performed in the |
171 | func(). */ | 173 | func(). */ |
@@ -200,7 +202,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
200 | struct sk_buff *skb = *skbp; | 202 | struct sk_buff *skb = *skbp; |
201 | struct ipv6_destopt_hao *hao; | 203 | struct ipv6_destopt_hao *hao; |
202 | struct inet6_skb_parm *opt = IP6CB(skb); | 204 | struct inet6_skb_parm *opt = IP6CB(skb); |
203 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw; | 205 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
204 | struct in6_addr tmp_addr; | 206 | struct in6_addr tmp_addr; |
205 | int ret; | 207 | int ret; |
206 | 208 | ||
@@ -211,7 +213,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
211 | opt->dsthao = opt->dst1; | 213 | opt->dsthao = opt->dst1; |
212 | opt->dst1 = 0; | 214 | opt->dst1 = 0; |
213 | 215 | ||
214 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff); | 216 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff); |
215 | 217 | ||
216 | if (hao->length != 16) { | 218 | if (hao->length != 16) { |
217 | LIMIT_NETDEBUG( | 219 | LIMIT_NETDEBUG( |
@@ -244,8 +246,9 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
244 | 246 | ||
245 | /* update all variable using below by copied skbuff */ | 247 | /* update all variable using below by copied skbuff */ |
246 | *skbp = skb = skb2; | 248 | *skbp = skb = skb2; |
247 | hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff); | 249 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) + |
248 | ipv6h = (struct ipv6hdr *)skb2->nh.raw; | 250 | optoff); |
251 | ipv6h = ipv6_hdr(skb2); | ||
249 | } | 252 | } |
250 | 253 | ||
251 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 254 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
@@ -255,7 +258,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
255 | ipv6_addr_copy(&ipv6h->saddr, &hao->addr); | 258 | ipv6_addr_copy(&ipv6h->saddr, &hao->addr); |
256 | ipv6_addr_copy(&hao->addr, &tmp_addr); | 259 | ipv6_addr_copy(&hao->addr, &tmp_addr); |
257 | 260 | ||
258 | if (skb->tstamp.off_sec == 0) | 261 | if (skb->tstamp.tv64 == 0) |
259 | __net_timestamp(skb); | 262 | __net_timestamp(skb); |
260 | 263 | ||
261 | return 1; | 264 | return 1; |
@@ -285,16 +288,16 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
285 | #endif | 288 | #endif |
286 | struct dst_entry *dst; | 289 | struct dst_entry *dst; |
287 | 290 | ||
288 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 291 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
289 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 292 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
293 | ((skb_transport_header(skb)[1] + 1) << 3)))) { | ||
290 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 294 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
291 | IPSTATS_MIB_INHDRERRORS); | 295 | IPSTATS_MIB_INHDRERRORS); |
292 | kfree_skb(skb); | 296 | kfree_skb(skb); |
293 | return -1; | 297 | return -1; |
294 | } | 298 | } |
295 | 299 | ||
296 | opt->lastopt = skb->h.raw - skb->nh.raw; | 300 | opt->lastopt = opt->dst1 = skb_network_header_len(skb); |
297 | opt->dst1 = skb->h.raw - skb->nh.raw; | ||
298 | #ifdef CONFIG_IPV6_MIP6 | 301 | #ifdef CONFIG_IPV6_MIP6 |
299 | dstbuf = opt->dst1; | 302 | dstbuf = opt->dst1; |
300 | #endif | 303 | #endif |
@@ -303,7 +306,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
303 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { | 306 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { |
304 | dst_release(dst); | 307 | dst_release(dst); |
305 | skb = *skbp; | 308 | skb = *skbp; |
306 | skb->h.raw += ((skb->h.raw[1]+1)<<3); | 309 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
307 | opt = IP6CB(skb); | 310 | opt = IP6CB(skb); |
308 | #ifdef CONFIG_IPV6_MIP6 | 311 | #ifdef CONFIG_IPV6_MIP6 |
309 | opt->nhoff = dstbuf; | 312 | opt->nhoff = dstbuf; |
@@ -384,18 +387,20 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
384 | 387 | ||
385 | in6_dev_put(idev); | 388 | in6_dev_put(idev); |
386 | 389 | ||
387 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 390 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
388 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 391 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
392 | ((skb_transport_header(skb)[1] + 1) << 3)))) { | ||
389 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 393 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
390 | IPSTATS_MIB_INHDRERRORS); | 394 | IPSTATS_MIB_INHDRERRORS); |
391 | kfree_skb(skb); | 395 | kfree_skb(skb); |
392 | return -1; | 396 | return -1; |
393 | } | 397 | } |
394 | 398 | ||
395 | hdr = (struct ipv6_rt_hdr *) skb->h.raw; | 399 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); |
396 | 400 | ||
397 | switch (hdr->type) { | 401 | switch (hdr->type) { |
398 | #ifdef CONFIG_IPV6_MIP6 | 402 | #ifdef CONFIG_IPV6_MIP6 |
403 | case IPV6_SRCRT_TYPE_2: | ||
399 | break; | 404 | break; |
400 | #endif | 405 | #endif |
401 | case IPV6_SRCRT_TYPE_0: | 406 | case IPV6_SRCRT_TYPE_0: |
@@ -406,11 +411,12 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
406 | default: | 411 | default: |
407 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 412 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
408 | IPSTATS_MIB_INHDRERRORS); | 413 | IPSTATS_MIB_INHDRERRORS); |
409 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | 414 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
415 | (&hdr->type) - skb_network_header(skb)); | ||
410 | return -1; | 416 | return -1; |
411 | } | 417 | } |
412 | 418 | ||
413 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || | 419 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || |
414 | skb->pkt_type != PACKET_HOST) { | 420 | skb->pkt_type != PACKET_HOST) { |
415 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 421 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
416 | IPSTATS_MIB_INADDRERRORS); | 422 | IPSTATS_MIB_INADDRERRORS); |
@@ -438,12 +444,11 @@ looped_back: | |||
438 | break; | 444 | break; |
439 | } | 445 | } |
440 | 446 | ||
441 | opt->lastopt = skb->h.raw - skb->nh.raw; | 447 | opt->lastopt = opt->srcrt = skb_network_header_len(skb); |
442 | opt->srcrt = skb->h.raw - skb->nh.raw; | 448 | skb->transport_header += (hdr->hdrlen + 1) << 3; |
443 | skb->h.raw += (hdr->hdrlen + 1) << 3; | ||
444 | opt->dst0 = opt->dst1; | 449 | opt->dst0 = opt->dst1; |
445 | opt->dst1 = 0; | 450 | opt->dst1 = 0; |
446 | opt->nhoff = (&hdr->nexthdr) - skb->nh.raw; | 451 | opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb); |
447 | return 1; | 452 | return 1; |
448 | } | 453 | } |
449 | 454 | ||
@@ -452,7 +457,9 @@ looped_back: | |||
452 | if (hdr->hdrlen & 0x01) { | 457 | if (hdr->hdrlen & 0x01) { |
453 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 458 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
454 | IPSTATS_MIB_INHDRERRORS); | 459 | IPSTATS_MIB_INHDRERRORS); |
455 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); | 460 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
461 | ((&hdr->hdrlen) - | ||
462 | skb_network_header(skb))); | ||
456 | return -1; | 463 | return -1; |
457 | } | 464 | } |
458 | break; | 465 | break; |
@@ -479,7 +486,9 @@ looped_back: | |||
479 | if (hdr->segments_left > n) { | 486 | if (hdr->segments_left > n) { |
480 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 487 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
481 | IPSTATS_MIB_INHDRERRORS); | 488 | IPSTATS_MIB_INHDRERRORS); |
482 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); | 489 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
490 | ((&hdr->segments_left) - | ||
491 | skb_network_header(skb))); | ||
483 | return -1; | 492 | return -1; |
484 | } | 493 | } |
485 | 494 | ||
@@ -498,7 +507,7 @@ looped_back: | |||
498 | kfree_skb(skb); | 507 | kfree_skb(skb); |
499 | *skbp = skb = skb2; | 508 | *skbp = skb = skb2; |
500 | opt = IP6CB(skb2); | 509 | opt = IP6CB(skb2); |
501 | hdr = (struct ipv6_rt_hdr *) skb2->h.raw; | 510 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2); |
502 | } | 511 | } |
503 | 512 | ||
504 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 513 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
@@ -514,7 +523,7 @@ looped_back: | |||
514 | #ifdef CONFIG_IPV6_MIP6 | 523 | #ifdef CONFIG_IPV6_MIP6 |
515 | case IPV6_SRCRT_TYPE_2: | 524 | case IPV6_SRCRT_TYPE_2: |
516 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, | 525 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, |
517 | (xfrm_address_t *)&skb->nh.ipv6h->saddr, | 526 | (xfrm_address_t *)&ipv6_hdr(skb)->saddr, |
518 | IPPROTO_ROUTING) < 0) { | 527 | IPPROTO_ROUTING) < 0) { |
519 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 528 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
520 | IPSTATS_MIB_INADDRERRORS); | 529 | IPSTATS_MIB_INADDRERRORS); |
@@ -541,19 +550,19 @@ looped_back: | |||
541 | } | 550 | } |
542 | 551 | ||
543 | ipv6_addr_copy(&daddr, addr); | 552 | ipv6_addr_copy(&daddr, addr); |
544 | ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr); | 553 | ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr); |
545 | ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr); | 554 | ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr); |
546 | 555 | ||
547 | dst_release(xchg(&skb->dst, NULL)); | 556 | dst_release(xchg(&skb->dst, NULL)); |
548 | ip6_route_input(skb); | 557 | ip6_route_input(skb); |
549 | if (skb->dst->error) { | 558 | if (skb->dst->error) { |
550 | skb_push(skb, skb->data - skb->nh.raw); | 559 | skb_push(skb, skb->data - skb_network_header(skb)); |
551 | dst_input(skb); | 560 | dst_input(skb); |
552 | return -1; | 561 | return -1; |
553 | } | 562 | } |
554 | 563 | ||
555 | if (skb->dst->dev->flags&IFF_LOOPBACK) { | 564 | if (skb->dst->dev->flags&IFF_LOOPBACK) { |
556 | if (skb->nh.ipv6h->hop_limit <= 1) { | 565 | if (ipv6_hdr(skb)->hop_limit <= 1) { |
557 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 566 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
558 | IPSTATS_MIB_INHDRERRORS); | 567 | IPSTATS_MIB_INHDRERRORS); |
559 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 568 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, |
@@ -561,11 +570,11 @@ looped_back: | |||
561 | kfree_skb(skb); | 570 | kfree_skb(skb); |
562 | return -1; | 571 | return -1; |
563 | } | 572 | } |
564 | skb->nh.ipv6h->hop_limit--; | 573 | ipv6_hdr(skb)->hop_limit--; |
565 | goto looped_back; | 574 | goto looped_back; |
566 | } | 575 | } |
567 | 576 | ||
568 | skb_push(skb, skb->data - skb->nh.raw); | 577 | skb_push(skb, skb->data - skb_network_header(skb)); |
569 | dst_input(skb); | 578 | dst_input(skb); |
570 | return -1; | 579 | return -1; |
571 | } | 580 | } |
@@ -656,13 +665,14 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); | |||
656 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 665 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) |
657 | { | 666 | { |
658 | struct sk_buff *skb = *skbp; | 667 | struct sk_buff *skb = *skbp; |
668 | const unsigned char *nh = skb_network_header(skb); | ||
659 | 669 | ||
660 | if (skb->nh.raw[optoff+1] == 2) { | 670 | if (nh[optoff + 1] == 2) { |
661 | IP6CB(skb)->ra = optoff; | 671 | IP6CB(skb)->ra = optoff; |
662 | return 1; | 672 | return 1; |
663 | } | 673 | } |
664 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", | 674 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", |
665 | skb->nh.raw[optoff+1]); | 675 | nh[optoff + 1]); |
666 | kfree_skb(skb); | 676 | kfree_skb(skb); |
667 | return 0; | 677 | return 0; |
668 | } | 678 | } |
@@ -672,23 +682,24 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | |||
672 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | 682 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) |
673 | { | 683 | { |
674 | struct sk_buff *skb = *skbp; | 684 | struct sk_buff *skb = *skbp; |
685 | const unsigned char *nh = skb_network_header(skb); | ||
675 | u32 pkt_len; | 686 | u32 pkt_len; |
676 | 687 | ||
677 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 688 | if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { |
678 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", | 689 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", |
679 | skb->nh.raw[optoff+1]); | 690 | nh[optoff+1]); |
680 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 691 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
681 | IPSTATS_MIB_INHDRERRORS); | 692 | IPSTATS_MIB_INHDRERRORS); |
682 | goto drop; | 693 | goto drop; |
683 | } | 694 | } |
684 | 695 | ||
685 | pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); | 696 | pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); |
686 | if (pkt_len <= IPV6_MAXPLEN) { | 697 | if (pkt_len <= IPV6_MAXPLEN) { |
687 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | 698 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
688 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); | 699 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); |
689 | return 0; | 700 | return 0; |
690 | } | 701 | } |
691 | if (skb->nh.ipv6h->payload_len) { | 702 | if (ipv6_hdr(skb)->payload_len) { |
692 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | 703 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
693 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); | 704 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); |
694 | return 0; | 705 | return 0; |
@@ -727,13 +738,14 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) | |||
727 | struct inet6_skb_parm *opt = IP6CB(skb); | 738 | struct inet6_skb_parm *opt = IP6CB(skb); |
728 | 739 | ||
729 | /* | 740 | /* |
730 | * skb->nh.raw is equal to skb->data, and | 741 | * skb_network_header(skb) is equal to skb->data, and |
731 | * skb->h.raw - skb->nh.raw is always equal to | 742 | * skb_network_header_len(skb) is always equal to |
732 | * sizeof(struct ipv6hdr) by definition of | 743 | * sizeof(struct ipv6hdr) by definition of |
733 | * hop-by-hop options. | 744 | * hop-by-hop options. |
734 | */ | 745 | */ |
735 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || | 746 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || |
736 | !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) { | 747 | !pskb_may_pull(skb, (sizeof(struct ipv6hdr) + |
748 | ((skb_transport_header(skb)[1] + 1) << 3)))) { | ||
737 | kfree_skb(skb); | 749 | kfree_skb(skb); |
738 | return -1; | 750 | return -1; |
739 | } | 751 | } |
@@ -741,7 +753,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) | |||
741 | opt->hop = sizeof(struct ipv6hdr); | 753 | opt->hop = sizeof(struct ipv6hdr); |
742 | if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { | 754 | if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { |
743 | skb = *skbp; | 755 | skb = *skbp; |
744 | skb->h.raw += (skb->h.raw[1]+1)<<3; | 756 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
745 | opt = IP6CB(skb); | 757 | opt = IP6CB(skb); |
746 | opt->nhoff = sizeof(struct ipv6hdr); | 758 | opt->nhoff = sizeof(struct ipv6hdr); |
747 | return 1; | 759 | return 1; |
@@ -810,6 +822,8 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, | |||
810 | ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); | 822 | ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); |
811 | } | 823 | } |
812 | 824 | ||
825 | EXPORT_SYMBOL(ipv6_push_nfrag_opts); | ||
826 | |||
813 | void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto) | 827 | void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto) |
814 | { | 828 | { |
815 | if (opt->dst1opt) | 829 | if (opt->dst1opt) |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index ea3035b4e3e8..fc3882c90604 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <net/fib_rules.h> | 18 | #include <net/fib_rules.h> |
19 | #include <net/ipv6.h> | 19 | #include <net/ipv6.h> |
20 | #include <net/addrconf.h> | ||
20 | #include <net/ip6_route.h> | 21 | #include <net/ip6_route.h> |
21 | #include <net/netlink.h> | 22 | #include <net/netlink.h> |
22 | 23 | ||
@@ -95,8 +96,27 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
95 | if (table) | 96 | if (table) |
96 | rt = lookup(table, flp, flags); | 97 | rt = lookup(table, flp, flags); |
97 | 98 | ||
98 | if (rt != &ip6_null_entry) | 99 | if (rt != &ip6_null_entry) { |
100 | struct fib6_rule *r = (struct fib6_rule *)rule; | ||
101 | |||
102 | /* | ||
103 | * If we need to find a source address for this traffic, | ||
104 | * we check the result if it meets requirement of the rule. | ||
105 | */ | ||
106 | if ((rule->flags & FIB_RULE_FIND_SADDR) && | ||
107 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { | ||
108 | struct in6_addr saddr; | ||
109 | if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst, | ||
110 | &saddr)) | ||
111 | goto again; | ||
112 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | ||
113 | r->src.plen)) | ||
114 | goto again; | ||
115 | ipv6_addr_copy(&flp->fl6_src, &saddr); | ||
116 | } | ||
99 | goto out; | 117 | goto out; |
118 | } | ||
119 | again: | ||
100 | dst_release(&rt->u.dst); | 120 | dst_release(&rt->u.dst); |
101 | rt = NULL; | 121 | rt = NULL; |
102 | goto out; | 122 | goto out; |
@@ -117,9 +137,17 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
117 | !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) | 137 | !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) |
118 | return 0; | 138 | return 0; |
119 | 139 | ||
140 | /* | ||
141 | * If FIB_RULE_FIND_SADDR is set and we do not have a | ||
142 | * source address for the traffic, we defer check for | ||
143 | * source address. | ||
144 | */ | ||
120 | if (r->src.plen) { | 145 | if (r->src.plen) { |
121 | if (!(flags & RT6_LOOKUP_F_HAS_SADDR) || | 146 | if (flags & RT6_LOOKUP_F_HAS_SADDR) { |
122 | !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) | 147 | if (!ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, |
148 | r->src.plen)) | ||
149 | return 0; | ||
150 | } else if (!(r->common.flags & FIB_RULE_FIND_SADDR)) | ||
123 | return 0; | 151 | return 0; |
124 | } | 152 | } |
125 | 153 | ||
@@ -216,11 +244,6 @@ nla_put_failure: | |||
216 | return -ENOBUFS; | 244 | return -ENOBUFS; |
217 | } | 245 | } |
218 | 246 | ||
219 | int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
220 | { | ||
221 | return fib_rules_dump(skb, cb, AF_INET6); | ||
222 | } | ||
223 | |||
224 | static u32 fib6_rule_default_pref(void) | 247 | static u32 fib6_rule_default_pref(void) |
225 | { | 248 | { |
226 | return 0x3FFF; | 249 | return 0x3FFF; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index edfe98bf64c3..e9bcce9e7bdf 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <asm/system.h> | 68 | #include <asm/system.h> |
69 | 69 | ||
70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; | 70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; |
71 | EXPORT_SYMBOL(icmpv6_statistics); | ||
71 | 72 | ||
72 | /* | 73 | /* |
73 | * The ICMP socket(s). This is the most convenient way to flow control | 74 | * The ICMP socket(s). This is the most convenient way to flow control |
@@ -128,9 +129,9 @@ void icmpv6_param_prob(struct sk_buff *skb, int code, int pos) | |||
128 | 129 | ||
129 | static int is_ineligible(struct sk_buff *skb) | 130 | static int is_ineligible(struct sk_buff *skb) |
130 | { | 131 | { |
131 | int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data; | 132 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
132 | int len = skb->len - ptr; | 133 | int len = skb->len - ptr; |
133 | __u8 nexthdr = skb->nh.ipv6h->nexthdr; | 134 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
134 | 135 | ||
135 | if (len < 0) | 136 | if (len < 0) |
136 | return 1; | 137 | return 1; |
@@ -205,7 +206,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) | |||
205 | { | 206 | { |
206 | u8 _optval, *op; | 207 | u8 _optval, *op; |
207 | 208 | ||
208 | offset += skb->nh.raw - skb->data; | 209 | offset += skb_network_offset(skb); |
209 | op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval); | 210 | op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval); |
210 | if (op == NULL) | 211 | if (op == NULL) |
211 | return 1; | 212 | return 1; |
@@ -221,7 +222,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
221 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) | 222 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) |
222 | goto out; | 223 | goto out; |
223 | 224 | ||
224 | icmp6h = (struct icmp6hdr*) skb->h.raw; | 225 | icmp6h = icmp6_hdr(skb); |
225 | memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); | 226 | memcpy(icmp6h, thdr, sizeof(struct icmp6hdr)); |
226 | icmp6h->icmp6_cksum = 0; | 227 | icmp6h->icmp6_cksum = 0; |
227 | 228 | ||
@@ -274,7 +275,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st | |||
274 | #ifdef CONFIG_IPV6_MIP6 | 275 | #ifdef CONFIG_IPV6_MIP6 |
275 | static void mip6_addr_swap(struct sk_buff *skb) | 276 | static void mip6_addr_swap(struct sk_buff *skb) |
276 | { | 277 | { |
277 | struct ipv6hdr *iph = skb->nh.ipv6h; | 278 | struct ipv6hdr *iph = ipv6_hdr(skb); |
278 | struct inet6_skb_parm *opt = IP6CB(skb); | 279 | struct inet6_skb_parm *opt = IP6CB(skb); |
279 | struct ipv6_destopt_hao *hao; | 280 | struct ipv6_destopt_hao *hao; |
280 | struct in6_addr tmp; | 281 | struct in6_addr tmp; |
@@ -283,7 +284,8 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
283 | if (opt->dsthao) { | 284 | if (opt->dsthao) { |
284 | off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); | 285 | off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); |
285 | if (likely(off >= 0)) { | 286 | if (likely(off >= 0)) { |
286 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off); | 287 | hao = (struct ipv6_destopt_hao *) |
288 | (skb_network_header(skb) + off); | ||
287 | ipv6_addr_copy(&tmp, &iph->saddr); | 289 | ipv6_addr_copy(&tmp, &iph->saddr); |
288 | ipv6_addr_copy(&iph->saddr, &hao->addr); | 290 | ipv6_addr_copy(&iph->saddr, &hao->addr); |
289 | ipv6_addr_copy(&hao->addr, &tmp); | 291 | ipv6_addr_copy(&hao->addr, &tmp); |
@@ -301,7 +303,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
301 | struct net_device *dev) | 303 | struct net_device *dev) |
302 | { | 304 | { |
303 | struct inet6_dev *idev = NULL; | 305 | struct inet6_dev *idev = NULL; |
304 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 306 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
305 | struct sock *sk; | 307 | struct sock *sk; |
306 | struct ipv6_pinfo *np; | 308 | struct ipv6_pinfo *np; |
307 | struct in6_addr *saddr = NULL; | 309 | struct in6_addr *saddr = NULL; |
@@ -315,7 +317,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
315 | int hlimit, tclass; | 317 | int hlimit, tclass; |
316 | int err = 0; | 318 | int err = 0; |
317 | 319 | ||
318 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) | 320 | if ((u8 *)hdr < skb->head || |
321 | (skb->network_header + sizeof(*hdr)) > skb->tail) | ||
319 | return; | 322 | return; |
320 | 323 | ||
321 | /* | 324 | /* |
@@ -430,7 +433,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
430 | tclass = 0; | 433 | tclass = 0; |
431 | 434 | ||
432 | msg.skb = skb; | 435 | msg.skb = skb; |
433 | msg.offset = skb->nh.raw - skb->data; | 436 | msg.offset = skb_network_offset(skb); |
434 | msg.type = type; | 437 | msg.type = type; |
435 | 438 | ||
436 | len = skb->len - msg.offset; | 439 | len = skb->len - msg.offset; |
@@ -466,13 +469,15 @@ out: | |||
466 | icmpv6_xmit_unlock(); | 469 | icmpv6_xmit_unlock(); |
467 | } | 470 | } |
468 | 471 | ||
472 | EXPORT_SYMBOL(icmpv6_send); | ||
473 | |||
469 | static void icmpv6_echo_reply(struct sk_buff *skb) | 474 | static void icmpv6_echo_reply(struct sk_buff *skb) |
470 | { | 475 | { |
471 | struct sock *sk; | 476 | struct sock *sk; |
472 | struct inet6_dev *idev; | 477 | struct inet6_dev *idev; |
473 | struct ipv6_pinfo *np; | 478 | struct ipv6_pinfo *np; |
474 | struct in6_addr *saddr = NULL; | 479 | struct in6_addr *saddr = NULL; |
475 | struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw; | 480 | struct icmp6hdr *icmph = icmp6_hdr(skb); |
476 | struct icmp6hdr tmp_hdr; | 481 | struct icmp6hdr tmp_hdr; |
477 | struct flowi fl; | 482 | struct flowi fl; |
478 | struct icmpv6_msg msg; | 483 | struct icmpv6_msg msg; |
@@ -481,7 +486,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
481 | int hlimit; | 486 | int hlimit; |
482 | int tclass; | 487 | int tclass; |
483 | 488 | ||
484 | saddr = &skb->nh.ipv6h->daddr; | 489 | saddr = &ipv6_hdr(skb)->daddr; |
485 | 490 | ||
486 | if (!ipv6_unicast_destination(skb)) | 491 | if (!ipv6_unicast_destination(skb)) |
487 | saddr = NULL; | 492 | saddr = NULL; |
@@ -491,7 +496,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
491 | 496 | ||
492 | memset(&fl, 0, sizeof(fl)); | 497 | memset(&fl, 0, sizeof(fl)); |
493 | fl.proto = IPPROTO_ICMPV6; | 498 | fl.proto = IPPROTO_ICMPV6; |
494 | ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr); | 499 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
495 | if (saddr) | 500 | if (saddr) |
496 | ipv6_addr_copy(&fl.fl6_src, saddr); | 501 | ipv6_addr_copy(&fl.fl6_src, saddr); |
497 | fl.oif = skb->dev->ifindex; | 502 | fl.oif = skb->dev->ifindex; |
@@ -579,8 +584,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
579 | if (!pskb_may_pull(skb, inner_offset+8)) | 584 | if (!pskb_may_pull(skb, inner_offset+8)) |
580 | return; | 585 | return; |
581 | 586 | ||
582 | saddr = &skb->nh.ipv6h->saddr; | 587 | saddr = &ipv6_hdr(skb)->saddr; |
583 | daddr = &skb->nh.ipv6h->daddr; | 588 | daddr = &ipv6_hdr(skb)->daddr; |
584 | 589 | ||
585 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 590 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
586 | Without this we will not able f.e. to make source routed | 591 | Without this we will not able f.e. to make source routed |
@@ -624,8 +629,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
624 | 629 | ||
625 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); | 630 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); |
626 | 631 | ||
627 | saddr = &skb->nh.ipv6h->saddr; | 632 | saddr = &ipv6_hdr(skb)->saddr; |
628 | daddr = &skb->nh.ipv6h->daddr; | 633 | daddr = &ipv6_hdr(skb)->daddr; |
629 | 634 | ||
630 | /* Perform checksum. */ | 635 | /* Perform checksum. */ |
631 | switch (skb->ip_summed) { | 636 | switch (skb->ip_summed) { |
@@ -647,7 +652,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
647 | if (!pskb_pull(skb, sizeof(struct icmp6hdr))) | 652 | if (!pskb_pull(skb, sizeof(struct icmp6hdr))) |
648 | goto discard_it; | 653 | goto discard_it; |
649 | 654 | ||
650 | hdr = (struct icmp6hdr *) skb->h.raw; | 655 | hdr = icmp6_hdr(skb); |
651 | 656 | ||
652 | type = hdr->icmp6_type; | 657 | type = hdr->icmp6_type; |
653 | 658 | ||
@@ -673,7 +678,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
673 | */ | 678 | */ |
674 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 679 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
675 | goto discard_it; | 680 | goto discard_it; |
676 | hdr = (struct icmp6hdr *) skb->h.raw; | 681 | hdr = icmp6_hdr(skb); |
677 | orig_hdr = (struct ipv6hdr *) (hdr + 1); | 682 | orig_hdr = (struct ipv6hdr *) (hdr + 1); |
678 | rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, | 683 | rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, |
679 | ntohl(hdr->icmp6_mtu)); | 684 | ntohl(hdr->icmp6_mtu)); |
@@ -727,7 +732,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
727 | */ | 732 | */ |
728 | 733 | ||
729 | icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); | 734 | icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); |
730 | }; | 735 | } |
736 | |||
731 | kfree_skb(skb); | 737 | kfree_skb(skb); |
732 | return 0; | 738 | return 0; |
733 | 739 | ||
@@ -860,11 +866,13 @@ int icmpv6_err_convert(int type, int code, int *err) | |||
860 | case ICMPV6_TIME_EXCEED: | 866 | case ICMPV6_TIME_EXCEED: |
861 | *err = EHOSTUNREACH; | 867 | *err = EHOSTUNREACH; |
862 | break; | 868 | break; |
863 | }; | 869 | } |
864 | 870 | ||
865 | return fatal; | 871 | return fatal; |
866 | } | 872 | } |
867 | 873 | ||
874 | EXPORT_SYMBOL(icmpv6_err_convert); | ||
875 | |||
868 | #ifdef CONFIG_SYSCTL | 876 | #ifdef CONFIG_SYSCTL |
869 | ctl_table ipv6_icmp_table[] = { | 877 | ctl_table ipv6_icmp_table[] = { |
870 | { | 878 | { |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 268f476ef3db..ca08ee88d07f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -359,7 +359,7 @@ end: | |||
359 | return res; | 359 | return res; |
360 | } | 360 | } |
361 | 361 | ||
362 | int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | 362 | static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) |
363 | { | 363 | { |
364 | unsigned int h, s_h; | 364 | unsigned int h, s_h; |
365 | unsigned int e = 0, s_e; | 365 | unsigned int e = 0, s_e; |
@@ -1486,6 +1486,8 @@ void __init fib6_init(void) | |||
1486 | NULL, NULL); | 1486 | NULL, NULL); |
1487 | 1487 | ||
1488 | fib6_tables_init(); | 1488 | fib6_tables_init(); |
1489 | |||
1490 | __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); | ||
1489 | } | 1491 | } |
1490 | 1492 | ||
1491 | void fib6_gc_cleanup(void) | 1493 | void fib6_gc_cleanup(void) |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 61e7a6c8141d..be0ee8a34f9b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -96,12 +96,12 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
96 | if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) | 96 | if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) |
97 | goto err; | 97 | goto err; |
98 | 98 | ||
99 | hdr = skb->nh.ipv6h; | 99 | hdr = ipv6_hdr(skb); |
100 | 100 | ||
101 | if (hdr->version != 6) | 101 | if (hdr->version != 6) |
102 | goto err; | 102 | goto err; |
103 | 103 | ||
104 | skb->h.raw = (u8 *)(hdr + 1); | 104 | skb->transport_header = skb->network_header + sizeof(*hdr); |
105 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); | 105 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); |
106 | 106 | ||
107 | pkt_len = ntohs(hdr->payload_len); | 107 | pkt_len = ntohs(hdr->payload_len); |
@@ -116,7 +116,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
116 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); | 116 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
117 | goto drop; | 117 | goto drop; |
118 | } | 118 | } |
119 | hdr = skb->nh.ipv6h; | 119 | hdr = ipv6_hdr(skb); |
120 | } | 120 | } |
121 | 121 | ||
122 | if (hdr->nexthdr == NEXTHDR_HOP) { | 122 | if (hdr->nexthdr == NEXTHDR_HOP) { |
@@ -160,10 +160,10 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
160 | rcu_read_lock(); | 160 | rcu_read_lock(); |
161 | resubmit: | 161 | resubmit: |
162 | idev = ip6_dst_idev(skb->dst); | 162 | idev = ip6_dst_idev(skb->dst); |
163 | if (!pskb_pull(skb, skb->h.raw - skb->data)) | 163 | if (!pskb_pull(skb, skb_transport_offset(skb))) |
164 | goto discard; | 164 | goto discard; |
165 | nhoff = IP6CB(skb)->nhoff; | 165 | nhoff = IP6CB(skb)->nhoff; |
166 | nexthdr = skb->nh.raw[nhoff]; | 166 | nexthdr = skb_network_header(skb)[nhoff]; |
167 | 167 | ||
168 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); | 168 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); |
169 | if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) | 169 | if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) |
@@ -181,9 +181,9 @@ resubmit: | |||
181 | indefinitely. */ | 181 | indefinitely. */ |
182 | nf_reset(skb); | 182 | nf_reset(skb); |
183 | 183 | ||
184 | skb_postpull_rcsum(skb, skb->nh.raw, | 184 | skb_postpull_rcsum(skb, skb_network_header(skb), |
185 | skb->h.raw - skb->nh.raw); | 185 | skb_network_header_len(skb)); |
186 | hdr = skb->nh.ipv6h; | 186 | hdr = ipv6_hdr(skb); |
187 | if (ipv6_addr_is_multicast(&hdr->daddr) && | 187 | if (ipv6_addr_is_multicast(&hdr->daddr) && |
188 | !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, | 188 | !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, |
189 | &hdr->saddr) && | 189 | &hdr->saddr) && |
@@ -234,7 +234,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
234 | 234 | ||
235 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); | 235 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); |
236 | 236 | ||
237 | hdr = skb->nh.ipv6h; | 237 | hdr = ipv6_hdr(skb); |
238 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || | 238 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || |
239 | ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); | 239 | ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); |
240 | 240 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 305516921aa8..f508171bab73 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -88,8 +88,8 @@ static inline int ip6_output_finish(struct sk_buff *skb) | |||
88 | /* dev_loopback_xmit for use with netfilter. */ | 88 | /* dev_loopback_xmit for use with netfilter. */ |
89 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 89 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
90 | { | 90 | { |
91 | newskb->mac.raw = newskb->data; | 91 | skb_reset_mac_header(newskb); |
92 | __skb_pull(newskb, newskb->nh.raw - newskb->data); | 92 | __skb_pull(newskb, skb_network_offset(newskb)); |
93 | newskb->pkt_type = PACKET_LOOPBACK; | 93 | newskb->pkt_type = PACKET_LOOPBACK; |
94 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 94 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
95 | BUG_TRAP(newskb->dst); | 95 | BUG_TRAP(newskb->dst); |
@@ -107,13 +107,13 @@ static int ip6_output2(struct sk_buff *skb) | |||
107 | skb->protocol = htons(ETH_P_IPV6); | 107 | skb->protocol = htons(ETH_P_IPV6); |
108 | skb->dev = dev; | 108 | skb->dev = dev; |
109 | 109 | ||
110 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { | 110 | if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { |
111 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; | 111 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
112 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); | 112 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); |
113 | 113 | ||
114 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 114 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
115 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, | 115 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
116 | &skb->nh.ipv6h->saddr)) { | 116 | &ipv6_hdr(skb)->saddr)) { |
117 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); | 117 | struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); |
118 | 118 | ||
119 | /* Do not check for IFF_ALLMULTI; multicast routing | 119 | /* Do not check for IFF_ALLMULTI; multicast routing |
@@ -124,7 +124,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
124 | newskb->dev, | 124 | newskb->dev, |
125 | ip6_dev_loopback_xmit); | 125 | ip6_dev_loopback_xmit); |
126 | 126 | ||
127 | if (skb->nh.ipv6h->hop_limit == 0) { | 127 | if (ipv6_hdr(skb)->hop_limit == 0) { |
128 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); | 128 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
129 | kfree_skb(skb); | 129 | kfree_skb(skb); |
130 | return 0; | 130 | return 0; |
@@ -137,9 +137,17 @@ static int ip6_output2(struct sk_buff *skb) | |||
137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); | 137 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | ||
141 | { | ||
142 | struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; | ||
143 | |||
144 | return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? | ||
145 | skb->dst->dev->mtu : dst_mtu(skb->dst); | ||
146 | } | ||
147 | |||
140 | int ip6_output(struct sk_buff *skb) | 148 | int ip6_output(struct sk_buff *skb) |
141 | { | 149 | { |
142 | if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) || | 150 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
143 | dst_allfrag(skb->dst)) | 151 | dst_allfrag(skb->dst)) |
144 | return ip6_fragment(skb, ip6_output2); | 152 | return ip6_fragment(skb, ip6_output2); |
145 | else | 153 | else |
@@ -191,7 +199,9 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
191 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop); | 199 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop); |
192 | } | 200 | } |
193 | 201 | ||
194 | hdr = skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, sizeof(struct ipv6hdr)); | 202 | skb_push(skb, sizeof(struct ipv6hdr)); |
203 | skb_reset_network_header(skb); | ||
204 | hdr = ipv6_hdr(skb); | ||
195 | 205 | ||
196 | /* | 206 | /* |
197 | * Fill in the IPv6 header | 207 | * Fill in the IPv6 header |
@@ -239,6 +249,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
239 | return -EMSGSIZE; | 249 | return -EMSGSIZE; |
240 | } | 250 | } |
241 | 251 | ||
252 | EXPORT_SYMBOL(ip6_xmit); | ||
253 | |||
242 | /* | 254 | /* |
243 | * To avoid extra problems ND packets are send through this | 255 | * To avoid extra problems ND packets are send through this |
244 | * routine. It's code duplication but I really want to avoid | 256 | * routine. It's code duplication but I really want to avoid |
@@ -259,8 +271,9 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
259 | 271 | ||
260 | totlen = len + sizeof(struct ipv6hdr); | 272 | totlen = len + sizeof(struct ipv6hdr); |
261 | 273 | ||
262 | hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); | 274 | skb_reset_network_header(skb); |
263 | skb->nh.ipv6h = hdr; | 275 | skb_put(skb, sizeof(struct ipv6hdr)); |
276 | hdr = ipv6_hdr(skb); | ||
264 | 277 | ||
265 | *(__be32*)hdr = htonl(0x60000000); | 278 | *(__be32*)hdr = htonl(0x60000000); |
266 | 279 | ||
@@ -305,7 +318,7 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel) | |||
305 | 318 | ||
306 | static int ip6_forward_proxy_check(struct sk_buff *skb) | 319 | static int ip6_forward_proxy_check(struct sk_buff *skb) |
307 | { | 320 | { |
308 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 321 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
309 | u8 nexthdr = hdr->nexthdr; | 322 | u8 nexthdr = hdr->nexthdr; |
310 | int offset; | 323 | int offset; |
311 | 324 | ||
@@ -319,10 +332,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) | |||
319 | if (nexthdr == IPPROTO_ICMPV6) { | 332 | if (nexthdr == IPPROTO_ICMPV6) { |
320 | struct icmp6hdr *icmp6; | 333 | struct icmp6hdr *icmp6; |
321 | 334 | ||
322 | if (!pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) | 335 | if (!pskb_may_pull(skb, (skb_network_header(skb) + |
336 | offset + 1 - skb->data))) | ||
323 | return 0; | 337 | return 0; |
324 | 338 | ||
325 | icmp6 = (struct icmp6hdr *)(skb->nh.raw + offset); | 339 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); |
326 | 340 | ||
327 | switch (icmp6->icmp6_type) { | 341 | switch (icmp6->icmp6_type) { |
328 | case NDISC_ROUTER_SOLICITATION: | 342 | case NDISC_ROUTER_SOLICITATION: |
@@ -361,7 +375,7 @@ static inline int ip6_forward_finish(struct sk_buff *skb) | |||
361 | int ip6_forward(struct sk_buff *skb) | 375 | int ip6_forward(struct sk_buff *skb) |
362 | { | 376 | { |
363 | struct dst_entry *dst = skb->dst; | 377 | struct dst_entry *dst = skb->dst; |
364 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 378 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
365 | struct inet6_skb_parm *opt = IP6CB(skb); | 379 | struct inet6_skb_parm *opt = IP6CB(skb); |
366 | 380 | ||
367 | if (ipv6_devconf.forwarding == 0) | 381 | if (ipv6_devconf.forwarding == 0) |
@@ -372,7 +386,7 @@ int ip6_forward(struct sk_buff *skb) | |||
372 | goto drop; | 386 | goto drop; |
373 | } | 387 | } |
374 | 388 | ||
375 | skb->ip_summed = CHECKSUM_NONE; | 389 | skb_forward_csum(skb); |
376 | 390 | ||
377 | /* | 391 | /* |
378 | * We DO NOT make any processing on | 392 | * We DO NOT make any processing on |
@@ -388,7 +402,7 @@ int ip6_forward(struct sk_buff *skb) | |||
388 | * that different fragments will go along one path. --ANK | 402 | * that different fragments will go along one path. --ANK |
389 | */ | 403 | */ |
390 | if (opt->ra) { | 404 | if (opt->ra) { |
391 | u8 *ptr = skb->nh.raw + opt->ra; | 405 | u8 *ptr = skb_network_header(skb) + opt->ra; |
392 | if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) | 406 | if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3])) |
393 | return 0; | 407 | return 0; |
394 | } | 408 | } |
@@ -470,7 +484,7 @@ int ip6_forward(struct sk_buff *skb) | |||
470 | goto drop; | 484 | goto drop; |
471 | } | 485 | } |
472 | 486 | ||
473 | hdr = skb->nh.ipv6h; | 487 | hdr = ipv6_hdr(skb); |
474 | 488 | ||
475 | /* Mangling hops number delayed to point after skb COW */ | 489 | /* Mangling hops number delayed to point after skb COW */ |
476 | 490 | ||
@@ -499,33 +513,18 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
499 | #ifdef CONFIG_NET_SCHED | 513 | #ifdef CONFIG_NET_SCHED |
500 | to->tc_index = from->tc_index; | 514 | to->tc_index = from->tc_index; |
501 | #endif | 515 | #endif |
502 | #ifdef CONFIG_NETFILTER | 516 | nf_copy(to, from); |
503 | /* Connection association is same as pre-frag packet */ | ||
504 | nf_conntrack_put(to->nfct); | ||
505 | to->nfct = from->nfct; | ||
506 | nf_conntrack_get(to->nfct); | ||
507 | to->nfctinfo = from->nfctinfo; | ||
508 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
509 | nf_conntrack_put_reasm(to->nfct_reasm); | ||
510 | to->nfct_reasm = from->nfct_reasm; | ||
511 | nf_conntrack_get_reasm(to->nfct_reasm); | ||
512 | #endif | ||
513 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
514 | nf_bridge_put(to->nf_bridge); | ||
515 | to->nf_bridge = from->nf_bridge; | ||
516 | nf_bridge_get(to->nf_bridge); | ||
517 | #endif | ||
518 | #endif | ||
519 | skb_copy_secmark(to, from); | 517 | skb_copy_secmark(to, from); |
520 | } | 518 | } |
521 | 519 | ||
522 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 520 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
523 | { | 521 | { |
524 | u16 offset = sizeof(struct ipv6hdr); | 522 | u16 offset = sizeof(struct ipv6hdr); |
525 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 523 | struct ipv6_opt_hdr *exthdr = |
526 | unsigned int packet_len = skb->tail - skb->nh.raw; | 524 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
525 | unsigned int packet_len = skb->tail - skb->network_header; | ||
527 | int found_rhdr = 0; | 526 | int found_rhdr = 0; |
528 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 527 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
529 | 528 | ||
530 | while (offset + 1 <= packet_len) { | 529 | while (offset + 1 <= packet_len) { |
531 | 530 | ||
@@ -550,7 +549,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
550 | 549 | ||
551 | offset += ipv6_optlen(exthdr); | 550 | offset += ipv6_optlen(exthdr); |
552 | *nexthdr = &exthdr->nexthdr; | 551 | *nexthdr = &exthdr->nexthdr; |
553 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 552 | exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + |
553 | offset); | ||
554 | } | 554 | } |
555 | 555 | ||
556 | return offset; | 556 | return offset; |
@@ -574,7 +574,20 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
574 | hlen = ip6_find_1stfragopt(skb, &prevhdr); | 574 | hlen = ip6_find_1stfragopt(skb, &prevhdr); |
575 | nexthdr = *prevhdr; | 575 | nexthdr = *prevhdr; |
576 | 576 | ||
577 | mtu = dst_mtu(&rt->u.dst); | 577 | mtu = ip6_skb_dst_mtu(skb); |
578 | |||
579 | /* We must not fragment if the socket is set to force MTU discovery | ||
580 | * or if the skb it not generated by a local socket. (This last | ||
581 | * check should be redundant, but it's free.) | ||
582 | */ | ||
583 | if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) { | ||
584 | skb->dev = skb->dst->dev; | ||
585 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | ||
586 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); | ||
587 | kfree_skb(skb); | ||
588 | return -EMSGSIZE; | ||
589 | } | ||
590 | |||
578 | if (np && np->frag_size < mtu) { | 591 | if (np && np->frag_size < mtu) { |
579 | if (np->frag_size) | 592 | if (np->frag_size) |
580 | mtu = np->frag_size; | 593 | mtu = np->frag_size; |
@@ -616,7 +629,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
616 | /* BUILD HEADER */ | 629 | /* BUILD HEADER */ |
617 | 630 | ||
618 | *prevhdr = NEXTHDR_FRAGMENT; | 631 | *prevhdr = NEXTHDR_FRAGMENT; |
619 | tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); | 632 | tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); |
620 | if (!tmp_hdr) { | 633 | if (!tmp_hdr) { |
621 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); | 634 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
622 | return -ENOMEM; | 635 | return -ENOMEM; |
@@ -624,8 +637,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
624 | 637 | ||
625 | __skb_pull(skb, hlen); | 638 | __skb_pull(skb, hlen); |
626 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); | 639 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); |
627 | skb->nh.raw = __skb_push(skb, hlen); | 640 | __skb_push(skb, hlen); |
628 | memcpy(skb->nh.raw, tmp_hdr, hlen); | 641 | skb_reset_network_header(skb); |
642 | memcpy(skb_network_header(skb), tmp_hdr, hlen); | ||
629 | 643 | ||
630 | ipv6_select_ident(skb, fh); | 644 | ipv6_select_ident(skb, fh); |
631 | fh->nexthdr = nexthdr; | 645 | fh->nexthdr = nexthdr; |
@@ -636,7 +650,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
636 | first_len = skb_pagelen(skb); | 650 | first_len = skb_pagelen(skb); |
637 | skb->data_len = first_len - skb_headlen(skb); | 651 | skb->data_len = first_len - skb_headlen(skb); |
638 | skb->len = first_len; | 652 | skb->len = first_len; |
639 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); | 653 | ipv6_hdr(skb)->payload_len = htons(first_len - |
654 | sizeof(struct ipv6hdr)); | ||
640 | 655 | ||
641 | dst_hold(&rt->u.dst); | 656 | dst_hold(&rt->u.dst); |
642 | 657 | ||
@@ -645,10 +660,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
645 | * before previous one went down. */ | 660 | * before previous one went down. */ |
646 | if (frag) { | 661 | if (frag) { |
647 | frag->ip_summed = CHECKSUM_NONE; | 662 | frag->ip_summed = CHECKSUM_NONE; |
648 | frag->h.raw = frag->data; | 663 | skb_reset_transport_header(frag); |
649 | fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr)); | 664 | fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr)); |
650 | frag->nh.raw = __skb_push(frag, hlen); | 665 | __skb_push(frag, hlen); |
651 | memcpy(frag->nh.raw, tmp_hdr, hlen); | 666 | skb_reset_network_header(frag); |
667 | memcpy(skb_network_header(frag), tmp_hdr, | ||
668 | hlen); | ||
652 | offset += skb->len - hlen - sizeof(struct frag_hdr); | 669 | offset += skb->len - hlen - sizeof(struct frag_hdr); |
653 | fh->nexthdr = nexthdr; | 670 | fh->nexthdr = nexthdr; |
654 | fh->reserved = 0; | 671 | fh->reserved = 0; |
@@ -656,7 +673,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
656 | if (frag->next != NULL) | 673 | if (frag->next != NULL) |
657 | fh->frag_off |= htons(IP6_MF); | 674 | fh->frag_off |= htons(IP6_MF); |
658 | fh->identification = frag_id; | 675 | fh->identification = frag_id; |
659 | frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); | 676 | ipv6_hdr(frag)->payload_len = |
677 | htons(frag->len - | ||
678 | sizeof(struct ipv6hdr)); | ||
660 | ip6_copy_metadata(frag, skb); | 679 | ip6_copy_metadata(frag, skb); |
661 | } | 680 | } |
662 | 681 | ||
@@ -733,9 +752,10 @@ slow_path: | |||
733 | ip6_copy_metadata(frag, skb); | 752 | ip6_copy_metadata(frag, skb); |
734 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); | 753 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); |
735 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 754 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
736 | frag->nh.raw = frag->data; | 755 | skb_reset_network_header(frag); |
737 | fh = (struct frag_hdr*)(frag->data + hlen); | 756 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
738 | frag->h.raw = frag->data + hlen + sizeof(struct frag_hdr); | 757 | frag->transport_header = (frag->network_header + hlen + |
758 | sizeof(struct frag_hdr)); | ||
739 | 759 | ||
740 | /* | 760 | /* |
741 | * Charge the memory for the fragment to any owner | 761 | * Charge the memory for the fragment to any owner |
@@ -747,7 +767,7 @@ slow_path: | |||
747 | /* | 767 | /* |
748 | * Copy the packet header into the new buffer. | 768 | * Copy the packet header into the new buffer. |
749 | */ | 769 | */ |
750 | memcpy(frag->nh.raw, skb->data, hlen); | 770 | skb_copy_from_linear_data(skb, skb_network_header(frag), hlen); |
751 | 771 | ||
752 | /* | 772 | /* |
753 | * Build fragment header. | 773 | * Build fragment header. |
@@ -763,14 +783,15 @@ slow_path: | |||
763 | /* | 783 | /* |
764 | * Copy a block of the IP datagram. | 784 | * Copy a block of the IP datagram. |
765 | */ | 785 | */ |
766 | if (skb_copy_bits(skb, ptr, frag->h.raw, len)) | 786 | if (skb_copy_bits(skb, ptr, skb_transport_header(skb), len)) |
767 | BUG(); | 787 | BUG(); |
768 | left -= len; | 788 | left -= len; |
769 | 789 | ||
770 | fh->frag_off = htons(offset); | 790 | fh->frag_off = htons(offset); |
771 | if (left > 0) | 791 | if (left > 0) |
772 | fh->frag_off |= htons(IP6_MF); | 792 | fh->frag_off |= htons(IP6_MF); |
773 | frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr)); | 793 | ipv6_hdr(frag)->payload_len = htons(frag->len - |
794 | sizeof(struct ipv6hdr)); | ||
774 | 795 | ||
775 | ptr += len; | 796 | ptr += len; |
776 | offset += len; | 797 | offset += len; |
@@ -861,6 +882,41 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
861 | goto out_err_release; | 882 | goto out_err_release; |
862 | } | 883 | } |
863 | 884 | ||
885 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
886 | /* | ||
887 | * Here if the dst entry we've looked up | ||
888 | * has a neighbour entry that is in the INCOMPLETE | ||
889 | * state and the src address from the flow is | ||
890 | * marked as OPTIMISTIC, we release the found | ||
891 | * dst entry and replace it instead with the | ||
892 | * dst entry of the nexthop router | ||
893 | */ | ||
894 | if (!((*dst)->neighbour->nud_state & NUD_VALID)) { | ||
895 | struct inet6_ifaddr *ifp; | ||
896 | struct flowi fl_gw; | ||
897 | int redirect; | ||
898 | |||
899 | ifp = ipv6_get_ifaddr(&fl->fl6_src, (*dst)->dev, 1); | ||
900 | |||
901 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | ||
902 | if (ifp) | ||
903 | in6_ifa_put(ifp); | ||
904 | |||
905 | if (redirect) { | ||
906 | /* | ||
907 | * We need to get the dst entry for the | ||
908 | * default router instead | ||
909 | */ | ||
910 | dst_release(*dst); | ||
911 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | ||
912 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | ||
913 | *dst = ip6_route_output(sk, &fl_gw); | ||
914 | if ((err = (*dst)->error)) | ||
915 | goto out_err_release; | ||
916 | } | ||
917 | } | ||
918 | #endif | ||
919 | |||
864 | return 0; | 920 | return 0; |
865 | 921 | ||
866 | out_err_release: | 922 | out_err_release: |
@@ -939,10 +995,10 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
939 | skb_put(skb,fragheaderlen + transhdrlen); | 995 | skb_put(skb,fragheaderlen + transhdrlen); |
940 | 996 | ||
941 | /* initialize network header pointer */ | 997 | /* initialize network header pointer */ |
942 | skb->nh.raw = skb->data; | 998 | skb_reset_network_header(skb); |
943 | 999 | ||
944 | /* initialize protocol header pointer */ | 1000 | /* initialize protocol header pointer */ |
945 | skb->h.raw = skb->data + fragheaderlen; | 1001 | skb->transport_header = skb->network_header + fragheaderlen; |
946 | 1002 | ||
947 | skb->ip_summed = CHECKSUM_PARTIAL; | 1003 | skb->ip_summed = CHECKSUM_PARTIAL; |
948 | skb->csum = 0; | 1004 | skb->csum = 0; |
@@ -1015,7 +1071,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1015 | inet->cork.fl = *fl; | 1071 | inet->cork.fl = *fl; |
1016 | np->cork.hop_limit = hlimit; | 1072 | np->cork.hop_limit = hlimit; |
1017 | np->cork.tclass = tclass; | 1073 | np->cork.tclass = tclass; |
1018 | mtu = dst_mtu(rt->u.dst.path); | 1074 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
1075 | rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); | ||
1019 | if (np->frag_size < mtu) { | 1076 | if (np->frag_size < mtu) { |
1020 | if (np->frag_size) | 1077 | if (np->frag_size) |
1021 | mtu = np->frag_size; | 1078 | mtu = np->frag_size; |
@@ -1162,10 +1219,10 @@ alloc_new_skb: | |||
1162 | * Find where to start putting bytes | 1219 | * Find where to start putting bytes |
1163 | */ | 1220 | */ |
1164 | data = skb_put(skb, fraglen); | 1221 | data = skb_put(skb, fraglen); |
1165 | skb->nh.raw = data + exthdrlen; | 1222 | skb_set_network_header(skb, exthdrlen); |
1166 | data += fragheaderlen; | 1223 | data += fragheaderlen; |
1167 | skb->h.raw = data + exthdrlen; | 1224 | skb->transport_header = (skb->network_header + |
1168 | 1225 | fragheaderlen); | |
1169 | if (fraggap) { | 1226 | if (fraggap) { |
1170 | skb->csum = skb_copy_and_csum_bits( | 1227 | skb->csum = skb_copy_and_csum_bits( |
1171 | skb_prev, maxfraglen, | 1228 | skb_prev, maxfraglen, |
@@ -1288,10 +1345,10 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1288 | tail_skb = &(skb_shinfo(skb)->frag_list); | 1345 | tail_skb = &(skb_shinfo(skb)->frag_list); |
1289 | 1346 | ||
1290 | /* move skb->data to ip header from ext header */ | 1347 | /* move skb->data to ip header from ext header */ |
1291 | if (skb->data < skb->nh.raw) | 1348 | if (skb->data < skb_network_header(skb)) |
1292 | __skb_pull(skb, skb->nh.raw - skb->data); | 1349 | __skb_pull(skb, skb_network_offset(skb)); |
1293 | while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { | 1350 | while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { |
1294 | __skb_pull(tmp_skb, skb->h.raw - skb->nh.raw); | 1351 | __skb_pull(tmp_skb, skb_network_header_len(skb)); |
1295 | *tail_skb = tmp_skb; | 1352 | *tail_skb = tmp_skb; |
1296 | tail_skb = &(tmp_skb->next); | 1353 | tail_skb = &(tmp_skb->next); |
1297 | skb->len += tmp_skb->len; | 1354 | skb->len += tmp_skb->len; |
@@ -1303,13 +1360,15 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1303 | } | 1360 | } |
1304 | 1361 | ||
1305 | ipv6_addr_copy(final_dst, &fl->fl6_dst); | 1362 | ipv6_addr_copy(final_dst, &fl->fl6_dst); |
1306 | __skb_pull(skb, skb->h.raw - skb->nh.raw); | 1363 | __skb_pull(skb, skb_network_header_len(skb)); |
1307 | if (opt && opt->opt_flen) | 1364 | if (opt && opt->opt_flen) |
1308 | ipv6_push_frag_opts(skb, opt, &proto); | 1365 | ipv6_push_frag_opts(skb, opt, &proto); |
1309 | if (opt && opt->opt_nflen) | 1366 | if (opt && opt->opt_nflen) |
1310 | ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst); | 1367 | ipv6_push_nfrag_opts(skb, opt, &proto, &final_dst); |
1311 | 1368 | ||
1312 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); | 1369 | skb_push(skb, sizeof(struct ipv6hdr)); |
1370 | skb_reset_network_header(skb); | ||
1371 | hdr = ipv6_hdr(skb); | ||
1313 | 1372 | ||
1314 | *(__be32*)hdr = fl->fl6_flowlabel | | 1373 | *(__be32*)hdr = fl->fl6_flowlabel | |
1315 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1374 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 08d944223ec8..a0902fbdb4e1 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1,14 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * IPv6 over IPv6 tunnel device | 2 | * IPv6 tunneling device |
3 | * Linux INET6 implementation | 3 | * Linux INET6 implementation |
4 | * | 4 | * |
5 | * Authors: | 5 | * Authors: |
6 | * Ville Nuorvala <vnuorval@tcs.hut.fi> | 6 | * Ville Nuorvala <vnuorval@tcs.hut.fi> |
7 | * Yasuyuki Kozakai <kozakai@linux-ipv6.org> | ||
7 | * | 8 | * |
8 | * $Id$ | 9 | * $Id$ |
9 | * | 10 | * |
10 | * Based on: | 11 | * Based on: |
11 | * linux/net/ipv6/sit.c | 12 | * linux/net/ipv6/sit.c and linux/net/ipv4/ipip.c |
12 | * | 13 | * |
13 | * RFC 2473 | 14 | * RFC 2473 |
14 | * | 15 | * |
@@ -24,6 +25,7 @@ | |||
24 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
25 | #include <linux/types.h> | 26 | #include <linux/types.h> |
26 | #include <linux/sockios.h> | 27 | #include <linux/sockios.h> |
28 | #include <linux/icmp.h> | ||
27 | #include <linux/if.h> | 29 | #include <linux/if.h> |
28 | #include <linux/in.h> | 30 | #include <linux/in.h> |
29 | #include <linux/ip.h> | 31 | #include <linux/ip.h> |
@@ -41,6 +43,7 @@ | |||
41 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
42 | #include <asm/atomic.h> | 44 | #include <asm/atomic.h> |
43 | 45 | ||
46 | #include <net/icmp.h> | ||
44 | #include <net/ip.h> | 47 | #include <net/ip.h> |
45 | #include <net/ipv6.h> | 48 | #include <net/ipv6.h> |
46 | #include <net/ip6_route.h> | 49 | #include <net/ip6_route.h> |
@@ -51,7 +54,7 @@ | |||
51 | #include <net/inet_ecn.h> | 54 | #include <net/inet_ecn.h> |
52 | 55 | ||
53 | MODULE_AUTHOR("Ville Nuorvala"); | 56 | MODULE_AUTHOR("Ville Nuorvala"); |
54 | MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel"); | 57 | MODULE_DESCRIPTION("IPv6 tunneling device"); |
55 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
56 | 59 | ||
57 | #define IPV6_TLV_TEL_DST_SIZE 8 | 60 | #define IPV6_TLV_TEL_DST_SIZE 8 |
@@ -63,6 +66,7 @@ MODULE_LICENSE("GPL"); | |||
63 | #endif | 66 | #endif |
64 | 67 | ||
65 | #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) | 68 | #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) |
69 | #define IPV6_TCLASS_SHIFT 20 | ||
66 | 70 | ||
67 | #define HASH_SIZE 32 | 71 | #define HASH_SIZE 32 |
68 | 72 | ||
@@ -70,12 +74,12 @@ MODULE_LICENSE("GPL"); | |||
70 | (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ | 74 | (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ |
71 | (HASH_SIZE - 1)) | 75 | (HASH_SIZE - 1)) |
72 | 76 | ||
73 | static int ip6ip6_fb_tnl_dev_init(struct net_device *dev); | 77 | static int ip6_fb_tnl_dev_init(struct net_device *dev); |
74 | static int ip6ip6_tnl_dev_init(struct net_device *dev); | 78 | static int ip6_tnl_dev_init(struct net_device *dev); |
75 | static void ip6ip6_tnl_dev_setup(struct net_device *dev); | 79 | static void ip6_tnl_dev_setup(struct net_device *dev); |
76 | 80 | ||
77 | /* the IPv6 tunnel fallback device */ | 81 | /* the IPv6 tunnel fallback device */ |
78 | static struct net_device *ip6ip6_fb_tnl_dev; | 82 | static struct net_device *ip6_fb_tnl_dev; |
79 | 83 | ||
80 | 84 | ||
81 | /* lists for storing tunnels in use */ | 85 | /* lists for storing tunnels in use */ |
@@ -84,7 +88,7 @@ static struct ip6_tnl *tnls_wc[1]; | |||
84 | static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l }; | 88 | static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l }; |
85 | 89 | ||
86 | /* lock for the tunnel lists */ | 90 | /* lock for the tunnel lists */ |
87 | static DEFINE_RWLOCK(ip6ip6_lock); | 91 | static DEFINE_RWLOCK(ip6_tnl_lock); |
88 | 92 | ||
89 | static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t) | 93 | static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t) |
90 | { | 94 | { |
@@ -115,7 +119,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) | |||
115 | } | 119 | } |
116 | 120 | ||
117 | /** | 121 | /** |
118 | * ip6ip6_tnl_lookup - fetch tunnel matching the end-point addresses | 122 | * ip6_tnl_lookup - fetch tunnel matching the end-point addresses |
119 | * @remote: the address of the tunnel exit-point | 123 | * @remote: the address of the tunnel exit-point |
120 | * @local: the address of the tunnel entry-point | 124 | * @local: the address of the tunnel entry-point |
121 | * | 125 | * |
@@ -126,7 +130,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) | |||
126 | **/ | 130 | **/ |
127 | 131 | ||
128 | static struct ip6_tnl * | 132 | static struct ip6_tnl * |
129 | ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) | 133 | ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) |
130 | { | 134 | { |
131 | unsigned h0 = HASH(remote); | 135 | unsigned h0 = HASH(remote); |
132 | unsigned h1 = HASH(local); | 136 | unsigned h1 = HASH(local); |
@@ -145,18 +149,18 @@ ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) | |||
145 | } | 149 | } |
146 | 150 | ||
147 | /** | 151 | /** |
148 | * ip6ip6_bucket - get head of list matching given tunnel parameters | 152 | * ip6_tnl_bucket - get head of list matching given tunnel parameters |
149 | * @p: parameters containing tunnel end-points | 153 | * @p: parameters containing tunnel end-points |
150 | * | 154 | * |
151 | * Description: | 155 | * Description: |
152 | * ip6ip6_bucket() returns the head of the list matching the | 156 | * ip6_tnl_bucket() returns the head of the list matching the |
153 | * &struct in6_addr entries laddr and raddr in @p. | 157 | * &struct in6_addr entries laddr and raddr in @p. |
154 | * | 158 | * |
155 | * Return: head of IPv6 tunnel list | 159 | * Return: head of IPv6 tunnel list |
156 | **/ | 160 | **/ |
157 | 161 | ||
158 | static struct ip6_tnl ** | 162 | static struct ip6_tnl ** |
159 | ip6ip6_bucket(struct ip6_tnl_parm *p) | 163 | ip6_tnl_bucket(struct ip6_tnl_parm *p) |
160 | { | 164 | { |
161 | struct in6_addr *remote = &p->raddr; | 165 | struct in6_addr *remote = &p->raddr; |
162 | struct in6_addr *local = &p->laddr; | 166 | struct in6_addr *local = &p->laddr; |
@@ -171,36 +175,36 @@ ip6ip6_bucket(struct ip6_tnl_parm *p) | |||
171 | } | 175 | } |
172 | 176 | ||
173 | /** | 177 | /** |
174 | * ip6ip6_tnl_link - add tunnel to hash table | 178 | * ip6_tnl_link - add tunnel to hash table |
175 | * @t: tunnel to be added | 179 | * @t: tunnel to be added |
176 | **/ | 180 | **/ |
177 | 181 | ||
178 | static void | 182 | static void |
179 | ip6ip6_tnl_link(struct ip6_tnl *t) | 183 | ip6_tnl_link(struct ip6_tnl *t) |
180 | { | 184 | { |
181 | struct ip6_tnl **tp = ip6ip6_bucket(&t->parms); | 185 | struct ip6_tnl **tp = ip6_tnl_bucket(&t->parms); |
182 | 186 | ||
183 | t->next = *tp; | 187 | t->next = *tp; |
184 | write_lock_bh(&ip6ip6_lock); | 188 | write_lock_bh(&ip6_tnl_lock); |
185 | *tp = t; | 189 | *tp = t; |
186 | write_unlock_bh(&ip6ip6_lock); | 190 | write_unlock_bh(&ip6_tnl_lock); |
187 | } | 191 | } |
188 | 192 | ||
189 | /** | 193 | /** |
190 | * ip6ip6_tnl_unlink - remove tunnel from hash table | 194 | * ip6_tnl_unlink - remove tunnel from hash table |
191 | * @t: tunnel to be removed | 195 | * @t: tunnel to be removed |
192 | **/ | 196 | **/ |
193 | 197 | ||
194 | static void | 198 | static void |
195 | ip6ip6_tnl_unlink(struct ip6_tnl *t) | 199 | ip6_tnl_unlink(struct ip6_tnl *t) |
196 | { | 200 | { |
197 | struct ip6_tnl **tp; | 201 | struct ip6_tnl **tp; |
198 | 202 | ||
199 | for (tp = ip6ip6_bucket(&t->parms); *tp; tp = &(*tp)->next) { | 203 | for (tp = ip6_tnl_bucket(&t->parms); *tp; tp = &(*tp)->next) { |
200 | if (t == *tp) { | 204 | if (t == *tp) { |
201 | write_lock_bh(&ip6ip6_lock); | 205 | write_lock_bh(&ip6_tnl_lock); |
202 | *tp = t->next; | 206 | *tp = t->next; |
203 | write_unlock_bh(&ip6ip6_lock); | 207 | write_unlock_bh(&ip6_tnl_lock); |
204 | break; | 208 | break; |
205 | } | 209 | } |
206 | } | 210 | } |
@@ -237,12 +241,12 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) | |||
237 | if (i == IP6_TNL_MAX) | 241 | if (i == IP6_TNL_MAX) |
238 | goto failed; | 242 | goto failed; |
239 | } | 243 | } |
240 | dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup); | 244 | dev = alloc_netdev(sizeof (*t), name, ip6_tnl_dev_setup); |
241 | if (dev == NULL) | 245 | if (dev == NULL) |
242 | goto failed; | 246 | goto failed; |
243 | 247 | ||
244 | t = netdev_priv(dev); | 248 | t = netdev_priv(dev); |
245 | dev->init = ip6ip6_tnl_dev_init; | 249 | dev->init = ip6_tnl_dev_init; |
246 | t->parms = *p; | 250 | t->parms = *p; |
247 | 251 | ||
248 | if ((err = register_netdevice(dev)) < 0) { | 252 | if ((err = register_netdevice(dev)) < 0) { |
@@ -250,19 +254,19 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) | |||
250 | goto failed; | 254 | goto failed; |
251 | } | 255 | } |
252 | dev_hold(dev); | 256 | dev_hold(dev); |
253 | ip6ip6_tnl_link(t); | 257 | ip6_tnl_link(t); |
254 | return t; | 258 | return t; |
255 | failed: | 259 | failed: |
256 | return NULL; | 260 | return NULL; |
257 | } | 261 | } |
258 | 262 | ||
259 | /** | 263 | /** |
260 | * ip6ip6_tnl_locate - find or create tunnel matching given parameters | 264 | * ip6_tnl_locate - find or create tunnel matching given parameters |
261 | * @p: tunnel parameters | 265 | * @p: tunnel parameters |
262 | * @create: != 0 if allowed to create new tunnel if no match found | 266 | * @create: != 0 if allowed to create new tunnel if no match found |
263 | * | 267 | * |
264 | * Description: | 268 | * Description: |
265 | * ip6ip6_tnl_locate() first tries to locate an existing tunnel | 269 | * ip6_tnl_locate() first tries to locate an existing tunnel |
266 | * based on @parms. If this is unsuccessful, but @create is set a new | 270 | * based on @parms. If this is unsuccessful, but @create is set a new |
267 | * tunnel device is created and registered for use. | 271 | * tunnel device is created and registered for use. |
268 | * | 272 | * |
@@ -270,13 +274,13 @@ failed: | |||
270 | * matching tunnel or NULL | 274 | * matching tunnel or NULL |
271 | **/ | 275 | **/ |
272 | 276 | ||
273 | static struct ip6_tnl *ip6ip6_tnl_locate(struct ip6_tnl_parm *p, int create) | 277 | static struct ip6_tnl *ip6_tnl_locate(struct ip6_tnl_parm *p, int create) |
274 | { | 278 | { |
275 | struct in6_addr *remote = &p->raddr; | 279 | struct in6_addr *remote = &p->raddr; |
276 | struct in6_addr *local = &p->laddr; | 280 | struct in6_addr *local = &p->laddr; |
277 | struct ip6_tnl *t; | 281 | struct ip6_tnl *t; |
278 | 282 | ||
279 | for (t = *ip6ip6_bucket(p); t; t = t->next) { | 283 | for (t = *ip6_tnl_bucket(p); t; t = t->next) { |
280 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 284 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
281 | ipv6_addr_equal(remote, &t->parms.raddr)) | 285 | ipv6_addr_equal(remote, &t->parms.raddr)) |
282 | return t; | 286 | return t; |
@@ -287,24 +291,24 @@ static struct ip6_tnl *ip6ip6_tnl_locate(struct ip6_tnl_parm *p, int create) | |||
287 | } | 291 | } |
288 | 292 | ||
289 | /** | 293 | /** |
290 | * ip6ip6_tnl_dev_uninit - tunnel device uninitializer | 294 | * ip6_tnl_dev_uninit - tunnel device uninitializer |
291 | * @dev: the device to be destroyed | 295 | * @dev: the device to be destroyed |
292 | * | 296 | * |
293 | * Description: | 297 | * Description: |
294 | * ip6ip6_tnl_dev_uninit() removes tunnel from its list | 298 | * ip6_tnl_dev_uninit() removes tunnel from its list |
295 | **/ | 299 | **/ |
296 | 300 | ||
297 | static void | 301 | static void |
298 | ip6ip6_tnl_dev_uninit(struct net_device *dev) | 302 | ip6_tnl_dev_uninit(struct net_device *dev) |
299 | { | 303 | { |
300 | struct ip6_tnl *t = netdev_priv(dev); | 304 | struct ip6_tnl *t = netdev_priv(dev); |
301 | 305 | ||
302 | if (dev == ip6ip6_fb_tnl_dev) { | 306 | if (dev == ip6_fb_tnl_dev) { |
303 | write_lock_bh(&ip6ip6_lock); | 307 | write_lock_bh(&ip6_tnl_lock); |
304 | tnls_wc[0] = NULL; | 308 | tnls_wc[0] = NULL; |
305 | write_unlock_bh(&ip6ip6_lock); | 309 | write_unlock_bh(&ip6_tnl_lock); |
306 | } else { | 310 | } else { |
307 | ip6ip6_tnl_unlink(t); | 311 | ip6_tnl_unlink(t); |
308 | } | 312 | } |
309 | ip6_tnl_dst_reset(t); | 313 | ip6_tnl_dst_reset(t); |
310 | dev_put(dev); | 314 | dev_put(dev); |
@@ -372,16 +376,16 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
372 | } | 376 | } |
373 | 377 | ||
374 | /** | 378 | /** |
375 | * ip6ip6_err - tunnel error handler | 379 | * ip6_tnl_err - tunnel error handler |
376 | * | 380 | * |
377 | * Description: | 381 | * Description: |
378 | * ip6ip6_err() should handle errors in the tunnel according | 382 | * ip6_tnl_err() should handle errors in the tunnel according |
379 | * to the specifications in RFC 2473. | 383 | * to the specifications in RFC 2473. |
380 | **/ | 384 | **/ |
381 | 385 | ||
382 | static int | 386 | static int |
383 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 387 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, |
384 | int type, int code, int offset, __be32 info) | 388 | int *type, int *code, int *msg, __be32 *info, int offset) |
385 | { | 389 | { |
386 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 390 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; |
387 | struct ip6_tnl *t; | 391 | struct ip6_tnl *t; |
@@ -396,13 +400,16 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
396 | in trouble since we might need the source address for further | 400 | in trouble since we might need the source address for further |
397 | processing of the error. */ | 401 | processing of the error. */ |
398 | 402 | ||
399 | read_lock(&ip6ip6_lock); | 403 | read_lock(&ip6_tnl_lock); |
400 | if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) | 404 | if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) |
405 | goto out; | ||
406 | |||
407 | if (t->parms.proto != ipproto && t->parms.proto != 0) | ||
401 | goto out; | 408 | goto out; |
402 | 409 | ||
403 | err = 0; | 410 | err = 0; |
404 | 411 | ||
405 | switch (type) { | 412 | switch (*type) { |
406 | __u32 teli; | 413 | __u32 teli; |
407 | struct ipv6_tlv_tnl_enc_lim *tel; | 414 | struct ipv6_tlv_tnl_enc_lim *tel; |
408 | __u32 mtu; | 415 | __u32 mtu; |
@@ -414,7 +421,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
414 | rel_msg = 1; | 421 | rel_msg = 1; |
415 | break; | 422 | break; |
416 | case ICMPV6_TIME_EXCEED: | 423 | case ICMPV6_TIME_EXCEED: |
417 | if (code == ICMPV6_EXC_HOPLIMIT) { | 424 | if ((*code) == ICMPV6_EXC_HOPLIMIT) { |
418 | if (net_ratelimit()) | 425 | if (net_ratelimit()) |
419 | printk(KERN_WARNING | 426 | printk(KERN_WARNING |
420 | "%s: Too small hop limit or " | 427 | "%s: Too small hop limit or " |
@@ -425,10 +432,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
425 | break; | 432 | break; |
426 | case ICMPV6_PARAMPROB: | 433 | case ICMPV6_PARAMPROB: |
427 | teli = 0; | 434 | teli = 0; |
428 | if (code == ICMPV6_HDR_FIELD) | 435 | if ((*code) == ICMPV6_HDR_FIELD) |
429 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); | 436 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); |
430 | 437 | ||
431 | if (teli && teli == ntohl(info) - 2) { | 438 | if (teli && teli == ntohl(*info) - 2) { |
432 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 439 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
433 | if (tel->encap_limit == 0) { | 440 | if (tel->encap_limit == 0) { |
434 | if (net_ratelimit()) | 441 | if (net_ratelimit()) |
@@ -445,7 +452,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
445 | } | 452 | } |
446 | break; | 453 | break; |
447 | case ICMPV6_PKT_TOOBIG: | 454 | case ICMPV6_PKT_TOOBIG: |
448 | mtu = ntohl(info) - offset; | 455 | mtu = ntohl(*info) - offset; |
449 | if (mtu < IPV6_MIN_MTU) | 456 | if (mtu < IPV6_MIN_MTU) |
450 | mtu = IPV6_MIN_MTU; | 457 | mtu = IPV6_MIN_MTU; |
451 | t->dev->mtu = mtu; | 458 | t->dev->mtu = mtu; |
@@ -458,20 +465,144 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
458 | } | 465 | } |
459 | break; | 466 | break; |
460 | } | 467 | } |
461 | if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) { | 468 | |
469 | *type = rel_type; | ||
470 | *code = rel_code; | ||
471 | *info = rel_info; | ||
472 | *msg = rel_msg; | ||
473 | |||
474 | out: | ||
475 | read_unlock(&ip6_tnl_lock); | ||
476 | return err; | ||
477 | } | ||
478 | |||
479 | static int | ||
480 | ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
481 | int type, int code, int offset, __u32 info) | ||
482 | { | ||
483 | int rel_msg = 0; | ||
484 | int rel_type = type; | ||
485 | int rel_code = code; | ||
486 | __u32 rel_info = info; | ||
487 | int err; | ||
488 | struct sk_buff *skb2; | ||
489 | struct iphdr *eiph; | ||
490 | struct flowi fl; | ||
491 | struct rtable *rt; | ||
492 | |||
493 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, | ||
494 | &rel_msg, &rel_info, offset); | ||
495 | if (err < 0) | ||
496 | return err; | ||
497 | |||
498 | if (rel_msg == 0) | ||
499 | return 0; | ||
500 | |||
501 | switch (rel_type) { | ||
502 | case ICMPV6_DEST_UNREACH: | ||
503 | if (rel_code != ICMPV6_ADDR_UNREACH) | ||
504 | return 0; | ||
505 | rel_type = ICMP_DEST_UNREACH; | ||
506 | rel_code = ICMP_HOST_UNREACH; | ||
507 | break; | ||
508 | case ICMPV6_PKT_TOOBIG: | ||
509 | if (rel_code != 0) | ||
510 | return 0; | ||
511 | rel_type = ICMP_DEST_UNREACH; | ||
512 | rel_code = ICMP_FRAG_NEEDED; | ||
513 | break; | ||
514 | default: | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | if (!pskb_may_pull(skb, offset + sizeof(struct iphdr))) | ||
519 | return 0; | ||
520 | |||
521 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
522 | if (!skb2) | ||
523 | return 0; | ||
524 | |||
525 | dst_release(skb2->dst); | ||
526 | skb2->dst = NULL; | ||
527 | skb_pull(skb2, offset); | ||
528 | skb_reset_network_header(skb2); | ||
529 | eiph = ip_hdr(skb2); | ||
530 | |||
531 | /* Try to guess incoming interface */ | ||
532 | memset(&fl, 0, sizeof(fl)); | ||
533 | fl.fl4_dst = eiph->saddr; | ||
534 | fl.fl4_tos = RT_TOS(eiph->tos); | ||
535 | fl.proto = IPPROTO_IPIP; | ||
536 | if (ip_route_output_key(&rt, &fl)) | ||
537 | goto out; | ||
538 | |||
539 | skb2->dev = rt->u.dst.dev; | ||
540 | |||
541 | /* route "incoming" packet */ | ||
542 | if (rt->rt_flags & RTCF_LOCAL) { | ||
543 | ip_rt_put(rt); | ||
544 | rt = NULL; | ||
545 | fl.fl4_dst = eiph->daddr; | ||
546 | fl.fl4_src = eiph->saddr; | ||
547 | fl.fl4_tos = eiph->tos; | ||
548 | if (ip_route_output_key(&rt, &fl) || | ||
549 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | ||
550 | ip_rt_put(rt); | ||
551 | goto out; | ||
552 | } | ||
553 | } else { | ||
554 | ip_rt_put(rt); | ||
555 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, | ||
556 | skb2->dev) || | ||
557 | skb2->dst->dev->type != ARPHRD_TUNNEL) | ||
558 | goto out; | ||
559 | } | ||
560 | |||
561 | /* change mtu on this route */ | ||
562 | if (rel_type == ICMP_DEST_UNREACH && rel_code == ICMP_FRAG_NEEDED) { | ||
563 | if (rel_info > dst_mtu(skb2->dst)) | ||
564 | goto out; | ||
565 | |||
566 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); | ||
567 | rel_info = htonl(rel_info); | ||
568 | } | ||
569 | |||
570 | icmp_send(skb2, rel_type, rel_code, rel_info); | ||
571 | |||
572 | out: | ||
573 | kfree_skb(skb2); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int | ||
578 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
579 | int type, int code, int offset, __u32 info) | ||
580 | { | ||
581 | int rel_msg = 0; | ||
582 | int rel_type = type; | ||
583 | int rel_code = code; | ||
584 | __u32 rel_info = info; | ||
585 | int err; | ||
586 | |||
587 | err = ip6_tnl_err(skb, IPPROTO_IPV6, opt, &rel_type, &rel_code, | ||
588 | &rel_msg, &rel_info, offset); | ||
589 | if (err < 0) | ||
590 | return err; | ||
591 | |||
592 | if (rel_msg && pskb_may_pull(skb, offset + sizeof(struct ipv6hdr))) { | ||
462 | struct rt6_info *rt; | 593 | struct rt6_info *rt; |
463 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 594 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
464 | 595 | ||
465 | if (!skb2) | 596 | if (!skb2) |
466 | goto out; | 597 | return 0; |
467 | 598 | ||
468 | dst_release(skb2->dst); | 599 | dst_release(skb2->dst); |
469 | skb2->dst = NULL; | 600 | skb2->dst = NULL; |
470 | skb_pull(skb2, offset); | 601 | skb_pull(skb2, offset); |
471 | skb2->nh.raw = skb2->data; | 602 | skb_reset_network_header(skb2); |
472 | 603 | ||
473 | /* Try to guess incoming interface */ | 604 | /* Try to guess incoming interface */ |
474 | rt = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0); | 605 | rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0); |
475 | 606 | ||
476 | if (rt && rt->rt6i_dev) | 607 | if (rt && rt->rt6i_dev) |
477 | skb2->dev = rt->rt6i_dev; | 608 | skb2->dev = rt->rt6i_dev; |
@@ -483,19 +614,34 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
483 | 614 | ||
484 | kfree_skb(skb2); | 615 | kfree_skb(skb2); |
485 | } | 616 | } |
486 | out: | 617 | |
487 | read_unlock(&ip6ip6_lock); | 618 | return 0; |
488 | return err; | ||
489 | } | 619 | } |
490 | 620 | ||
491 | static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, | 621 | static void ip4ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, |
492 | struct sk_buff *skb) | 622 | struct ipv6hdr *ipv6h, |
623 | struct sk_buff *skb) | ||
493 | { | 624 | { |
494 | struct ipv6hdr *inner_iph = skb->nh.ipv6h; | 625 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; |
495 | 626 | ||
496 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | 627 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
497 | IP6_ECN_set_ce(inner_iph); | 628 | ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); |
629 | |||
630 | if (INET_ECN_is_ce(dsfield)) | ||
631 | IP_ECN_set_ce(ip_hdr(skb)); | ||
632 | } | ||
633 | |||
634 | static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, | ||
635 | struct ipv6hdr *ipv6h, | ||
636 | struct sk_buff *skb) | ||
637 | { | ||
638 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | ||
639 | ipv6_copy_dscp(ipv6h, ipv6_hdr(skb)); | ||
640 | |||
641 | if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h))) | ||
642 | IP6_ECN_set_ce(ipv6_hdr(skb)); | ||
498 | } | 643 | } |
644 | |||
499 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | 645 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) |
500 | { | 646 | { |
501 | struct ip6_tnl_parm *p = &t->parms; | 647 | struct ip6_tnl_parm *p = &t->parms; |
@@ -519,53 +665,61 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | |||
519 | } | 665 | } |
520 | 666 | ||
521 | /** | 667 | /** |
522 | * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally | 668 | * ip6_tnl_rcv - decapsulate IPv6 packet and retransmit it locally |
523 | * @skb: received socket buffer | 669 | * @skb: received socket buffer |
670 | * @protocol: ethernet protocol ID | ||
671 | * @dscp_ecn_decapsulate: the function to decapsulate DSCP code and ECN | ||
524 | * | 672 | * |
525 | * Return: 0 | 673 | * Return: 0 |
526 | **/ | 674 | **/ |
527 | 675 | ||
528 | static int | 676 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, |
529 | ip6ip6_rcv(struct sk_buff *skb) | 677 | __u8 ipproto, |
678 | void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, | ||
679 | struct ipv6hdr *ipv6h, | ||
680 | struct sk_buff *skb)) | ||
530 | { | 681 | { |
531 | struct ipv6hdr *ipv6h; | ||
532 | struct ip6_tnl *t; | 682 | struct ip6_tnl *t; |
683 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
533 | 684 | ||
534 | ipv6h = skb->nh.ipv6h; | 685 | read_lock(&ip6_tnl_lock); |
535 | 686 | ||
536 | read_lock(&ip6ip6_lock); | 687 | if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { |
688 | if (t->parms.proto != ipproto && t->parms.proto != 0) { | ||
689 | read_unlock(&ip6_tnl_lock); | ||
690 | goto discard; | ||
691 | } | ||
537 | 692 | ||
538 | if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { | ||
539 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 693 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
540 | read_unlock(&ip6ip6_lock); | 694 | read_unlock(&ip6_tnl_lock); |
541 | goto discard; | 695 | goto discard; |
542 | } | 696 | } |
543 | 697 | ||
544 | if (!ip6_tnl_rcv_ctl(t)) { | 698 | if (!ip6_tnl_rcv_ctl(t)) { |
545 | t->stat.rx_dropped++; | 699 | t->stat.rx_dropped++; |
546 | read_unlock(&ip6ip6_lock); | 700 | read_unlock(&ip6_tnl_lock); |
547 | goto discard; | 701 | goto discard; |
548 | } | 702 | } |
549 | secpath_reset(skb); | 703 | secpath_reset(skb); |
550 | skb->mac.raw = skb->nh.raw; | 704 | skb->mac_header = skb->network_header; |
551 | skb->nh.raw = skb->data; | 705 | skb_reset_network_header(skb); |
552 | skb->protocol = htons(ETH_P_IPV6); | 706 | skb->protocol = htons(protocol); |
553 | skb->pkt_type = PACKET_HOST; | 707 | skb->pkt_type = PACKET_HOST; |
554 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | 708 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); |
555 | skb->dev = t->dev; | 709 | skb->dev = t->dev; |
556 | dst_release(skb->dst); | 710 | dst_release(skb->dst); |
557 | skb->dst = NULL; | 711 | skb->dst = NULL; |
558 | nf_reset(skb); | 712 | nf_reset(skb); |
559 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 713 | |
560 | ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); | 714 | dscp_ecn_decapsulate(t, ipv6h, skb); |
561 | ip6ip6_ecn_decapsulate(ipv6h, skb); | 715 | |
562 | t->stat.rx_packets++; | 716 | t->stat.rx_packets++; |
563 | t->stat.rx_bytes += skb->len; | 717 | t->stat.rx_bytes += skb->len; |
564 | netif_rx(skb); | 718 | netif_rx(skb); |
565 | read_unlock(&ip6ip6_lock); | 719 | read_unlock(&ip6_tnl_lock); |
566 | return 0; | 720 | return 0; |
567 | } | 721 | } |
568 | read_unlock(&ip6ip6_lock); | 722 | read_unlock(&ip6_tnl_lock); |
569 | return 1; | 723 | return 1; |
570 | 724 | ||
571 | discard: | 725 | discard: |
@@ -573,6 +727,18 @@ discard: | |||
573 | return 0; | 727 | return 0; |
574 | } | 728 | } |
575 | 729 | ||
730 | static int ip4ip6_rcv(struct sk_buff *skb) | ||
731 | { | ||
732 | return ip6_tnl_rcv(skb, ETH_P_IP, IPPROTO_IPIP, | ||
733 | ip4ip6_dscp_ecn_decapsulate); | ||
734 | } | ||
735 | |||
736 | static int ip6ip6_rcv(struct sk_buff *skb) | ||
737 | { | ||
738 | return ip6_tnl_rcv(skb, ETH_P_IPV6, IPPROTO_IPV6, | ||
739 | ip6ip6_dscp_ecn_decapsulate); | ||
740 | } | ||
741 | |||
576 | struct ipv6_tel_txoption { | 742 | struct ipv6_tel_txoption { |
577 | struct ipv6_txoptions ops; | 743 | struct ipv6_txoptions ops; |
578 | __u8 dst_opt[8]; | 744 | __u8 dst_opt[8]; |
@@ -593,7 +759,7 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) | |||
593 | } | 759 | } |
594 | 760 | ||
595 | /** | 761 | /** |
596 | * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own | 762 | * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own |
597 | * @t: the outgoing tunnel device | 763 | * @t: the outgoing tunnel device |
598 | * @hdr: IPv6 header from the incoming packet | 764 | * @hdr: IPv6 header from the incoming packet |
599 | * | 765 | * |
@@ -607,7 +773,7 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) | |||
607 | **/ | 773 | **/ |
608 | 774 | ||
609 | static inline int | 775 | static inline int |
610 | ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) | 776 | ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) |
611 | { | 777 | { |
612 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | 778 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); |
613 | } | 779 | } |
@@ -641,72 +807,49 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
641 | return ret; | 807 | return ret; |
642 | } | 808 | } |
643 | /** | 809 | /** |
644 | * ip6ip6_tnl_xmit - encapsulate packet and send | 810 | * ip6_tnl_xmit2 - encapsulate packet and send |
645 | * @skb: the outgoing socket buffer | 811 | * @skb: the outgoing socket buffer |
646 | * @dev: the outgoing tunnel device | 812 | * @dev: the outgoing tunnel device |
813 | * @dsfield: dscp code for outer header | ||
814 | * @fl: flow of tunneled packet | ||
815 | * @encap_limit: encapsulation limit | ||
816 | * @pmtu: Path MTU is stored if packet is too big | ||
647 | * | 817 | * |
648 | * Description: | 818 | * Description: |
649 | * Build new header and do some sanity checks on the packet before sending | 819 | * Build new header and do some sanity checks on the packet before sending |
650 | * it. | 820 | * it. |
651 | * | 821 | * |
652 | * Return: | 822 | * Return: |
653 | * 0 | 823 | * 0 on success |
824 | * -1 fail | ||
825 | * %-EMSGSIZE message too big. return mtu in this case. | ||
654 | **/ | 826 | **/ |
655 | 827 | ||
656 | static int | 828 | static int ip6_tnl_xmit2(struct sk_buff *skb, |
657 | ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | 829 | struct net_device *dev, |
830 | __u8 dsfield, | ||
831 | struct flowi *fl, | ||
832 | int encap_limit, | ||
833 | __u32 *pmtu) | ||
658 | { | 834 | { |
659 | struct ip6_tnl *t = netdev_priv(dev); | 835 | struct ip6_tnl *t = netdev_priv(dev); |
660 | struct net_device_stats *stats = &t->stat; | 836 | struct net_device_stats *stats = &t->stat; |
661 | struct ipv6hdr *ipv6h = skb->nh.ipv6h; | 837 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
662 | int encap_limit = -1; | ||
663 | struct ipv6_tel_txoption opt; | 838 | struct ipv6_tel_txoption opt; |
664 | __u16 offset; | ||
665 | struct flowi fl; | ||
666 | struct dst_entry *dst; | 839 | struct dst_entry *dst; |
667 | struct net_device *tdev; | 840 | struct net_device *tdev; |
668 | int mtu; | 841 | int mtu; |
669 | int max_headroom = sizeof(struct ipv6hdr); | 842 | int max_headroom = sizeof(struct ipv6hdr); |
670 | u8 proto; | 843 | u8 proto; |
671 | int err; | 844 | int err = -1; |
672 | int pkt_len; | 845 | int pkt_len; |
673 | int dsfield; | ||
674 | |||
675 | if (t->recursion++) { | ||
676 | stats->collisions++; | ||
677 | goto tx_err; | ||
678 | } | ||
679 | if (skb->protocol != htons(ETH_P_IPV6) || | ||
680 | !ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h)) | ||
681 | goto tx_err; | ||
682 | |||
683 | if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { | ||
684 | struct ipv6_tlv_tnl_enc_lim *tel; | ||
685 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; | ||
686 | if (tel->encap_limit == 0) { | ||
687 | icmpv6_send(skb, ICMPV6_PARAMPROB, | ||
688 | ICMPV6_HDR_FIELD, offset + 2, skb->dev); | ||
689 | goto tx_err; | ||
690 | } | ||
691 | encap_limit = tel->encap_limit - 1; | ||
692 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
693 | encap_limit = t->parms.encap_limit; | ||
694 | |||
695 | memcpy(&fl, &t->fl, sizeof (fl)); | ||
696 | proto = fl.proto; | ||
697 | |||
698 | dsfield = ipv6_get_dsfield(ipv6h); | ||
699 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | ||
700 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | ||
701 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | ||
702 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | ||
703 | 846 | ||
704 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 847 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
705 | dst_hold(dst); | 848 | dst_hold(dst); |
706 | else { | 849 | else { |
707 | dst = ip6_route_output(NULL, &fl); | 850 | dst = ip6_route_output(NULL, fl); |
708 | 851 | ||
709 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0) < 0) | 852 | if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0) |
710 | goto tx_err_link_failure; | 853 | goto tx_err_link_failure; |
711 | } | 854 | } |
712 | 855 | ||
@@ -730,7 +873,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
730 | if (skb->dst) | 873 | if (skb->dst) |
731 | skb->dst->ops->update_pmtu(skb->dst, mtu); | 874 | skb->dst->ops->update_pmtu(skb->dst, mtu); |
732 | if (skb->len > mtu) { | 875 | if (skb->len > mtu) { |
733 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); | 876 | *pmtu = mtu; |
877 | err = -EMSGSIZE; | ||
734 | goto tx_err_dst_release; | 878 | goto tx_err_dst_release; |
735 | } | 879 | } |
736 | 880 | ||
@@ -754,22 +898,24 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
754 | dst_release(skb->dst); | 898 | dst_release(skb->dst); |
755 | skb->dst = dst_clone(dst); | 899 | skb->dst = dst_clone(dst); |
756 | 900 | ||
757 | skb->h.raw = skb->nh.raw; | 901 | skb->transport_header = skb->network_header; |
758 | 902 | ||
903 | proto = fl->proto; | ||
759 | if (encap_limit >= 0) { | 904 | if (encap_limit >= 0) { |
760 | init_tel_txopt(&opt, encap_limit); | 905 | init_tel_txopt(&opt, encap_limit); |
761 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); | 906 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); |
762 | } | 907 | } |
763 | skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr)); | 908 | skb_push(skb, sizeof(struct ipv6hdr)); |
764 | ipv6h = skb->nh.ipv6h; | 909 | skb_reset_network_header(skb); |
765 | *(__be32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); | 910 | ipv6h = ipv6_hdr(skb); |
911 | *(__be32*)ipv6h = fl->fl6_flowlabel | htonl(0x60000000); | ||
766 | dsfield = INET_ECN_encapsulate(0, dsfield); | 912 | dsfield = INET_ECN_encapsulate(0, dsfield); |
767 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); | 913 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); |
768 | ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | 914 | ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); |
769 | ipv6h->hop_limit = t->parms.hop_limit; | 915 | ipv6h->hop_limit = t->parms.hop_limit; |
770 | ipv6h->nexthdr = proto; | 916 | ipv6h->nexthdr = proto; |
771 | ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src); | 917 | ipv6_addr_copy(&ipv6h->saddr, &fl->fl6_src); |
772 | ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst); | 918 | ipv6_addr_copy(&ipv6h->daddr, &fl->fl6_dst); |
773 | nf_reset(skb); | 919 | nf_reset(skb); |
774 | pkt_len = skb->len; | 920 | pkt_len = skb->len; |
775 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, | 921 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, |
@@ -783,13 +929,131 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
783 | stats->tx_aborted_errors++; | 929 | stats->tx_aborted_errors++; |
784 | } | 930 | } |
785 | ip6_tnl_dst_store(t, dst); | 931 | ip6_tnl_dst_store(t, dst); |
786 | t->recursion--; | ||
787 | return 0; | 932 | return 0; |
788 | tx_err_link_failure: | 933 | tx_err_link_failure: |
789 | stats->tx_carrier_errors++; | 934 | stats->tx_carrier_errors++; |
790 | dst_link_failure(skb); | 935 | dst_link_failure(skb); |
791 | tx_err_dst_release: | 936 | tx_err_dst_release: |
792 | dst_release(dst); | 937 | dst_release(dst); |
938 | return err; | ||
939 | } | ||
940 | |||
941 | static inline int | ||
942 | ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | ||
943 | { | ||
944 | struct ip6_tnl *t = netdev_priv(dev); | ||
945 | struct iphdr *iph = ip_hdr(skb); | ||
946 | int encap_limit = -1; | ||
947 | struct flowi fl; | ||
948 | __u8 dsfield; | ||
949 | __u32 mtu; | ||
950 | int err; | ||
951 | |||
952 | if ((t->parms.proto != IPPROTO_IPIP && t->parms.proto != 0) || | ||
953 | !ip6_tnl_xmit_ctl(t)) | ||
954 | return -1; | ||
955 | |||
956 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
957 | encap_limit = t->parms.encap_limit; | ||
958 | |||
959 | memcpy(&fl, &t->fl, sizeof (fl)); | ||
960 | fl.proto = IPPROTO_IPIP; | ||
961 | |||
962 | dsfield = ipv4_get_dsfield(iph); | ||
963 | |||
964 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | ||
965 | fl.fl6_flowlabel |= ntohl(((__u32)iph->tos << IPV6_TCLASS_SHIFT) | ||
966 | & IPV6_TCLASS_MASK); | ||
967 | |||
968 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); | ||
969 | if (err != 0) { | ||
970 | /* XXX: send ICMP error even if DF is not set. */ | ||
971 | if (err == -EMSGSIZE) | ||
972 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | ||
973 | htonl(mtu)); | ||
974 | return -1; | ||
975 | } | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static inline int | ||
981 | ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | ||
982 | { | ||
983 | struct ip6_tnl *t = netdev_priv(dev); | ||
984 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
985 | int encap_limit = -1; | ||
986 | __u16 offset; | ||
987 | struct flowi fl; | ||
988 | __u8 dsfield; | ||
989 | __u32 mtu; | ||
990 | int err; | ||
991 | |||
992 | if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) || | ||
993 | !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) | ||
994 | return -1; | ||
995 | |||
996 | offset = parse_tlv_tnl_enc_lim(skb, skb_network_header(skb)); | ||
997 | if (offset > 0) { | ||
998 | struct ipv6_tlv_tnl_enc_lim *tel; | ||
999 | tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; | ||
1000 | if (tel->encap_limit == 0) { | ||
1001 | icmpv6_send(skb, ICMPV6_PARAMPROB, | ||
1002 | ICMPV6_HDR_FIELD, offset + 2, skb->dev); | ||
1003 | return -1; | ||
1004 | } | ||
1005 | encap_limit = tel->encap_limit - 1; | ||
1006 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
1007 | encap_limit = t->parms.encap_limit; | ||
1008 | |||
1009 | memcpy(&fl, &t->fl, sizeof (fl)); | ||
1010 | fl.proto = IPPROTO_IPV6; | ||
1011 | |||
1012 | dsfield = ipv6_get_dsfield(ipv6h); | ||
1013 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | ||
1014 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | ||
1015 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | ||
1016 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | ||
1017 | |||
1018 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); | ||
1019 | if (err != 0) { | ||
1020 | if (err == -EMSGSIZE) | ||
1021 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); | ||
1022 | return -1; | ||
1023 | } | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int | ||
1029 | ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1030 | { | ||
1031 | struct ip6_tnl *t = netdev_priv(dev); | ||
1032 | struct net_device_stats *stats = &t->stat; | ||
1033 | int ret; | ||
1034 | |||
1035 | if (t->recursion++) { | ||
1036 | t->stat.collisions++; | ||
1037 | goto tx_err; | ||
1038 | } | ||
1039 | |||
1040 | switch (skb->protocol) { | ||
1041 | case __constant_htons(ETH_P_IP): | ||
1042 | ret = ip4ip6_tnl_xmit(skb, dev); | ||
1043 | break; | ||
1044 | case __constant_htons(ETH_P_IPV6): | ||
1045 | ret = ip6ip6_tnl_xmit(skb, dev); | ||
1046 | break; | ||
1047 | default: | ||
1048 | goto tx_err; | ||
1049 | } | ||
1050 | |||
1051 | if (ret < 0) | ||
1052 | goto tx_err; | ||
1053 | |||
1054 | t->recursion--; | ||
1055 | return 0; | ||
1056 | |||
793 | tx_err: | 1057 | tx_err: |
794 | stats->tx_errors++; | 1058 | stats->tx_errors++; |
795 | stats->tx_dropped++; | 1059 | stats->tx_dropped++; |
@@ -817,7 +1081,7 @@ static void ip6_tnl_set_cap(struct ip6_tnl *t) | |||
817 | } | 1081 | } |
818 | } | 1082 | } |
819 | 1083 | ||
820 | static void ip6ip6_tnl_link_config(struct ip6_tnl *t) | 1084 | static void ip6_tnl_link_config(struct ip6_tnl *t) |
821 | { | 1085 | { |
822 | struct net_device *dev = t->dev; | 1086 | struct net_device *dev = t->dev; |
823 | struct ip6_tnl_parm *p = &t->parms; | 1087 | struct ip6_tnl_parm *p = &t->parms; |
@@ -870,17 +1134,17 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t) | |||
870 | } | 1134 | } |
871 | 1135 | ||
872 | /** | 1136 | /** |
873 | * ip6ip6_tnl_change - update the tunnel parameters | 1137 | * ip6_tnl_change - update the tunnel parameters |
874 | * @t: tunnel to be changed | 1138 | * @t: tunnel to be changed |
875 | * @p: tunnel configuration parameters | 1139 | * @p: tunnel configuration parameters |
876 | * @active: != 0 if tunnel is ready for use | 1140 | * @active: != 0 if tunnel is ready for use |
877 | * | 1141 | * |
878 | * Description: | 1142 | * Description: |
879 | * ip6ip6_tnl_change() updates the tunnel parameters | 1143 | * ip6_tnl_change() updates the tunnel parameters |
880 | **/ | 1144 | **/ |
881 | 1145 | ||
882 | static int | 1146 | static int |
883 | ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | 1147 | ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) |
884 | { | 1148 | { |
885 | ipv6_addr_copy(&t->parms.laddr, &p->laddr); | 1149 | ipv6_addr_copy(&t->parms.laddr, &p->laddr); |
886 | ipv6_addr_copy(&t->parms.raddr, &p->raddr); | 1150 | ipv6_addr_copy(&t->parms.raddr, &p->raddr); |
@@ -889,19 +1153,20 @@ ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | |||
889 | t->parms.encap_limit = p->encap_limit; | 1153 | t->parms.encap_limit = p->encap_limit; |
890 | t->parms.flowinfo = p->flowinfo; | 1154 | t->parms.flowinfo = p->flowinfo; |
891 | t->parms.link = p->link; | 1155 | t->parms.link = p->link; |
1156 | t->parms.proto = p->proto; | ||
892 | ip6_tnl_dst_reset(t); | 1157 | ip6_tnl_dst_reset(t); |
893 | ip6ip6_tnl_link_config(t); | 1158 | ip6_tnl_link_config(t); |
894 | return 0; | 1159 | return 0; |
895 | } | 1160 | } |
896 | 1161 | ||
897 | /** | 1162 | /** |
898 | * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace | 1163 | * ip6_tnl_ioctl - configure ipv6 tunnels from userspace |
899 | * @dev: virtual device associated with tunnel | 1164 | * @dev: virtual device associated with tunnel |
900 | * @ifr: parameters passed from userspace | 1165 | * @ifr: parameters passed from userspace |
901 | * @cmd: command to be performed | 1166 | * @cmd: command to be performed |
902 | * | 1167 | * |
903 | * Description: | 1168 | * Description: |
904 | * ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels | 1169 | * ip6_tnl_ioctl() is used for managing IPv6 tunnels |
905 | * from userspace. | 1170 | * from userspace. |
906 | * | 1171 | * |
907 | * The possible commands are the following: | 1172 | * The possible commands are the following: |
@@ -923,7 +1188,7 @@ ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | |||
923 | **/ | 1188 | **/ |
924 | 1189 | ||
925 | static int | 1190 | static int |
926 | ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 1191 | ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
927 | { | 1192 | { |
928 | int err = 0; | 1193 | int err = 0; |
929 | struct ip6_tnl_parm p; | 1194 | struct ip6_tnl_parm p; |
@@ -931,12 +1196,12 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
931 | 1196 | ||
932 | switch (cmd) { | 1197 | switch (cmd) { |
933 | case SIOCGETTUNNEL: | 1198 | case SIOCGETTUNNEL: |
934 | if (dev == ip6ip6_fb_tnl_dev) { | 1199 | if (dev == ip6_fb_tnl_dev) { |
935 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { | 1200 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { |
936 | err = -EFAULT; | 1201 | err = -EFAULT; |
937 | break; | 1202 | break; |
938 | } | 1203 | } |
939 | t = ip6ip6_tnl_locate(&p, 0); | 1204 | t = ip6_tnl_locate(&p, 0); |
940 | } | 1205 | } |
941 | if (t == NULL) | 1206 | if (t == NULL) |
942 | t = netdev_priv(dev); | 1207 | t = netdev_priv(dev); |
@@ -954,10 +1219,11 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
954 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1219 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
955 | break; | 1220 | break; |
956 | err = -EINVAL; | 1221 | err = -EINVAL; |
957 | if (p.proto != IPPROTO_IPV6) | 1222 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && |
1223 | p.proto != 0) | ||
958 | break; | 1224 | break; |
959 | t = ip6ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); | 1225 | t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); |
960 | if (dev != ip6ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { | 1226 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
961 | if (t != NULL) { | 1227 | if (t != NULL) { |
962 | if (t->dev != dev) { | 1228 | if (t->dev != dev) { |
963 | err = -EEXIST; | 1229 | err = -EEXIST; |
@@ -966,9 +1232,9 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
966 | } else | 1232 | } else |
967 | t = netdev_priv(dev); | 1233 | t = netdev_priv(dev); |
968 | 1234 | ||
969 | ip6ip6_tnl_unlink(t); | 1235 | ip6_tnl_unlink(t); |
970 | err = ip6ip6_tnl_change(t, &p); | 1236 | err = ip6_tnl_change(t, &p); |
971 | ip6ip6_tnl_link(t); | 1237 | ip6_tnl_link(t); |
972 | netdev_state_change(dev); | 1238 | netdev_state_change(dev); |
973 | } | 1239 | } |
974 | if (t) { | 1240 | if (t) { |
@@ -984,15 +1250,15 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
984 | if (!capable(CAP_NET_ADMIN)) | 1250 | if (!capable(CAP_NET_ADMIN)) |
985 | break; | 1251 | break; |
986 | 1252 | ||
987 | if (dev == ip6ip6_fb_tnl_dev) { | 1253 | if (dev == ip6_fb_tnl_dev) { |
988 | err = -EFAULT; | 1254 | err = -EFAULT; |
989 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1255 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
990 | break; | 1256 | break; |
991 | err = -ENOENT; | 1257 | err = -ENOENT; |
992 | if ((t = ip6ip6_tnl_locate(&p, 0)) == NULL) | 1258 | if ((t = ip6_tnl_locate(&p, 0)) == NULL) |
993 | break; | 1259 | break; |
994 | err = -EPERM; | 1260 | err = -EPERM; |
995 | if (t->dev == ip6ip6_fb_tnl_dev) | 1261 | if (t->dev == ip6_fb_tnl_dev) |
996 | break; | 1262 | break; |
997 | dev = t->dev; | 1263 | dev = t->dev; |
998 | } | 1264 | } |
@@ -1006,20 +1272,20 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1006 | } | 1272 | } |
1007 | 1273 | ||
1008 | /** | 1274 | /** |
1009 | * ip6ip6_tnl_get_stats - return the stats for tunnel device | 1275 | * ip6_tnl_get_stats - return the stats for tunnel device |
1010 | * @dev: virtual device associated with tunnel | 1276 | * @dev: virtual device associated with tunnel |
1011 | * | 1277 | * |
1012 | * Return: stats for device | 1278 | * Return: stats for device |
1013 | **/ | 1279 | **/ |
1014 | 1280 | ||
1015 | static struct net_device_stats * | 1281 | static struct net_device_stats * |
1016 | ip6ip6_tnl_get_stats(struct net_device *dev) | 1282 | ip6_tnl_get_stats(struct net_device *dev) |
1017 | { | 1283 | { |
1018 | return &(((struct ip6_tnl *)netdev_priv(dev))->stat); | 1284 | return &(((struct ip6_tnl *)netdev_priv(dev))->stat); |
1019 | } | 1285 | } |
1020 | 1286 | ||
1021 | /** | 1287 | /** |
1022 | * ip6ip6_tnl_change_mtu - change mtu manually for tunnel device | 1288 | * ip6_tnl_change_mtu - change mtu manually for tunnel device |
1023 | * @dev: virtual device associated with tunnel | 1289 | * @dev: virtual device associated with tunnel |
1024 | * @new_mtu: the new mtu | 1290 | * @new_mtu: the new mtu |
1025 | * | 1291 | * |
@@ -1029,7 +1295,7 @@ ip6ip6_tnl_get_stats(struct net_device *dev) | |||
1029 | **/ | 1295 | **/ |
1030 | 1296 | ||
1031 | static int | 1297 | static int |
1032 | ip6ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) | 1298 | ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) |
1033 | { | 1299 | { |
1034 | if (new_mtu < IPV6_MIN_MTU) { | 1300 | if (new_mtu < IPV6_MIN_MTU) { |
1035 | return -EINVAL; | 1301 | return -EINVAL; |
@@ -1039,22 +1305,22 @@ ip6ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) | |||
1039 | } | 1305 | } |
1040 | 1306 | ||
1041 | /** | 1307 | /** |
1042 | * ip6ip6_tnl_dev_setup - setup virtual tunnel device | 1308 | * ip6_tnl_dev_setup - setup virtual tunnel device |
1043 | * @dev: virtual device associated with tunnel | 1309 | * @dev: virtual device associated with tunnel |
1044 | * | 1310 | * |
1045 | * Description: | 1311 | * Description: |
1046 | * Initialize function pointers and device parameters | 1312 | * Initialize function pointers and device parameters |
1047 | **/ | 1313 | **/ |
1048 | 1314 | ||
1049 | static void ip6ip6_tnl_dev_setup(struct net_device *dev) | 1315 | static void ip6_tnl_dev_setup(struct net_device *dev) |
1050 | { | 1316 | { |
1051 | SET_MODULE_OWNER(dev); | 1317 | SET_MODULE_OWNER(dev); |
1052 | dev->uninit = ip6ip6_tnl_dev_uninit; | 1318 | dev->uninit = ip6_tnl_dev_uninit; |
1053 | dev->destructor = free_netdev; | 1319 | dev->destructor = free_netdev; |
1054 | dev->hard_start_xmit = ip6ip6_tnl_xmit; | 1320 | dev->hard_start_xmit = ip6_tnl_xmit; |
1055 | dev->get_stats = ip6ip6_tnl_get_stats; | 1321 | dev->get_stats = ip6_tnl_get_stats; |
1056 | dev->do_ioctl = ip6ip6_tnl_ioctl; | 1322 | dev->do_ioctl = ip6_tnl_ioctl; |
1057 | dev->change_mtu = ip6ip6_tnl_change_mtu; | 1323 | dev->change_mtu = ip6_tnl_change_mtu; |
1058 | 1324 | ||
1059 | dev->type = ARPHRD_TUNNEL6; | 1325 | dev->type = ARPHRD_TUNNEL6; |
1060 | dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr); | 1326 | dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr); |
@@ -1065,50 +1331,56 @@ static void ip6ip6_tnl_dev_setup(struct net_device *dev) | |||
1065 | 1331 | ||
1066 | 1332 | ||
1067 | /** | 1333 | /** |
1068 | * ip6ip6_tnl_dev_init_gen - general initializer for all tunnel devices | 1334 | * ip6_tnl_dev_init_gen - general initializer for all tunnel devices |
1069 | * @dev: virtual device associated with tunnel | 1335 | * @dev: virtual device associated with tunnel |
1070 | **/ | 1336 | **/ |
1071 | 1337 | ||
1072 | static inline void | 1338 | static inline void |
1073 | ip6ip6_tnl_dev_init_gen(struct net_device *dev) | 1339 | ip6_tnl_dev_init_gen(struct net_device *dev) |
1074 | { | 1340 | { |
1075 | struct ip6_tnl *t = netdev_priv(dev); | 1341 | struct ip6_tnl *t = netdev_priv(dev); |
1076 | t->fl.proto = IPPROTO_IPV6; | ||
1077 | t->dev = dev; | 1342 | t->dev = dev; |
1078 | strcpy(t->parms.name, dev->name); | 1343 | strcpy(t->parms.name, dev->name); |
1079 | } | 1344 | } |
1080 | 1345 | ||
1081 | /** | 1346 | /** |
1082 | * ip6ip6_tnl_dev_init - initializer for all non fallback tunnel devices | 1347 | * ip6_tnl_dev_init - initializer for all non fallback tunnel devices |
1083 | * @dev: virtual device associated with tunnel | 1348 | * @dev: virtual device associated with tunnel |
1084 | **/ | 1349 | **/ |
1085 | 1350 | ||
1086 | static int | 1351 | static int |
1087 | ip6ip6_tnl_dev_init(struct net_device *dev) | 1352 | ip6_tnl_dev_init(struct net_device *dev) |
1088 | { | 1353 | { |
1089 | struct ip6_tnl *t = netdev_priv(dev); | 1354 | struct ip6_tnl *t = netdev_priv(dev); |
1090 | ip6ip6_tnl_dev_init_gen(dev); | 1355 | ip6_tnl_dev_init_gen(dev); |
1091 | ip6ip6_tnl_link_config(t); | 1356 | ip6_tnl_link_config(t); |
1092 | return 0; | 1357 | return 0; |
1093 | } | 1358 | } |
1094 | 1359 | ||
1095 | /** | 1360 | /** |
1096 | * ip6ip6_fb_tnl_dev_init - initializer for fallback tunnel device | 1361 | * ip6_fb_tnl_dev_init - initializer for fallback tunnel device |
1097 | * @dev: fallback device | 1362 | * @dev: fallback device |
1098 | * | 1363 | * |
1099 | * Return: 0 | 1364 | * Return: 0 |
1100 | **/ | 1365 | **/ |
1101 | 1366 | ||
1102 | static int | 1367 | static int |
1103 | ip6ip6_fb_tnl_dev_init(struct net_device *dev) | 1368 | ip6_fb_tnl_dev_init(struct net_device *dev) |
1104 | { | 1369 | { |
1105 | struct ip6_tnl *t = netdev_priv(dev); | 1370 | struct ip6_tnl *t = netdev_priv(dev); |
1106 | ip6ip6_tnl_dev_init_gen(dev); | 1371 | ip6_tnl_dev_init_gen(dev); |
1372 | t->parms.proto = IPPROTO_IPV6; | ||
1107 | dev_hold(dev); | 1373 | dev_hold(dev); |
1108 | tnls_wc[0] = t; | 1374 | tnls_wc[0] = t; |
1109 | return 0; | 1375 | return 0; |
1110 | } | 1376 | } |
1111 | 1377 | ||
1378 | static struct xfrm6_tunnel ip4ip6_handler = { | ||
1379 | .handler = ip4ip6_rcv, | ||
1380 | .err_handler = ip4ip6_err, | ||
1381 | .priority = 1, | ||
1382 | }; | ||
1383 | |||
1112 | static struct xfrm6_tunnel ip6ip6_handler = { | 1384 | static struct xfrm6_tunnel ip6ip6_handler = { |
1113 | .handler = ip6ip6_rcv, | 1385 | .handler = ip6ip6_rcv, |
1114 | .err_handler = ip6ip6_err, | 1386 | .err_handler = ip6ip6_err, |
@@ -1125,30 +1397,40 @@ static int __init ip6_tunnel_init(void) | |||
1125 | { | 1397 | { |
1126 | int err; | 1398 | int err; |
1127 | 1399 | ||
1400 | if (xfrm6_tunnel_register(&ip4ip6_handler, AF_INET)) { | ||
1401 | printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n"); | ||
1402 | err = -EAGAIN; | ||
1403 | goto out; | ||
1404 | } | ||
1405 | |||
1128 | if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { | 1406 | if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { |
1129 | printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); | 1407 | printk(KERN_ERR "ip6_tunnel init: can't register ip6ip6\n"); |
1130 | return -EAGAIN; | 1408 | err = -EAGAIN; |
1409 | goto unreg_ip4ip6; | ||
1131 | } | 1410 | } |
1132 | ip6ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | 1411 | ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", |
1133 | ip6ip6_tnl_dev_setup); | 1412 | ip6_tnl_dev_setup); |
1134 | 1413 | ||
1135 | if (!ip6ip6_fb_tnl_dev) { | 1414 | if (!ip6_fb_tnl_dev) { |
1136 | err = -ENOMEM; | 1415 | err = -ENOMEM; |
1137 | goto fail; | 1416 | goto fail; |
1138 | } | 1417 | } |
1139 | ip6ip6_fb_tnl_dev->init = ip6ip6_fb_tnl_dev_init; | 1418 | ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init; |
1140 | 1419 | ||
1141 | if ((err = register_netdev(ip6ip6_fb_tnl_dev))) { | 1420 | if ((err = register_netdev(ip6_fb_tnl_dev))) { |
1142 | free_netdev(ip6ip6_fb_tnl_dev); | 1421 | free_netdev(ip6_fb_tnl_dev); |
1143 | goto fail; | 1422 | goto fail; |
1144 | } | 1423 | } |
1145 | return 0; | 1424 | return 0; |
1146 | fail: | 1425 | fail: |
1147 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); | 1426 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); |
1427 | unreg_ip4ip6: | ||
1428 | xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); | ||
1429 | out: | ||
1148 | return err; | 1430 | return err; |
1149 | } | 1431 | } |
1150 | 1432 | ||
1151 | static void __exit ip6ip6_destroy_tunnels(void) | 1433 | static void __exit ip6_tnl_destroy_tunnels(void) |
1152 | { | 1434 | { |
1153 | int h; | 1435 | int h; |
1154 | struct ip6_tnl *t; | 1436 | struct ip6_tnl *t; |
@@ -1168,11 +1450,14 @@ static void __exit ip6ip6_destroy_tunnels(void) | |||
1168 | 1450 | ||
1169 | static void __exit ip6_tunnel_cleanup(void) | 1451 | static void __exit ip6_tunnel_cleanup(void) |
1170 | { | 1452 | { |
1453 | if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET)) | ||
1454 | printk(KERN_INFO "ip6_tunnel close: can't deregister ip4ip6\n"); | ||
1455 | |||
1171 | if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) | 1456 | if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) |
1172 | printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); | 1457 | printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n"); |
1173 | 1458 | ||
1174 | rtnl_lock(); | 1459 | rtnl_lock(); |
1175 | ip6ip6_destroy_tunnels(); | 1460 | ip6_tnl_destroy_tunnels(); |
1176 | rtnl_unlock(); | 1461 | rtnl_unlock(); |
1177 | } | 1462 | } |
1178 | 1463 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 5724ba9f75de..1ee50b5782e1 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -79,9 +79,9 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
79 | skb->ip_summed = CHECKSUM_NONE; | 79 | skb->ip_summed = CHECKSUM_NONE; |
80 | 80 | ||
81 | /* Remove ipcomp header and decompress original payload */ | 81 | /* Remove ipcomp header and decompress original payload */ |
82 | iph = skb->nh.ipv6h; | 82 | iph = ipv6_hdr(skb); |
83 | ipch = (void *)skb->data; | 83 | ipch = (void *)skb->data; |
84 | skb->h.raw = skb->nh.raw + sizeof(*ipch); | 84 | skb->transport_header = skb->network_header + sizeof(*ipch); |
85 | __skb_pull(skb, sizeof(*ipch)); | 85 | __skb_pull(skb, sizeof(*ipch)); |
86 | 86 | ||
87 | /* decompression */ | 87 | /* decompression */ |
@@ -111,7 +111,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
111 | 111 | ||
112 | skb->truesize += dlen - plen; | 112 | skb->truesize += dlen - plen; |
113 | __skb_put(skb, dlen - plen); | 113 | __skb_put(skb, dlen - plen); |
114 | memcpy(skb->data, scratch, dlen); | 114 | skb_copy_to_linear_data(skb, scratch, dlen); |
115 | err = ipch->nexthdr; | 115 | err = ipch->nexthdr; |
116 | 116 | ||
117 | out_put_cpu: | 117 | out_put_cpu: |
@@ -124,15 +124,13 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
124 | { | 124 | { |
125 | int err; | 125 | int err; |
126 | struct ipv6hdr *top_iph; | 126 | struct ipv6hdr *top_iph; |
127 | int hdr_len; | ||
128 | struct ipv6_comp_hdr *ipch; | 127 | struct ipv6_comp_hdr *ipch; |
129 | struct ipcomp_data *ipcd = x->data; | 128 | struct ipcomp_data *ipcd = x->data; |
130 | int plen, dlen; | 129 | int plen, dlen; |
131 | u8 *start, *scratch; | 130 | u8 *start, *scratch; |
132 | struct crypto_comp *tfm; | 131 | struct crypto_comp *tfm; |
133 | int cpu; | 132 | int cpu; |
134 | 133 | int hdr_len = skb_transport_offset(skb); | |
135 | hdr_len = skb->h.raw - skb->data; | ||
136 | 134 | ||
137 | /* check whether datagram len is larger than threshold */ | 135 | /* check whether datagram len is larger than threshold */ |
138 | if ((skb->len - hdr_len) < ipcd->threshold) { | 136 | if ((skb->len - hdr_len) < ipcd->threshold) { |
@@ -145,7 +143,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
145 | /* compression */ | 143 | /* compression */ |
146 | plen = skb->len - hdr_len; | 144 | plen = skb->len - hdr_len; |
147 | dlen = IPCOMP_SCRATCH_SIZE; | 145 | dlen = IPCOMP_SCRATCH_SIZE; |
148 | start = skb->h.raw; | 146 | start = skb_transport_header(skb); |
149 | 147 | ||
150 | cpu = get_cpu(); | 148 | cpu = get_cpu(); |
151 | scratch = *per_cpu_ptr(ipcomp6_scratches, cpu); | 149 | scratch = *per_cpu_ptr(ipcomp6_scratches, cpu); |
@@ -166,10 +164,10 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
166 | top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | 164 | top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); |
167 | 165 | ||
168 | ipch = (struct ipv6_comp_hdr *)start; | 166 | ipch = (struct ipv6_comp_hdr *)start; |
169 | ipch->nexthdr = *skb->nh.raw; | 167 | ipch->nexthdr = *skb_network_header(skb); |
170 | ipch->flags = 0; | 168 | ipch->flags = 0; |
171 | ipch->cpi = htons((u16 )ntohl(x->id.spi)); | 169 | ipch->cpi = htons((u16 )ntohl(x->id.spi)); |
172 | *skb->nh.raw = IPPROTO_COMP; | 170 | *skb_network_header(skb) = IPPROTO_COMP; |
173 | 171 | ||
174 | out_ok: | 172 | out_ok: |
175 | return 0; | 173 | return 0; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index f5f9582a8d39..aa3d07c52a8f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -101,14 +101,14 @@ static int ipv6_gso_send_check(struct sk_buff *skb) | |||
101 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 101 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
102 | goto out; | 102 | goto out; |
103 | 103 | ||
104 | ipv6h = skb->nh.ipv6h; | 104 | ipv6h = ipv6_hdr(skb); |
105 | __skb_pull(skb, sizeof(*ipv6h)); | 105 | __skb_pull(skb, sizeof(*ipv6h)); |
106 | err = -EPROTONOSUPPORT; | 106 | err = -EPROTONOSUPPORT; |
107 | 107 | ||
108 | rcu_read_lock(); | 108 | rcu_read_lock(); |
109 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 109 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
110 | if (likely(ops && ops->gso_send_check)) { | 110 | if (likely(ops && ops->gso_send_check)) { |
111 | skb->h.raw = skb->data; | 111 | skb_reset_transport_header(skb); |
112 | err = ops->gso_send_check(skb); | 112 | err = ops->gso_send_check(skb); |
113 | } | 113 | } |
114 | rcu_read_unlock(); | 114 | rcu_read_unlock(); |
@@ -137,14 +137,14 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | |||
137 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 137 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
138 | goto out; | 138 | goto out; |
139 | 139 | ||
140 | ipv6h = skb->nh.ipv6h; | 140 | ipv6h = ipv6_hdr(skb); |
141 | __skb_pull(skb, sizeof(*ipv6h)); | 141 | __skb_pull(skb, sizeof(*ipv6h)); |
142 | segs = ERR_PTR(-EPROTONOSUPPORT); | 142 | segs = ERR_PTR(-EPROTONOSUPPORT); |
143 | 143 | ||
144 | rcu_read_lock(); | 144 | rcu_read_lock(); |
145 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); | 145 | ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); |
146 | if (likely(ops && ops->gso_segment)) { | 146 | if (likely(ops && ops->gso_segment)) { |
147 | skb->h.raw = skb->data; | 147 | skb_reset_transport_header(skb); |
148 | segs = ops->gso_segment(skb, features); | 148 | segs = ops->gso_segment(skb, features); |
149 | } | 149 | } |
150 | rcu_read_unlock(); | 150 | rcu_read_unlock(); |
@@ -153,7 +153,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | |||
153 | goto out; | 153 | goto out; |
154 | 154 | ||
155 | for (skb = segs; skb; skb = skb->next) { | 155 | for (skb = segs; skb; skb = skb->next) { |
156 | ipv6h = skb->nh.ipv6h; | 156 | ipv6h = ipv6_hdr(skb); |
157 | ipv6h->payload_len = htons(skb->len - skb->mac_len - | 157 | ipv6h->payload_len = htons(skb->len - skb->mac_len - |
158 | sizeof(*ipv6h)); | 158 | sizeof(*ipv6h)); |
159 | } | 159 | } |
@@ -694,7 +694,7 @@ done: | |||
694 | retv = ip6_ra_control(sk, val, NULL); | 694 | retv = ip6_ra_control(sk, val, NULL); |
695 | break; | 695 | break; |
696 | case IPV6_MTU_DISCOVER: | 696 | case IPV6_MTU_DISCOVER: |
697 | if (val<0 || val>2) | 697 | if (val<0 || val>3) |
698 | goto e_inval; | 698 | goto e_inval; |
699 | np->pmtudisc = val; | 699 | np->pmtudisc = val; |
700 | retv = 0; | 700 | retv = 0; |
@@ -761,6 +761,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
761 | return err; | 761 | return err; |
762 | } | 762 | } |
763 | 763 | ||
764 | EXPORT_SYMBOL(ipv6_setsockopt); | ||
764 | 765 | ||
765 | #ifdef CONFIG_COMPAT | 766 | #ifdef CONFIG_COMPAT |
766 | int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, | 767 | int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, |
@@ -796,18 +797,37 @@ EXPORT_SYMBOL(compat_ipv6_setsockopt); | |||
796 | #endif | 797 | #endif |
797 | 798 | ||
798 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, | 799 | static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, |
799 | char __user *optval, int len) | 800 | int optname, char __user *optval, int len) |
800 | { | 801 | { |
801 | struct ipv6_opt_hdr *hdr; | 802 | struct ipv6_opt_hdr *hdr; |
802 | 803 | ||
803 | if (!opt || !opt->hopopt) | 804 | if (!opt) |
805 | return 0; | ||
806 | |||
807 | switch(optname) { | ||
808 | case IPV6_HOPOPTS: | ||
809 | hdr = opt->hopopt; | ||
810 | break; | ||
811 | case IPV6_RTHDRDSTOPTS: | ||
812 | hdr = opt->dst0opt; | ||
813 | break; | ||
814 | case IPV6_RTHDR: | ||
815 | hdr = (struct ipv6_opt_hdr *)opt->srcrt; | ||
816 | break; | ||
817 | case IPV6_DSTOPTS: | ||
818 | hdr = opt->dst1opt; | ||
819 | break; | ||
820 | default: | ||
821 | return -EINVAL; /* should not happen */ | ||
822 | } | ||
823 | |||
824 | if (!hdr) | ||
804 | return 0; | 825 | return 0; |
805 | hdr = opt->hopopt; | ||
806 | 826 | ||
807 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); | 827 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); |
808 | if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) | 828 | if (copy_to_user(optval, hdr, len)); |
809 | return -EFAULT; | 829 | return -EFAULT; |
810 | return len; | 830 | return ipv6_optlen(hdr); |
811 | } | 831 | } |
812 | 832 | ||
813 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | 833 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, |
@@ -945,7 +965,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
945 | 965 | ||
946 | lock_sock(sk); | 966 | lock_sock(sk); |
947 | len = ipv6_getsockopt_sticky(sk, np->opt, | 967 | len = ipv6_getsockopt_sticky(sk, np->opt, |
948 | optval, len); | 968 | optname, optval, len); |
949 | release_sock(sk); | 969 | release_sock(sk); |
950 | return put_user(len, optlen); | 970 | return put_user(len, optlen); |
951 | } | 971 | } |
@@ -1066,6 +1086,8 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1066 | return err; | 1086 | return err; |
1067 | } | 1087 | } |
1068 | 1088 | ||
1089 | EXPORT_SYMBOL(ipv6_getsockopt); | ||
1090 | |||
1069 | #ifdef CONFIG_COMPAT | 1091 | #ifdef CONFIG_COMPAT |
1070 | int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, | 1092 | int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, |
1071 | char __user *optval, int __user *optlen) | 1093 | char __user *optval, int __user *optlen) |
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c deleted file mode 100644 index e12e3d4fccec..000000000000 --- a/net/ipv6/ipv6_syms.c +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | |||
2 | #include <linux/module.h> | ||
3 | #include <net/protocol.h> | ||
4 | #include <net/ipv6.h> | ||
5 | #include <net/addrconf.h> | ||
6 | #include <net/ip6_route.h> | ||
7 | #include <net/xfrm.h> | ||
8 | |||
9 | EXPORT_SYMBOL(icmpv6_send); | ||
10 | EXPORT_SYMBOL(icmpv6_statistics); | ||
11 | EXPORT_SYMBOL(icmpv6_err_convert); | ||
12 | EXPORT_SYMBOL(ndisc_mc_map); | ||
13 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
14 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
15 | EXPORT_SYMBOL(ip6_route_output); | ||
16 | EXPORT_SYMBOL(ipv6_setsockopt); | ||
17 | EXPORT_SYMBOL(ipv6_getsockopt); | ||
18 | EXPORT_SYMBOL(inet6_register_protosw); | ||
19 | EXPORT_SYMBOL(inet6_unregister_protosw); | ||
20 | EXPORT_SYMBOL(inet6_add_protocol); | ||
21 | EXPORT_SYMBOL(inet6_del_protocol); | ||
22 | EXPORT_SYMBOL(ip6_xmit); | ||
23 | EXPORT_SYMBOL(inet6_release); | ||
24 | EXPORT_SYMBOL(inet6_bind); | ||
25 | EXPORT_SYMBOL(inet6_getname); | ||
26 | EXPORT_SYMBOL(inet6_ioctl); | ||
27 | EXPORT_SYMBOL(ipv6_get_saddr); | ||
28 | EXPORT_SYMBOL(ipv6_chk_addr); | ||
29 | EXPORT_SYMBOL(in6_dev_finish_destroy); | ||
30 | #ifdef CONFIG_XFRM | ||
31 | EXPORT_SYMBOL(xfrm6_rcv); | ||
32 | EXPORT_SYMBOL(xfrm6_input_addr); | ||
33 | EXPORT_SYMBOL(xfrm6_find_1stfragopt); | ||
34 | #endif | ||
35 | EXPORT_SYMBOL(rt6_lookup); | ||
36 | EXPORT_SYMBOL(ipv6_push_nfrag_opts); | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index a8d6625ec782..6c2758951d60 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -988,7 +988,7 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr) | |||
988 | if (!pskb_may_pull(skb, sizeof(struct icmp6hdr))) | 988 | if (!pskb_may_pull(skb, sizeof(struct icmp6hdr))) |
989 | return 0; | 989 | return 0; |
990 | 990 | ||
991 | pic = (struct icmp6hdr *)skb->h.raw; | 991 | pic = icmp6_hdr(skb); |
992 | 992 | ||
993 | switch (pic->icmp6_type) { | 993 | switch (pic->icmp6_type) { |
994 | case ICMPV6_MGM_QUERY: | 994 | case ICMPV6_MGM_QUERY: |
@@ -1167,11 +1167,11 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1167 | return -EINVAL; | 1167 | return -EINVAL; |
1168 | 1168 | ||
1169 | /* compute payload length excluding extension headers */ | 1169 | /* compute payload length excluding extension headers */ |
1170 | len = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); | 1170 | len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr); |
1171 | len -= (char *)skb->h.raw - (char *)skb->nh.ipv6h; | 1171 | len -= skb_network_header_len(skb); |
1172 | 1172 | ||
1173 | /* Drop queries with not link local source */ | 1173 | /* Drop queries with not link local source */ |
1174 | if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL)) | 1174 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) |
1175 | return -EINVAL; | 1175 | return -EINVAL; |
1176 | 1176 | ||
1177 | idev = in6_dev_get(skb->dev); | 1177 | idev = in6_dev_get(skb->dev); |
@@ -1179,7 +1179,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1179 | if (idev == NULL) | 1179 | if (idev == NULL) |
1180 | return 0; | 1180 | return 0; |
1181 | 1181 | ||
1182 | hdr = (struct icmp6hdr *) skb->h.raw; | 1182 | hdr = icmp6_hdr(skb); |
1183 | group = (struct in6_addr *) (hdr + 1); | 1183 | group = (struct in6_addr *) (hdr + 1); |
1184 | group_type = ipv6_addr_type(group); | 1184 | group_type = ipv6_addr_type(group); |
1185 | 1185 | ||
@@ -1212,7 +1212,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1212 | in6_dev_put(idev); | 1212 | in6_dev_put(idev); |
1213 | return -EINVAL; | 1213 | return -EINVAL; |
1214 | } | 1214 | } |
1215 | mlh2 = (struct mld2_query *) skb->h.raw; | 1215 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1216 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1216 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; |
1217 | if (!max_delay) | 1217 | if (!max_delay) |
1218 | max_delay = 1; | 1218 | max_delay = 1; |
@@ -1235,7 +1235,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1235 | in6_dev_put(idev); | 1235 | in6_dev_put(idev); |
1236 | return -EINVAL; | 1236 | return -EINVAL; |
1237 | } | 1237 | } |
1238 | mlh2 = (struct mld2_query *) skb->h.raw; | 1238 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1239 | mark = 1; | 1239 | mark = 1; |
1240 | } | 1240 | } |
1241 | } else { | 1241 | } else { |
@@ -1300,10 +1300,10 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1300 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | 1300 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) |
1301 | return -EINVAL; | 1301 | return -EINVAL; |
1302 | 1302 | ||
1303 | hdr = (struct icmp6hdr*) skb->h.raw; | 1303 | hdr = icmp6_hdr(skb); |
1304 | 1304 | ||
1305 | /* Drop reports with not link local source */ | 1305 | /* Drop reports with not link local source */ |
1306 | addr_type = ipv6_addr_type(&skb->nh.ipv6h->saddr); | 1306 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); |
1307 | if (addr_type != IPV6_ADDR_ANY && | 1307 | if (addr_type != IPV6_ADDR_ANY && |
1308 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1308 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
1309 | return -EINVAL; | 1309 | return -EINVAL; |
@@ -1411,7 +1411,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1411 | 1411 | ||
1412 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1412 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
1413 | 1413 | ||
1414 | if (ipv6_get_lladdr(dev, &addr_buf)) { | 1414 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1415 | /* <draft-ietf-magma-mld-source-05.txt>: | 1415 | /* <draft-ietf-magma-mld-source-05.txt>: |
1416 | * use unspecified address as the source address | 1416 | * use unspecified address as the source address |
1417 | * when a valid link-local address is not available. | 1417 | * when a valid link-local address is not available. |
@@ -1423,8 +1423,9 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1423 | 1423 | ||
1424 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1424 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
1425 | 1425 | ||
1426 | pmr =(struct mld2_report *)skb_put(skb, sizeof(*pmr)); | 1426 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); |
1427 | skb->h.raw = (unsigned char *)pmr; | 1427 | skb_put(skb, sizeof(*pmr)); |
1428 | pmr = (struct mld2_report *)skb_transport_header(skb); | ||
1428 | pmr->type = ICMPV6_MLD2_REPORT; | 1429 | pmr->type = ICMPV6_MLD2_REPORT; |
1429 | pmr->resv1 = 0; | 1430 | pmr->resv1 = 0; |
1430 | pmr->csum = 0; | 1431 | pmr->csum = 0; |
@@ -1441,7 +1442,7 @@ static inline int mld_dev_queue_xmit2(struct sk_buff *skb) | |||
1441 | unsigned char ha[MAX_ADDR_LEN]; | 1442 | unsigned char ha[MAX_ADDR_LEN]; |
1442 | int err; | 1443 | int err; |
1443 | 1444 | ||
1444 | ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1); | 1445 | ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1); |
1445 | err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len); | 1446 | err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len); |
1446 | if (err < 0) { | 1447 | if (err < 0) { |
1447 | kfree_skb(skb); | 1448 | kfree_skb(skb); |
@@ -1459,20 +1460,21 @@ static inline int mld_dev_queue_xmit(struct sk_buff *skb) | |||
1459 | 1460 | ||
1460 | static void mld_sendpack(struct sk_buff *skb) | 1461 | static void mld_sendpack(struct sk_buff *skb) |
1461 | { | 1462 | { |
1462 | struct ipv6hdr *pip6 = skb->nh.ipv6h; | 1463 | struct ipv6hdr *pip6 = ipv6_hdr(skb); |
1463 | struct mld2_report *pmr = (struct mld2_report *)skb->h.raw; | 1464 | struct mld2_report *pmr = |
1465 | (struct mld2_report *)skb_transport_header(skb); | ||
1464 | int payload_len, mldlen; | 1466 | int payload_len, mldlen; |
1465 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1467 | struct inet6_dev *idev = in6_dev_get(skb->dev); |
1466 | int err; | 1468 | int err; |
1467 | 1469 | ||
1468 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | 1470 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
1469 | payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - | 1471 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); |
1470 | sizeof(struct ipv6hdr); | 1472 | mldlen = skb->tail - skb->transport_header; |
1471 | mldlen = skb->tail - skb->h.raw; | ||
1472 | pip6->payload_len = htons(payload_len); | 1473 | pip6->payload_len = htons(payload_len); |
1473 | 1474 | ||
1474 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1475 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
1475 | IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0)); | 1476 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), |
1477 | mldlen, 0)); | ||
1476 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, | 1478 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, |
1477 | mld_dev_queue_xmit); | 1479 | mld_dev_queue_xmit); |
1478 | if (!err) { | 1480 | if (!err) { |
@@ -1506,7 +1508,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1506 | pgr->grec_auxwords = 0; | 1508 | pgr->grec_auxwords = 0; |
1507 | pgr->grec_nsrcs = 0; | 1509 | pgr->grec_nsrcs = 0; |
1508 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ | 1510 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ |
1509 | pmr = (struct mld2_report *)skb->h.raw; | 1511 | pmr = (struct mld2_report *)skb_transport_header(skb); |
1510 | pmr->ngrec = htons(ntohs(pmr->ngrec)+1); | 1512 | pmr->ngrec = htons(ntohs(pmr->ngrec)+1); |
1511 | *ppgr = pgr; | 1513 | *ppgr = pgr; |
1512 | return skb; | 1514 | return skb; |
@@ -1539,7 +1541,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1539 | if (!*psf_list) | 1541 | if (!*psf_list) |
1540 | goto empty_source; | 1542 | goto empty_source; |
1541 | 1543 | ||
1542 | pmr = skb ? (struct mld2_report *)skb->h.raw : NULL; | 1544 | pmr = skb ? (struct mld2_report *)skb_transport_header(skb) : NULL; |
1543 | 1545 | ||
1544 | /* EX and TO_EX get a fresh packet, if needed */ | 1546 | /* EX and TO_EX get a fresh packet, if needed */ |
1545 | if (truncate) { | 1547 | if (truncate) { |
@@ -1791,7 +1793,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1791 | 1793 | ||
1792 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1794 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
1793 | 1795 | ||
1794 | if (ipv6_get_lladdr(dev, &addr_buf)) { | 1796 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1795 | /* <draft-ietf-magma-mld-source-05.txt>: | 1797 | /* <draft-ietf-magma-mld-source-05.txt>: |
1796 | * use unspecified address as the source address | 1798 | * use unspecified address as the source address |
1797 | * when a valid link-local address is not available. | 1799 | * when a valid link-local address is not available. |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 0afcabdd8ed6..13b7160fb892 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -90,23 +90,26 @@ int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) | |||
90 | { | 90 | { |
91 | struct ip6_mh *mh; | 91 | struct ip6_mh *mh; |
92 | 92 | ||
93 | if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) || | 93 | if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || |
94 | !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3))) | 94 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
95 | ((skb_transport_header(skb)[1] + 1) << 3)))) | ||
95 | return -1; | 96 | return -1; |
96 | 97 | ||
97 | mh = (struct ip6_mh *)skb->h.raw; | 98 | mh = (struct ip6_mh *)skb_transport_header(skb); |
98 | 99 | ||
99 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { | 100 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { |
100 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", | 101 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", |
101 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); | 102 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); |
102 | mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw); | 103 | mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - |
104 | skb_network_header(skb))); | ||
103 | return -1; | 105 | return -1; |
104 | } | 106 | } |
105 | 107 | ||
106 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 108 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
107 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", | 109 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", |
108 | mh->ip6mh_proto); | 110 | mh->ip6mh_proto); |
109 | mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw); | 111 | mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - |
112 | skb_network_header(skb))); | ||
110 | return -1; | 113 | return -1; |
111 | } | 114 | } |
112 | 115 | ||
@@ -122,12 +125,12 @@ struct mip6_report_rate_limiter { | |||
122 | }; | 125 | }; |
123 | 126 | ||
124 | static struct mip6_report_rate_limiter mip6_report_rl = { | 127 | static struct mip6_report_rate_limiter mip6_report_rl = { |
125 | .lock = SPIN_LOCK_UNLOCKED | 128 | .lock = __SPIN_LOCK_UNLOCKED(mip6_report_rl.lock) |
126 | }; | 129 | }; |
127 | 130 | ||
128 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) | 131 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) |
129 | { | 132 | { |
130 | struct ipv6hdr *iph = skb->nh.ipv6h; | 133 | struct ipv6hdr *iph = ipv6_hdr(skb); |
131 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; | 134 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; |
132 | 135 | ||
133 | if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) && | 136 | if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) && |
@@ -152,10 +155,10 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb) | |||
152 | iph = (struct ipv6hdr *)skb->data; | 155 | iph = (struct ipv6hdr *)skb->data; |
153 | iph->payload_len = htons(skb->len - sizeof(*iph)); | 156 | iph->payload_len = htons(skb->len - sizeof(*iph)); |
154 | 157 | ||
155 | nexthdr = *skb->nh.raw; | 158 | nexthdr = *skb_network_header(skb); |
156 | *skb->nh.raw = IPPROTO_DSTOPTS; | 159 | *skb_network_header(skb) = IPPROTO_DSTOPTS; |
157 | 160 | ||
158 | dstopt = (struct ipv6_destopt_hdr *)skb->h.raw; | 161 | dstopt = (struct ipv6_destopt_hdr *)skb_transport_header(skb); |
159 | dstopt->nexthdr = nexthdr; | 162 | dstopt->nexthdr = nexthdr; |
160 | 163 | ||
161 | hao = mip6_padn((char *)(dstopt + 1), | 164 | hao = mip6_padn((char *)(dstopt + 1), |
@@ -215,21 +218,22 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct | |||
215 | if (likely(opt->dsthao)) { | 218 | if (likely(opt->dsthao)) { |
216 | offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); | 219 | offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); |
217 | if (likely(offset >= 0)) | 220 | if (likely(offset >= 0)) |
218 | hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset); | 221 | hao = (struct ipv6_destopt_hao *) |
222 | (skb_network_header(skb) + offset); | ||
219 | } | 223 | } |
220 | 224 | ||
221 | skb_get_timestamp(skb, &stamp); | 225 | skb_get_timestamp(skb, &stamp); |
222 | 226 | ||
223 | if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr, | 227 | if (!mip6_report_rl_allow(&stamp, &ipv6_hdr(skb)->daddr, |
224 | hao ? &hao->addr : &skb->nh.ipv6h->saddr, | 228 | hao ? &hao->addr : &ipv6_hdr(skb)->saddr, |
225 | opt->iif)) | 229 | opt->iif)) |
226 | goto out; | 230 | goto out; |
227 | 231 | ||
228 | memset(&sel, 0, sizeof(sel)); | 232 | memset(&sel, 0, sizeof(sel)); |
229 | memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr, | 233 | memcpy(&sel.daddr, (xfrm_address_t *)&ipv6_hdr(skb)->daddr, |
230 | sizeof(sel.daddr)); | 234 | sizeof(sel.daddr)); |
231 | sel.prefixlen_d = 128; | 235 | sel.prefixlen_d = 128; |
232 | memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr, | 236 | memcpy(&sel.saddr, (xfrm_address_t *)&ipv6_hdr(skb)->saddr, |
233 | sizeof(sel.saddr)); | 237 | sizeof(sel.saddr)); |
234 | sel.prefixlen_s = 128; | 238 | sel.prefixlen_s = 128; |
235 | sel.family = AF_INET6; | 239 | sel.family = AF_INET6; |
@@ -253,11 +257,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
253 | u8 **nexthdr) | 257 | u8 **nexthdr) |
254 | { | 258 | { |
255 | u16 offset = sizeof(struct ipv6hdr); | 259 | u16 offset = sizeof(struct ipv6hdr); |
256 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 260 | struct ipv6_opt_hdr *exthdr = |
257 | unsigned int packet_len = skb->tail - skb->nh.raw; | 261 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
262 | const unsigned char *nh = skb_network_header(skb); | ||
263 | unsigned int packet_len = skb->tail - skb->network_header; | ||
258 | int found_rhdr = 0; | 264 | int found_rhdr = 0; |
259 | 265 | ||
260 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 266 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
261 | 267 | ||
262 | while (offset + 1 <= packet_len) { | 268 | while (offset + 1 <= packet_len) { |
263 | 269 | ||
@@ -288,7 +294,7 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
288 | 294 | ||
289 | offset += ipv6_optlen(exthdr); | 295 | offset += ipv6_optlen(exthdr); |
290 | *nexthdr = &exthdr->nexthdr; | 296 | *nexthdr = &exthdr->nexthdr; |
291 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 297 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
292 | } | 298 | } |
293 | 299 | ||
294 | return offset; | 300 | return offset; |
@@ -361,10 +367,10 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb) | |||
361 | iph = (struct ipv6hdr *)skb->data; | 367 | iph = (struct ipv6hdr *)skb->data; |
362 | iph->payload_len = htons(skb->len - sizeof(*iph)); | 368 | iph->payload_len = htons(skb->len - sizeof(*iph)); |
363 | 369 | ||
364 | nexthdr = *skb->nh.raw; | 370 | nexthdr = *skb_network_header(skb); |
365 | *skb->nh.raw = IPPROTO_ROUTING; | 371 | *skb_network_header(skb) = IPPROTO_ROUTING; |
366 | 372 | ||
367 | rt2 = (struct rt2_hdr *)skb->h.raw; | 373 | rt2 = (struct rt2_hdr *)skb_transport_header(skb); |
368 | rt2->rt_hdr.nexthdr = nexthdr; | 374 | rt2->rt_hdr.nexthdr = nexthdr; |
369 | rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1; | 375 | rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1; |
370 | rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2; | 376 | rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2; |
@@ -383,11 +389,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
383 | u8 **nexthdr) | 389 | u8 **nexthdr) |
384 | { | 390 | { |
385 | u16 offset = sizeof(struct ipv6hdr); | 391 | u16 offset = sizeof(struct ipv6hdr); |
386 | struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); | 392 | struct ipv6_opt_hdr *exthdr = |
387 | unsigned int packet_len = skb->tail - skb->nh.raw; | 393 | (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); |
394 | const unsigned char *nh = skb_network_header(skb); | ||
395 | unsigned int packet_len = skb->tail - skb->network_header; | ||
388 | int found_rhdr = 0; | 396 | int found_rhdr = 0; |
389 | 397 | ||
390 | *nexthdr = &skb->nh.ipv6h->nexthdr; | 398 | *nexthdr = &ipv6_hdr(skb)->nexthdr; |
391 | 399 | ||
392 | while (offset + 1 <= packet_len) { | 400 | while (offset + 1 <= packet_len) { |
393 | 401 | ||
@@ -397,7 +405,7 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
397 | case NEXTHDR_ROUTING: | 405 | case NEXTHDR_ROUTING: |
398 | if (offset + 3 <= packet_len) { | 406 | if (offset + 3 <= packet_len) { |
399 | struct ipv6_rt_hdr *rt; | 407 | struct ipv6_rt_hdr *rt; |
400 | rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset); | 408 | rt = (struct ipv6_rt_hdr *)(nh + offset); |
401 | if (rt->type != 0) | 409 | if (rt->type != 0) |
402 | return offset; | 410 | return offset; |
403 | } | 411 | } |
@@ -417,7 +425,7 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, | |||
417 | 425 | ||
418 | offset += ipv6_optlen(exthdr); | 426 | offset += ipv6_optlen(exthdr); |
419 | *nexthdr = &exthdr->nexthdr; | 427 | *nexthdr = &exthdr->nexthdr; |
420 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 428 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
421 | } | 429 | } |
422 | 430 | ||
423 | return offset; | 431 | return offset; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 121f31c283f8..d8b36451bada 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -319,6 +319,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d | |||
319 | return -EINVAL; | 319 | return -EINVAL; |
320 | } | 320 | } |
321 | 321 | ||
322 | EXPORT_SYMBOL(ndisc_mc_map); | ||
323 | |||
322 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev) | 324 | static u32 ndisc_hash(const void *pkey, const struct net_device *dev) |
323 | { | 325 | { |
324 | const u32 *p32 = pkey; | 326 | const u32 *p32 = pkey; |
@@ -425,36 +427,23 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type, | |||
425 | security_sk_classify_flow(ndisc_socket->sk, fl); | 427 | security_sk_classify_flow(ndisc_socket->sk, fl); |
426 | } | 428 | } |
427 | 429 | ||
428 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | 430 | static void __ndisc_send(struct net_device *dev, |
429 | struct in6_addr *daddr, struct in6_addr *solicited_addr, | 431 | struct neighbour *neigh, |
430 | int router, int solicited, int override, int inc_opt) | 432 | struct in6_addr *daddr, struct in6_addr *saddr, |
433 | struct icmp6hdr *icmp6h, struct in6_addr *target, | ||
434 | int llinfo, int icmp6_mib_outnd) | ||
431 | { | 435 | { |
432 | struct in6_addr tmpaddr; | ||
433 | struct inet6_ifaddr *ifp; | ||
434 | struct inet6_dev *idev; | ||
435 | struct flowi fl; | 436 | struct flowi fl; |
436 | struct dst_entry* dst; | 437 | struct dst_entry *dst; |
437 | struct sock *sk = ndisc_socket->sk; | 438 | struct sock *sk = ndisc_socket->sk; |
438 | struct in6_addr *src_addr; | ||
439 | struct nd_msg *msg; | ||
440 | int len; | ||
441 | struct sk_buff *skb; | 439 | struct sk_buff *skb; |
440 | struct icmp6hdr *hdr; | ||
441 | struct inet6_dev *idev; | ||
442 | int len; | ||
442 | int err; | 443 | int err; |
444 | u8 *opt; | ||
443 | 445 | ||
444 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | 446 | ndisc_flow_init(&fl, icmp6h->icmp6_type, saddr, daddr, |
445 | |||
446 | /* for anycast or proxy, solicited_addr != src_addr */ | ||
447 | ifp = ipv6_get_ifaddr(solicited_addr, dev, 1); | ||
448 | if (ifp) { | ||
449 | src_addr = solicited_addr; | ||
450 | in6_ifa_put(ifp); | ||
451 | } else { | ||
452 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) | ||
453 | return; | ||
454 | src_addr = &tmpaddr; | ||
455 | } | ||
456 | |||
457 | ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr, | ||
458 | dev->ifindex); | 447 | dev->ifindex); |
459 | 448 | ||
460 | dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); | 449 | dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); |
@@ -465,60 +454,57 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
465 | if (err < 0) | 454 | if (err < 0) |
466 | return; | 455 | return; |
467 | 456 | ||
468 | if (inc_opt) { | 457 | if (!dev->addr_len) |
469 | if (dev->addr_len) | 458 | llinfo = 0; |
470 | len += ndisc_opt_addr_space(dev); | 459 | |
471 | else | 460 | len = sizeof(struct icmp6hdr) + (target ? sizeof(*target) : 0); |
472 | inc_opt = 0; | 461 | if (llinfo) |
473 | } | 462 | len += ndisc_opt_addr_space(dev); |
474 | 463 | ||
475 | skb = sock_alloc_send_skb(sk, | 464 | skb = sock_alloc_send_skb(sk, |
476 | (MAX_HEADER + sizeof(struct ipv6hdr) + | 465 | (MAX_HEADER + sizeof(struct ipv6hdr) + |
477 | len + LL_RESERVED_SPACE(dev)), | 466 | len + LL_RESERVED_SPACE(dev)), |
478 | 1, &err); | 467 | 1, &err); |
479 | 468 | if (!skb) { | |
480 | if (skb == NULL) { | ||
481 | ND_PRINTK0(KERN_ERR | 469 | ND_PRINTK0(KERN_ERR |
482 | "ICMPv6 NA: %s() failed to allocate an skb.\n", | 470 | "ICMPv6 ND: %s() failed to allocate an skb.\n", |
483 | __FUNCTION__); | 471 | __FUNCTION__); |
484 | dst_release(dst); | 472 | dst_release(dst); |
485 | return; | 473 | return; |
486 | } | 474 | } |
487 | 475 | ||
488 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 476 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); |
489 | ip6_nd_hdr(sk, skb, dev, src_addr, daddr, IPPROTO_ICMPV6, len); | 477 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); |
490 | |||
491 | msg = (struct nd_msg *)skb_put(skb, len); | ||
492 | skb->h.raw = (unsigned char*)msg; | ||
493 | 478 | ||
494 | msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; | 479 | skb->transport_header = skb->tail; |
495 | msg->icmph.icmp6_code = 0; | 480 | skb_put(skb, len); |
496 | msg->icmph.icmp6_cksum = 0; | ||
497 | 481 | ||
498 | msg->icmph.icmp6_unused = 0; | 482 | hdr = (struct icmp6hdr *)skb_transport_header(skb); |
499 | msg->icmph.icmp6_router = router; | 483 | memcpy(hdr, icmp6h, sizeof(*hdr)); |
500 | msg->icmph.icmp6_solicited = solicited; | ||
501 | msg->icmph.icmp6_override = override; | ||
502 | 484 | ||
503 | /* Set the target address. */ | 485 | opt = skb_transport_header(skb) + sizeof(struct icmp6hdr); |
504 | ipv6_addr_copy(&msg->target, solicited_addr); | 486 | if (target) { |
487 | ipv6_addr_copy((struct in6_addr *)opt, target); | ||
488 | opt += sizeof(*target); | ||
489 | } | ||
505 | 490 | ||
506 | if (inc_opt) | 491 | if (llinfo) |
507 | ndisc_fill_addr_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, | 492 | ndisc_fill_addr_option(opt, llinfo, dev->dev_addr, |
508 | dev->addr_len, dev->type); | 493 | dev->addr_len, dev->type); |
509 | 494 | ||
510 | /* checksum */ | 495 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len, |
511 | msg->icmph.icmp6_cksum = csum_ipv6_magic(src_addr, daddr, len, | 496 | IPPROTO_ICMPV6, |
512 | IPPROTO_ICMPV6, | 497 | csum_partial((__u8 *) hdr, |
513 | csum_partial((__u8 *) msg, | 498 | len, 0)); |
514 | len, 0)); | ||
515 | 499 | ||
516 | skb->dst = dst; | 500 | skb->dst = dst; |
501 | |||
517 | idev = in6_dev_get(dst->dev); | 502 | idev = in6_dev_get(dst->dev); |
518 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | 503 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
504 | |||
519 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 505 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
520 | if (!err) { | 506 | if (!err) { |
521 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); | 507 | ICMP6_INC_STATS(idev, icmp6_mib_outnd); |
522 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | 508 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); |
523 | } | 509 | } |
524 | 510 | ||
@@ -526,165 +512,95 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
526 | in6_dev_put(idev); | 512 | in6_dev_put(idev); |
527 | } | 513 | } |
528 | 514 | ||
515 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | ||
516 | struct in6_addr *daddr, struct in6_addr *solicited_addr, | ||
517 | int router, int solicited, int override, int inc_opt) | ||
518 | { | ||
519 | struct in6_addr tmpaddr; | ||
520 | struct inet6_ifaddr *ifp; | ||
521 | struct in6_addr *src_addr; | ||
522 | struct icmp6hdr icmp6h = { | ||
523 | .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, | ||
524 | }; | ||
525 | |||
526 | /* for anycast or proxy, solicited_addr != src_addr */ | ||
527 | ifp = ipv6_get_ifaddr(solicited_addr, dev, 1); | ||
528 | if (ifp) { | ||
529 | src_addr = solicited_addr; | ||
530 | if (ifp->flags & IFA_F_OPTIMISTIC) | ||
531 | override = 0; | ||
532 | in6_ifa_put(ifp); | ||
533 | } else { | ||
534 | if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) | ||
535 | return; | ||
536 | src_addr = &tmpaddr; | ||
537 | } | ||
538 | |||
539 | icmp6h.icmp6_router = router; | ||
540 | icmp6h.icmp6_solicited = solicited; | ||
541 | icmp6h.icmp6_override = override; | ||
542 | |||
543 | __ndisc_send(dev, neigh, daddr, src_addr, | ||
544 | &icmp6h, solicited_addr, | ||
545 | inc_opt ? ND_OPT_TARGET_LL_ADDR : 0, | ||
546 | ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); | ||
547 | } | ||
548 | |||
529 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | 549 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, |
530 | struct in6_addr *solicit, | 550 | struct in6_addr *solicit, |
531 | struct in6_addr *daddr, struct in6_addr *saddr) | 551 | struct in6_addr *daddr, struct in6_addr *saddr) |
532 | { | 552 | { |
533 | struct flowi fl; | ||
534 | struct dst_entry* dst; | ||
535 | struct inet6_dev *idev; | ||
536 | struct sock *sk = ndisc_socket->sk; | ||
537 | struct sk_buff *skb; | ||
538 | struct nd_msg *msg; | ||
539 | struct in6_addr addr_buf; | 553 | struct in6_addr addr_buf; |
540 | int len; | 554 | struct icmp6hdr icmp6h = { |
541 | int err; | 555 | .icmp6_type = NDISC_NEIGHBOUR_SOLICITATION, |
542 | int send_llinfo; | 556 | }; |
543 | 557 | ||
544 | if (saddr == NULL) { | 558 | if (saddr == NULL) { |
545 | if (ipv6_get_lladdr(dev, &addr_buf)) | 559 | if (ipv6_get_lladdr(dev, &addr_buf, |
560 | (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))) | ||
546 | return; | 561 | return; |
547 | saddr = &addr_buf; | 562 | saddr = &addr_buf; |
548 | } | 563 | } |
549 | 564 | ||
550 | ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr, | 565 | __ndisc_send(dev, neigh, daddr, saddr, |
551 | dev->ifindex); | 566 | &icmp6h, solicit, |
552 | 567 | !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0, | |
553 | dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); | 568 | ICMP6_MIB_OUTNEIGHBORSOLICITS); |
554 | if (!dst) | ||
555 | return; | ||
556 | |||
557 | err = xfrm_lookup(&dst, &fl, NULL, 0); | ||
558 | if (err < 0) | ||
559 | return; | ||
560 | |||
561 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | ||
562 | send_llinfo = dev->addr_len && !ipv6_addr_any(saddr); | ||
563 | if (send_llinfo) | ||
564 | len += ndisc_opt_addr_space(dev); | ||
565 | |||
566 | skb = sock_alloc_send_skb(sk, | ||
567 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
568 | len + LL_RESERVED_SPACE(dev)), | ||
569 | 1, &err); | ||
570 | if (skb == NULL) { | ||
571 | ND_PRINTK0(KERN_ERR | ||
572 | "ICMPv6 NA: %s() failed to allocate an skb.\n", | ||
573 | __FUNCTION__); | ||
574 | dst_release(dst); | ||
575 | return; | ||
576 | } | ||
577 | |||
578 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | ||
579 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); | ||
580 | |||
581 | msg = (struct nd_msg *)skb_put(skb, len); | ||
582 | skb->h.raw = (unsigned char*)msg; | ||
583 | msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION; | ||
584 | msg->icmph.icmp6_code = 0; | ||
585 | msg->icmph.icmp6_cksum = 0; | ||
586 | msg->icmph.icmp6_unused = 0; | ||
587 | |||
588 | /* Set the target address. */ | ||
589 | ipv6_addr_copy(&msg->target, solicit); | ||
590 | |||
591 | if (send_llinfo) | ||
592 | ndisc_fill_addr_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, | ||
593 | dev->addr_len, dev->type); | ||
594 | |||
595 | /* checksum */ | ||
596 | msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, | ||
597 | daddr, len, | ||
598 | IPPROTO_ICMPV6, | ||
599 | csum_partial((__u8 *) msg, | ||
600 | len, 0)); | ||
601 | /* send it! */ | ||
602 | skb->dst = dst; | ||
603 | idev = in6_dev_get(dst->dev); | ||
604 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | ||
605 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | ||
606 | if (!err) { | ||
607 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); | ||
608 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | ||
609 | } | ||
610 | |||
611 | if (likely(idev != NULL)) | ||
612 | in6_dev_put(idev); | ||
613 | } | 569 | } |
614 | 570 | ||
615 | void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | 571 | void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, |
616 | struct in6_addr *daddr) | 572 | struct in6_addr *daddr) |
617 | { | 573 | { |
618 | struct flowi fl; | 574 | struct icmp6hdr icmp6h = { |
619 | struct dst_entry* dst; | 575 | .icmp6_type = NDISC_ROUTER_SOLICITATION, |
620 | struct inet6_dev *idev; | 576 | }; |
621 | struct sock *sk = ndisc_socket->sk; | 577 | int send_sllao = dev->addr_len; |
622 | struct sk_buff *skb; | ||
623 | struct icmp6hdr *hdr; | ||
624 | __u8 * opt; | ||
625 | int len; | ||
626 | int err; | ||
627 | |||
628 | ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr, | ||
629 | dev->ifindex); | ||
630 | |||
631 | dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output); | ||
632 | if (!dst) | ||
633 | return; | ||
634 | |||
635 | err = xfrm_lookup(&dst, &fl, NULL, 0); | ||
636 | if (err < 0) | ||
637 | return; | ||
638 | |||
639 | len = sizeof(struct icmp6hdr); | ||
640 | if (dev->addr_len) | ||
641 | len += ndisc_opt_addr_space(dev); | ||
642 | |||
643 | skb = sock_alloc_send_skb(sk, | ||
644 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
645 | len + LL_RESERVED_SPACE(dev)), | ||
646 | 1, &err); | ||
647 | if (skb == NULL) { | ||
648 | ND_PRINTK0(KERN_ERR | ||
649 | "ICMPv6 RS: %s() failed to allocate an skb.\n", | ||
650 | __FUNCTION__); | ||
651 | dst_release(dst); | ||
652 | return; | ||
653 | } | ||
654 | |||
655 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | ||
656 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); | ||
657 | |||
658 | hdr = (struct icmp6hdr *)skb_put(skb, len); | ||
659 | skb->h.raw = (unsigned char*)hdr; | ||
660 | hdr->icmp6_type = NDISC_ROUTER_SOLICITATION; | ||
661 | hdr->icmp6_code = 0; | ||
662 | hdr->icmp6_cksum = 0; | ||
663 | hdr->icmp6_unused = 0; | ||
664 | |||
665 | opt = (u8*) (hdr + 1); | ||
666 | |||
667 | if (dev->addr_len) | ||
668 | ndisc_fill_addr_option(opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, | ||
669 | dev->addr_len, dev->type); | ||
670 | |||
671 | /* checksum */ | ||
672 | hdr->icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr, daddr, len, | ||
673 | IPPROTO_ICMPV6, | ||
674 | csum_partial((__u8 *) hdr, len, 0)); | ||
675 | 578 | ||
676 | /* send it! */ | 579 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
677 | skb->dst = dst; | 580 | /* |
678 | idev = in6_dev_get(dst->dev); | 581 | * According to section 2.2 of RFC 4429, we must not |
679 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); | 582 | * send router solicitations with a sllao from |
680 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 583 | * optimistic addresses, but we may send the solicitation |
681 | if (!err) { | 584 | * if we don't include the sllao. So here we check |
682 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); | 585 | * if our address is optimistic, and if so, we |
683 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | 586 | * supress the inclusion of the sllao. |
587 | */ | ||
588 | if (send_sllao) { | ||
589 | struct inet6_ifaddr *ifp = ipv6_get_ifaddr(saddr, dev, 1); | ||
590 | if (ifp) { | ||
591 | if (ifp->flags & IFA_F_OPTIMISTIC) { | ||
592 | send_sllao = 0; | ||
593 | } | ||
594 | in6_ifa_put(ifp); | ||
595 | } else { | ||
596 | send_sllao = 0; | ||
597 | } | ||
684 | } | 598 | } |
685 | 599 | #endif | |
686 | if (likely(idev != NULL)) | 600 | __ndisc_send(dev, NULL, daddr, saddr, |
687 | in6_dev_put(idev); | 601 | &icmp6h, NULL, |
602 | send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0, | ||
603 | ICMP6_MIB_OUTROUTERSOLICITS); | ||
688 | } | 604 | } |
689 | 605 | ||
690 | 606 | ||
@@ -708,8 +624,8 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
708 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; | 624 | struct in6_addr *target = (struct in6_addr *)&neigh->primary_key; |
709 | int probes = atomic_read(&neigh->probes); | 625 | int probes = atomic_read(&neigh->probes); |
710 | 626 | ||
711 | if (skb && ipv6_chk_addr(&skb->nh.ipv6h->saddr, dev, 1)) | 627 | if (skb && ipv6_chk_addr(&ipv6_hdr(skb)->saddr, dev, 1)) |
712 | saddr = &skb->nh.ipv6h->saddr; | 628 | saddr = &ipv6_hdr(skb)->saddr; |
713 | 629 | ||
714 | if ((probes -= neigh->parms->ucast_probes) < 0) { | 630 | if ((probes -= neigh->parms->ucast_probes) < 0) { |
715 | if (!(neigh->nud_state & NUD_VALID)) { | 631 | if (!(neigh->nud_state & NUD_VALID)) { |
@@ -732,11 +648,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
732 | 648 | ||
733 | static void ndisc_recv_ns(struct sk_buff *skb) | 649 | static void ndisc_recv_ns(struct sk_buff *skb) |
734 | { | 650 | { |
735 | struct nd_msg *msg = (struct nd_msg *)skb->h.raw; | 651 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
736 | struct in6_addr *saddr = &skb->nh.ipv6h->saddr; | 652 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
737 | struct in6_addr *daddr = &skb->nh.ipv6h->daddr; | 653 | struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
738 | u8 *lladdr = NULL; | 654 | u8 *lladdr = NULL; |
739 | u32 ndoptlen = skb->tail - msg->opt; | 655 | u32 ndoptlen = skb->tail - (skb->transport_header + |
656 | offsetof(struct nd_msg, opt)); | ||
740 | struct ndisc_options ndopts; | 657 | struct ndisc_options ndopts; |
741 | struct net_device *dev = skb->dev; | 658 | struct net_device *dev = skb->dev; |
742 | struct inet6_ifaddr *ifp; | 659 | struct inet6_ifaddr *ifp; |
@@ -796,28 +713,40 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
796 | inc = ipv6_addr_is_multicast(daddr); | 713 | inc = ipv6_addr_is_multicast(daddr); |
797 | 714 | ||
798 | if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) { | 715 | if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) { |
799 | if (ifp->flags & IFA_F_TENTATIVE) { | 716 | |
800 | /* Address is tentative. If the source | 717 | if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) { |
801 | is unspecified address, it is someone | 718 | if (dad) { |
802 | does DAD, otherwise we ignore solicitations | 719 | if (dev->type == ARPHRD_IEEE802_TR) { |
803 | until DAD timer expires. | 720 | const unsigned char *sadr; |
804 | */ | 721 | sadr = skb_mac_header(skb); |
805 | if (!dad) | 722 | if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && |
723 | sadr[9] == dev->dev_addr[1] && | ||
724 | sadr[10] == dev->dev_addr[2] && | ||
725 | sadr[11] == dev->dev_addr[3] && | ||
726 | sadr[12] == dev->dev_addr[4] && | ||
727 | sadr[13] == dev->dev_addr[5]) { | ||
728 | /* looped-back to us */ | ||
729 | goto out; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | /* | ||
734 | * We are colliding with another node | ||
735 | * who is doing DAD | ||
736 | * so fail our DAD process | ||
737 | */ | ||
738 | addrconf_dad_failure(ifp); | ||
806 | goto out; | 739 | goto out; |
807 | if (dev->type == ARPHRD_IEEE802_TR) { | 740 | } else { |
808 | unsigned char *sadr = skb->mac.raw; | 741 | /* |
809 | if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 && | 742 | * This is not a dad solicitation. |
810 | sadr[9] == dev->dev_addr[1] && | 743 | * If we are an optimistic node, |
811 | sadr[10] == dev->dev_addr[2] && | 744 | * we should respond. |
812 | sadr[11] == dev->dev_addr[3] && | 745 | * Otherwise, we should ignore it. |
813 | sadr[12] == dev->dev_addr[4] && | 746 | */ |
814 | sadr[13] == dev->dev_addr[5]) { | 747 | if (!(ifp->flags & IFA_F_OPTIMISTIC)) |
815 | /* looped-back to us */ | ||
816 | goto out; | 748 | goto out; |
817 | } | ||
818 | } | 749 | } |
819 | addrconf_dad_failure(ifp); | ||
820 | return; | ||
821 | } | 750 | } |
822 | 751 | ||
823 | idev = ifp->idev; | 752 | idev = ifp->idev; |
@@ -898,11 +827,12 @@ out: | |||
898 | 827 | ||
899 | static void ndisc_recv_na(struct sk_buff *skb) | 828 | static void ndisc_recv_na(struct sk_buff *skb) |
900 | { | 829 | { |
901 | struct nd_msg *msg = (struct nd_msg *)skb->h.raw; | 830 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
902 | struct in6_addr *saddr = &skb->nh.ipv6h->saddr; | 831 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
903 | struct in6_addr *daddr = &skb->nh.ipv6h->daddr; | 832 | struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
904 | u8 *lladdr = NULL; | 833 | u8 *lladdr = NULL; |
905 | u32 ndoptlen = skb->tail - msg->opt; | 834 | u32 ndoptlen = skb->tail - (skb->transport_header + |
835 | offsetof(struct nd_msg, opt)); | ||
906 | struct ndisc_options ndopts; | 836 | struct ndisc_options ndopts; |
907 | struct net_device *dev = skb->dev; | 837 | struct net_device *dev = skb->dev; |
908 | struct inet6_ifaddr *ifp; | 838 | struct inet6_ifaddr *ifp; |
@@ -1000,11 +930,11 @@ out: | |||
1000 | 930 | ||
1001 | static void ndisc_recv_rs(struct sk_buff *skb) | 931 | static void ndisc_recv_rs(struct sk_buff *skb) |
1002 | { | 932 | { |
1003 | struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw; | 933 | struct rs_msg *rs_msg = (struct rs_msg *)skb_transport_header(skb); |
1004 | unsigned long ndoptlen = skb->len - sizeof(*rs_msg); | 934 | unsigned long ndoptlen = skb->len - sizeof(*rs_msg); |
1005 | struct neighbour *neigh; | 935 | struct neighbour *neigh; |
1006 | struct inet6_dev *idev; | 936 | struct inet6_dev *idev; |
1007 | struct in6_addr *saddr = &skb->nh.ipv6h->saddr; | 937 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
1008 | struct ndisc_options ndopts; | 938 | struct ndisc_options ndopts; |
1009 | u8 *lladdr = NULL; | 939 | u8 *lladdr = NULL; |
1010 | 940 | ||
@@ -1057,7 +987,7 @@ out: | |||
1057 | 987 | ||
1058 | static void ndisc_router_discovery(struct sk_buff *skb) | 988 | static void ndisc_router_discovery(struct sk_buff *skb) |
1059 | { | 989 | { |
1060 | struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw; | 990 | struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); |
1061 | struct neighbour *neigh = NULL; | 991 | struct neighbour *neigh = NULL; |
1062 | struct inet6_dev *in6_dev; | 992 | struct inet6_dev *in6_dev; |
1063 | struct rt6_info *rt = NULL; | 993 | struct rt6_info *rt = NULL; |
@@ -1068,9 +998,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1068 | 998 | ||
1069 | __u8 * opt = (__u8 *)(ra_msg + 1); | 999 | __u8 * opt = (__u8 *)(ra_msg + 1); |
1070 | 1000 | ||
1071 | optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg); | 1001 | optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg); |
1072 | 1002 | ||
1073 | if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1003 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
1074 | ND_PRINTK2(KERN_WARNING | 1004 | ND_PRINTK2(KERN_WARNING |
1075 | "ICMPv6 RA: source address is not link-local.\n"); | 1005 | "ICMPv6 RA: source address is not link-local.\n"); |
1076 | return; | 1006 | return; |
@@ -1136,7 +1066,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1136 | pref = ICMPV6_ROUTER_PREF_MEDIUM; | 1066 | pref = ICMPV6_ROUTER_PREF_MEDIUM; |
1137 | #endif | 1067 | #endif |
1138 | 1068 | ||
1139 | rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); | 1069 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); |
1140 | 1070 | ||
1141 | if (rt) | 1071 | if (rt) |
1142 | neigh = rt->rt6i_nexthop; | 1072 | neigh = rt->rt6i_nexthop; |
@@ -1151,7 +1081,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1151 | ND_PRINTK3(KERN_DEBUG | 1081 | ND_PRINTK3(KERN_DEBUG |
1152 | "ICMPv6 RA: adding default router.\n"); | 1082 | "ICMPv6 RA: adding default router.\n"); |
1153 | 1083 | ||
1154 | rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref); | 1084 | rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); |
1155 | if (rt == NULL) { | 1085 | if (rt == NULL) { |
1156 | ND_PRINTK0(KERN_ERR | 1086 | ND_PRINTK0(KERN_ERR |
1157 | "ICMPv6 RA: %s() failed to add default route.\n", | 1087 | "ICMPv6 RA: %s() failed to add default route.\n", |
@@ -1223,7 +1153,7 @@ skip_defrtr: | |||
1223 | */ | 1153 | */ |
1224 | 1154 | ||
1225 | if (!neigh) | 1155 | if (!neigh) |
1226 | neigh = __neigh_lookup(&nd_tbl, &skb->nh.ipv6h->saddr, | 1156 | neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr, |
1227 | skb->dev, 1); | 1157 | skb->dev, 1); |
1228 | if (neigh) { | 1158 | if (neigh) { |
1229 | u8 *lladdr = NULL; | 1159 | u8 *lladdr = NULL; |
@@ -1252,7 +1182,7 @@ skip_defrtr: | |||
1252 | if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) | 1182 | if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) |
1253 | continue; | 1183 | continue; |
1254 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, | 1184 | rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3, |
1255 | &skb->nh.ipv6h->saddr); | 1185 | &ipv6_hdr(skb)->saddr); |
1256 | } | 1186 | } |
1257 | } | 1187 | } |
1258 | #endif | 1188 | #endif |
@@ -1311,13 +1241,13 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1311 | int optlen; | 1241 | int optlen; |
1312 | u8 *lladdr = NULL; | 1242 | u8 *lladdr = NULL; |
1313 | 1243 | ||
1314 | if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1244 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
1315 | ND_PRINTK2(KERN_WARNING | 1245 | ND_PRINTK2(KERN_WARNING |
1316 | "ICMPv6 Redirect: source address is not link-local.\n"); | 1246 | "ICMPv6 Redirect: source address is not link-local.\n"); |
1317 | return; | 1247 | return; |
1318 | } | 1248 | } |
1319 | 1249 | ||
1320 | optlen = skb->tail - skb->h.raw; | 1250 | optlen = skb->tail - skb->transport_header; |
1321 | optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); | 1251 | optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); |
1322 | 1252 | ||
1323 | if (optlen < 0) { | 1253 | if (optlen < 0) { |
@@ -1326,7 +1256,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1326 | return; | 1256 | return; |
1327 | } | 1257 | } |
1328 | 1258 | ||
1329 | icmph = (struct icmp6hdr *) skb->h.raw; | 1259 | icmph = icmp6_hdr(skb); |
1330 | target = (struct in6_addr *) (icmph + 1); | 1260 | target = (struct in6_addr *) (icmph + 1); |
1331 | dest = target + 1; | 1261 | dest = target + 1; |
1332 | 1262 | ||
@@ -1376,8 +1306,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1376 | 1306 | ||
1377 | neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); | 1307 | neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); |
1378 | if (neigh) { | 1308 | if (neigh) { |
1379 | rt6_redirect(dest, &skb->nh.ipv6h->daddr, | 1309 | rt6_redirect(dest, &ipv6_hdr(skb)->daddr, |
1380 | &skb->nh.ipv6h->saddr, neigh, lladdr, | 1310 | &ipv6_hdr(skb)->saddr, neigh, lladdr, |
1381 | on_link); | 1311 | on_link); |
1382 | neigh_release(neigh); | 1312 | neigh_release(neigh); |
1383 | } | 1313 | } |
@@ -1406,21 +1336,21 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1406 | 1336 | ||
1407 | dev = skb->dev; | 1337 | dev = skb->dev; |
1408 | 1338 | ||
1409 | if (ipv6_get_lladdr(dev, &saddr_buf)) { | 1339 | if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) { |
1410 | ND_PRINTK2(KERN_WARNING | 1340 | ND_PRINTK2(KERN_WARNING |
1411 | "ICMPv6 Redirect: no link-local address on %s\n", | 1341 | "ICMPv6 Redirect: no link-local address on %s\n", |
1412 | dev->name); | 1342 | dev->name); |
1413 | return; | 1343 | return; |
1414 | } | 1344 | } |
1415 | 1345 | ||
1416 | if (!ipv6_addr_equal(&skb->nh.ipv6h->daddr, target) && | 1346 | if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && |
1417 | !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { | 1347 | !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { |
1418 | ND_PRINTK2(KERN_WARNING | 1348 | ND_PRINTK2(KERN_WARNING |
1419 | "ICMPv6 Redirect: target address is not link-local.\n"); | 1349 | "ICMPv6 Redirect: target address is not link-local.\n"); |
1420 | return; | 1350 | return; |
1421 | } | 1351 | } |
1422 | 1352 | ||
1423 | ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr, | 1353 | ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1424 | dev->ifindex); | 1354 | dev->ifindex); |
1425 | 1355 | ||
1426 | dst = ip6_route_output(NULL, &fl); | 1356 | dst = ip6_route_output(NULL, &fl); |
@@ -1475,11 +1405,12 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1475 | hlen = 0; | 1405 | hlen = 0; |
1476 | 1406 | ||
1477 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1407 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); |
1478 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr, | 1408 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1479 | IPPROTO_ICMPV6, len); | 1409 | IPPROTO_ICMPV6, len); |
1480 | 1410 | ||
1481 | icmph = (struct icmp6hdr *)skb_put(buff, len); | 1411 | skb_set_transport_header(buff, skb_tail_pointer(buff) - buff->data); |
1482 | buff->h.raw = (unsigned char*)icmph; | 1412 | skb_put(buff, len); |
1413 | icmph = icmp6_hdr(buff); | ||
1483 | 1414 | ||
1484 | memset(icmph, 0, sizeof(struct icmp6hdr)); | 1415 | memset(icmph, 0, sizeof(struct icmp6hdr)); |
1485 | icmph->icmp6_type = NDISC_REDIRECT; | 1416 | icmph->icmp6_type = NDISC_REDIRECT; |
@@ -1491,7 +1422,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1491 | addrp = (struct in6_addr *)(icmph + 1); | 1422 | addrp = (struct in6_addr *)(icmph + 1); |
1492 | ipv6_addr_copy(addrp, target); | 1423 | ipv6_addr_copy(addrp, target); |
1493 | addrp++; | 1424 | addrp++; |
1494 | ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr); | 1425 | ipv6_addr_copy(addrp, &ipv6_hdr(skb)->daddr); |
1495 | 1426 | ||
1496 | opt = (u8*) (addrp + 1); | 1427 | opt = (u8*) (addrp + 1); |
1497 | 1428 | ||
@@ -1512,9 +1443,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1512 | *(opt++) = (rd_len >> 3); | 1443 | *(opt++) = (rd_len >> 3); |
1513 | opt += 6; | 1444 | opt += 6; |
1514 | 1445 | ||
1515 | memcpy(opt, skb->nh.ipv6h, rd_len - 8); | 1446 | memcpy(opt, ipv6_hdr(skb), rd_len - 8); |
1516 | 1447 | ||
1517 | icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &skb->nh.ipv6h->saddr, | 1448 | icmph->icmp6_cksum = csum_ipv6_magic(&saddr_buf, &ipv6_hdr(skb)->saddr, |
1518 | len, IPPROTO_ICMPV6, | 1449 | len, IPPROTO_ICMPV6, |
1519 | csum_partial((u8 *) icmph, len, 0)); | 1450 | csum_partial((u8 *) icmph, len, 0)); |
1520 | 1451 | ||
@@ -1544,14 +1475,14 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1544 | if (!pskb_may_pull(skb, skb->len)) | 1475 | if (!pskb_may_pull(skb, skb->len)) |
1545 | return 0; | 1476 | return 0; |
1546 | 1477 | ||
1547 | msg = (struct nd_msg *) skb->h.raw; | 1478 | msg = (struct nd_msg *)skb_transport_header(skb); |
1548 | 1479 | ||
1549 | __skb_push(skb, skb->data-skb->h.raw); | 1480 | __skb_push(skb, skb->data - skb_transport_header(skb)); |
1550 | 1481 | ||
1551 | if (skb->nh.ipv6h->hop_limit != 255) { | 1482 | if (ipv6_hdr(skb)->hop_limit != 255) { |
1552 | ND_PRINTK2(KERN_WARNING | 1483 | ND_PRINTK2(KERN_WARNING |
1553 | "ICMPv6 NDISC: invalid hop-limit: %d\n", | 1484 | "ICMPv6 NDISC: invalid hop-limit: %d\n", |
1554 | skb->nh.ipv6h->hop_limit); | 1485 | ipv6_hdr(skb)->hop_limit); |
1555 | return 0; | 1486 | return 0; |
1556 | } | 1487 | } |
1557 | 1488 | ||
@@ -1584,7 +1515,7 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1584 | case NDISC_REDIRECT: | 1515 | case NDISC_REDIRECT: |
1585 | ndisc_redirect_rcv(skb); | 1516 | ndisc_redirect_rcv(skb); |
1586 | break; | 1517 | break; |
1587 | }; | 1518 | } |
1588 | 1519 | ||
1589 | return 0; | 1520 | return 0; |
1590 | } | 1521 | } |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 1c405dd30c67..38b149613915 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | int ip6_route_me_harder(struct sk_buff *skb) | 12 | int ip6_route_me_harder(struct sk_buff *skb) |
13 | { | 13 | { |
14 | struct ipv6hdr *iph = skb->nh.ipv6h; | 14 | struct ipv6hdr *iph = ipv6_hdr(skb); |
15 | struct dst_entry *dst; | 15 | struct dst_entry *dst; |
16 | struct flowi fl = { | 16 | struct flowi fl = { |
17 | .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | 17 | .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, |
@@ -61,7 +61,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) | |||
61 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 61 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
62 | 62 | ||
63 | if (info->hook == NF_IP6_LOCAL_OUT) { | 63 | if (info->hook == NF_IP6_LOCAL_OUT) { |
64 | struct ipv6hdr *iph = skb->nh.ipv6h; | 64 | struct ipv6hdr *iph = ipv6_hdr(skb); |
65 | 65 | ||
66 | rt_info->daddr = iph->daddr; | 66 | rt_info->daddr = iph->daddr; |
67 | rt_info->saddr = iph->saddr; | 67 | rt_info->saddr = iph->saddr; |
@@ -73,7 +73,7 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
74 | 74 | ||
75 | if (info->hook == NF_IP6_LOCAL_OUT) { | 75 | if (info->hook == NF_IP6_LOCAL_OUT) { |
76 | struct ipv6hdr *iph = (*pskb)->nh.ipv6h; | 76 | struct ipv6hdr *iph = ipv6_hdr(*pskb); |
77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | 77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || |
78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) | 78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) |
79 | return ip6_route_me_harder(*pskb); | 79 | return ip6_route_me_harder(*pskb); |
@@ -84,7 +84,7 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
84 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | 84 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
85 | unsigned int dataoff, u_int8_t protocol) | 85 | unsigned int dataoff, u_int8_t protocol) |
86 | { | 86 | { |
87 | struct ipv6hdr *ip6h = skb->nh.ipv6h; | 87 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
88 | __sum16 csum = 0; | 88 | __sum16 csum = 0; |
89 | 89 | ||
90 | switch (skb->ip_summed) { | 90 | switch (skb->ip_summed) { |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index fdb30a5916e5..0004db38af6d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -11,18 +11,6 @@ | |||
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
14 | * | ||
15 | * 2001-11-06: First try. Working with ip_queue.c for IPv4 and trying | ||
16 | * to adapt it to IPv6 | ||
17 | * HEAVILY based in ipqueue.c by James Morris. It's just | ||
18 | * a little modified version of it, so he's nearly the | ||
19 | * real coder of this. | ||
20 | * Few changes needed, mainly the hard_routing code and | ||
21 | * the netlink socket protocol (we're NETLINK_IP6_FW). | ||
22 | * 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c] | ||
23 | * 2005-02-04: Added /proc counter for dropped packets; fixed so | ||
24 | * packets aren't delivered to user space if they're going | ||
25 | * to be dropped. | ||
26 | */ | 14 | */ |
27 | #include <linux/module.h> | 15 | #include <linux/module.h> |
28 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
@@ -189,12 +177,13 @@ ipq_flush(int verdict) | |||
189 | static struct sk_buff * | 177 | static struct sk_buff * |
190 | ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | 178 | ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) |
191 | { | 179 | { |
192 | unsigned char *old_tail; | 180 | sk_buff_data_t old_tail; |
193 | size_t size = 0; | 181 | size_t size = 0; |
194 | size_t data_len = 0; | 182 | size_t data_len = 0; |
195 | struct sk_buff *skb; | 183 | struct sk_buff *skb; |
196 | struct ipq_packet_msg *pmsg; | 184 | struct ipq_packet_msg *pmsg; |
197 | struct nlmsghdr *nlh; | 185 | struct nlmsghdr *nlh; |
186 | struct timeval tv; | ||
198 | 187 | ||
199 | read_lock_bh(&queue_lock); | 188 | read_lock_bh(&queue_lock); |
200 | 189 | ||
@@ -232,15 +221,16 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | |||
232 | if (!skb) | 221 | if (!skb) |
233 | goto nlmsg_failure; | 222 | goto nlmsg_failure; |
234 | 223 | ||
235 | old_tail= skb->tail; | 224 | old_tail = skb->tail; |
236 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); | 225 | nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); |
237 | pmsg = NLMSG_DATA(nlh); | 226 | pmsg = NLMSG_DATA(nlh); |
238 | memset(pmsg, 0, sizeof(*pmsg)); | 227 | memset(pmsg, 0, sizeof(*pmsg)); |
239 | 228 | ||
240 | pmsg->packet_id = (unsigned long )entry; | 229 | pmsg->packet_id = (unsigned long )entry; |
241 | pmsg->data_len = data_len; | 230 | pmsg->data_len = data_len; |
242 | pmsg->timestamp_sec = entry->skb->tstamp.off_sec; | 231 | tv = ktime_to_timeval(entry->skb->tstamp); |
243 | pmsg->timestamp_usec = entry->skb->tstamp.off_usec; | 232 | pmsg->timestamp_sec = tv.tv_sec; |
233 | pmsg->timestamp_usec = tv.tv_usec; | ||
244 | pmsg->mark = entry->skb->mark; | 234 | pmsg->mark = entry->skb->mark; |
245 | pmsg->hook = entry->info->hook; | 235 | pmsg->hook = entry->info->hook; |
246 | pmsg->hw_protocol = entry->skb->protocol; | 236 | pmsg->hw_protocol = entry->skb->protocol; |
@@ -376,7 +366,7 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
376 | } | 366 | } |
377 | if (!skb_make_writable(&e->skb, v->data_len)) | 367 | if (!skb_make_writable(&e->skb, v->data_len)) |
378 | return -ENOMEM; | 368 | return -ENOMEM; |
379 | memcpy(e->skb->data, v->payload, v->data_len); | 369 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
380 | e->skb->ip_summed = CHECKSUM_NONE; | 370 | e->skb->ip_summed = CHECKSUM_NONE; |
381 | 371 | ||
382 | return 0; | 372 | return 0; |
@@ -485,7 +475,7 @@ ipq_rcv_skb(struct sk_buff *skb) | |||
485 | if (skblen < sizeof(*nlh)) | 475 | if (skblen < sizeof(*nlh)) |
486 | return; | 476 | return; |
487 | 477 | ||
488 | nlh = (struct nlmsghdr *)skb->data; | 478 | nlh = nlmsg_hdr(skb); |
489 | nlmsglen = nlh->nlmsg_len; | 479 | nlmsglen = nlh->nlmsg_len; |
490 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) | 480 | if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) |
491 | return; | 481 | return; |
@@ -667,7 +657,7 @@ static int __init ip6_queue_init(void) | |||
667 | struct proc_dir_entry *proc; | 657 | struct proc_dir_entry *proc; |
668 | 658 | ||
669 | netlink_register_notifier(&ipq_nl_notifier); | 659 | netlink_register_notifier(&ipq_nl_notifier); |
670 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, | 660 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, NULL, |
671 | THIS_MODULE); | 661 | THIS_MODULE); |
672 | if (ipqnl == NULL) { | 662 | if (ipqnl == NULL) { |
673 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); | 663 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7c512e13f956..9aa624026688 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -7,15 +7,6 @@ | |||
7 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | ||
11 | * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> | ||
12 | * - increase module usage count as soon as we have rules inside | ||
13 | * a table | ||
14 | * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> | ||
15 | * - new extension header parser code | ||
16 | * 15 Oct 2005 Harald Welte <laforge@netfilter.org> | ||
17 | * - Unification of {ip,ip6}_tables into x_tables | ||
18 | * - Removed tcp and udp code, since it's not ipv6 specific | ||
19 | */ | 10 | */ |
20 | 11 | ||
21 | #include <linux/capability.h> | 12 | #include <linux/capability.h> |
@@ -115,7 +106,7 @@ ip6_packet_match(const struct sk_buff *skb, | |||
115 | { | 106 | { |
116 | size_t i; | 107 | size_t i; |
117 | unsigned long ret; | 108 | unsigned long ret; |
118 | const struct ipv6hdr *ipv6 = skb->nh.ipv6h; | 109 | const struct ipv6hdr *ipv6 = ipv6_hdr(skb); |
119 | 110 | ||
120 | #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg)) | 111 | #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg)) |
121 | 112 | ||
@@ -301,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
301 | goto no_match; | 292 | goto no_match; |
302 | 293 | ||
303 | ADD_COUNTER(e->counters, | 294 | ADD_COUNTER(e->counters, |
304 | ntohs((*pskb)->nh.ipv6h->payload_len) | 295 | ntohs(ipv6_hdr(*pskb)->payload_len) |
305 | + IPV6_HDR_LEN, | 296 | + IPV6_HDR_LEN, |
306 | 1); | 297 | 1); |
307 | 298 | ||
@@ -1448,8 +1439,8 @@ static void __exit ip6_tables_fini(void) | |||
1448 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | 1439 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, |
1449 | int target, unsigned short *fragoff) | 1440 | int target, unsigned short *fragoff) |
1450 | { | 1441 | { |
1451 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | 1442 | unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr); |
1452 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | 1443 | u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
1453 | unsigned int len = skb->len - start; | 1444 | unsigned int len = skb->len - start; |
1454 | 1445 | ||
1455 | if (fragoff) | 1446 | if (fragoff) |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index ccbab66277e3..4115a576ba25 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -32,7 +32,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
32 | if (!skb_make_writable(pskb, (*pskb)->len)) | 32 | if (!skb_make_writable(pskb, (*pskb)->len)) |
33 | return NF_DROP; | 33 | return NF_DROP; |
34 | 34 | ||
35 | ip6h = (*pskb)->nh.ipv6h; | 35 | ip6h = ipv6_hdr(*pskb); |
36 | 36 | ||
37 | switch (info->mode) { | 37 | switch (info->mode) { |
38 | case IP6T_HL_SET: | 38 | case IP6T_HL_SET: |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index afaa039d0b7b..5bb9cd349350 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -396,8 +396,8 @@ ip6t_log_packet(unsigned int pf, | |||
396 | /* MAC logging for input chain only. */ | 396 | /* MAC logging for input chain only. */ |
397 | printk("MAC="); | 397 | printk("MAC="); |
398 | if (skb->dev && (len = skb->dev->hard_header_len) && | 398 | if (skb->dev && (len = skb->dev->hard_header_len) && |
399 | skb->mac.raw != skb->nh.raw) { | 399 | skb->mac_header != skb->network_header) { |
400 | unsigned char *p = skb->mac.raw; | 400 | const unsigned char *p = skb_mac_header(skb); |
401 | int i; | 401 | int i; |
402 | 402 | ||
403 | if (skb->dev->type == ARPHRD_SIT && | 403 | if (skb->dev->type == ARPHRD_SIT && |
@@ -412,7 +412,8 @@ ip6t_log_packet(unsigned int pf, | |||
412 | printk(" "); | 412 | printk(" "); |
413 | 413 | ||
414 | if (skb->dev->type == ARPHRD_SIT) { | 414 | if (skb->dev->type == ARPHRD_SIT) { |
415 | struct iphdr *iph = (struct iphdr *)skb->mac.raw; | 415 | const struct iphdr *iph = |
416 | (struct iphdr *)skb_mac_header(skb); | ||
416 | printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ", | 417 | printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ", |
417 | NIPQUAD(iph->saddr), | 418 | NIPQUAD(iph->saddr), |
418 | NIPQUAD(iph->daddr)); | 419 | NIPQUAD(iph->daddr)); |
@@ -421,7 +422,7 @@ ip6t_log_packet(unsigned int pf, | |||
421 | printk(" "); | 422 | printk(" "); |
422 | } | 423 | } |
423 | 424 | ||
424 | dump_packet(loginfo, skb, (u8*)skb->nh.ipv6h - skb->data, 1); | 425 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); |
425 | printk("\n"); | 426 | printk("\n"); |
426 | spin_unlock_bh(&log_lock); | 427 | spin_unlock_bh(&log_lock); |
427 | } | 428 | } |
@@ -489,14 +490,10 @@ static int __init ip6t_log_init(void) | |||
489 | ret = xt_register_target(&ip6t_log_reg); | 490 | ret = xt_register_target(&ip6t_log_reg); |
490 | if (ret < 0) | 491 | if (ret < 0) |
491 | return ret; | 492 | return ret; |
492 | if (nf_log_register(PF_INET6, &ip6t_logger) < 0) { | 493 | ret = nf_log_register(PF_INET6, &ip6t_logger); |
493 | printk(KERN_WARNING "ip6t_LOG: not logging via system console " | 494 | if (ret < 0 && ret != -EEXIST) |
494 | "since somebody else already registered for PF_INET6\n"); | 495 | xt_unregister_target(&ip6t_log_reg); |
495 | /* we cannot make module load fail here, since otherwise | 496 | return ret; |
496 | * ip6tables userspace would abort */ | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | 497 | } |
501 | 498 | ||
502 | static void __exit ip6t_log_fini(void) | 499 | static void __exit ip6t_log_fini(void) |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 6abee94c929f..cb3d2415a064 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -47,7 +47,7 @@ static void send_reset(struct sk_buff *oldskb) | |||
47 | struct tcphdr otcph, *tcph; | 47 | struct tcphdr otcph, *tcph; |
48 | unsigned int otcplen, hh_len; | 48 | unsigned int otcplen, hh_len; |
49 | int tcphoff, needs_ack; | 49 | int tcphoff, needs_ack; |
50 | struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h; | 50 | struct ipv6hdr *oip6h = ipv6_hdr(oldskb), *ip6h; |
51 | struct dst_entry *dst = NULL; | 51 | struct dst_entry *dst = NULL; |
52 | u8 proto; | 52 | u8 proto; |
53 | struct flowi fl; | 53 | struct flowi fl; |
@@ -120,8 +120,9 @@ static void send_reset(struct sk_buff *oldskb) | |||
120 | 120 | ||
121 | skb_reserve(nskb, hh_len + dst->header_len); | 121 | skb_reserve(nskb, hh_len + dst->header_len); |
122 | 122 | ||
123 | ip6h = nskb->nh.ipv6h = (struct ipv6hdr *) | 123 | skb_put(nskb, sizeof(struct ipv6hdr)); |
124 | skb_put(nskb, sizeof(struct ipv6hdr)); | 124 | skb_reset_network_header(nskb); |
125 | ip6h = ipv6_hdr(nskb); | ||
125 | ip6h->version = 6; | 126 | ip6h->version = 6; |
126 | ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT); | 127 | ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT); |
127 | ip6h->nexthdr = IPPROTO_TCP; | 128 | ip6h->nexthdr = IPPROTO_TCP; |
@@ -155,8 +156,8 @@ static void send_reset(struct sk_buff *oldskb) | |||
155 | tcph->check = 0; | 156 | tcph->check = 0; |
156 | 157 | ||
157 | /* Adjust TCP checksum */ | 158 | /* Adjust TCP checksum */ |
158 | tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr, | 159 | tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr, |
159 | &nskb->nh.ipv6h->daddr, | 160 | &ipv6_hdr(nskb)->daddr, |
160 | sizeof(struct tcphdr), IPPROTO_TCP, | 161 | sizeof(struct tcphdr), IPPROTO_TCP, |
161 | csum_partial((char *)tcph, | 162 | csum_partial((char *)tcph, |
162 | sizeof(struct tcphdr), 0)); | 163 | sizeof(struct tcphdr), 0)); |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 967bed71d4a8..0f3dd932f0a6 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -32,8 +32,8 @@ match(const struct sk_buff *skb, | |||
32 | unsigned char eui64[8]; | 32 | unsigned char eui64[8]; |
33 | int i = 0; | 33 | int i = 0; |
34 | 34 | ||
35 | if (!(skb->mac.raw >= skb->head && | 35 | if (!(skb_mac_header(skb) >= skb->head && |
36 | (skb->mac.raw + ETH_HLEN) <= skb->data) && | 36 | (skb_mac_header(skb) + ETH_HLEN) <= skb->data) && |
37 | offset != 0) { | 37 | offset != 0) { |
38 | *hotdrop = 1; | 38 | *hotdrop = 1; |
39 | return 0; | 39 | return 0; |
@@ -42,7 +42,7 @@ match(const struct sk_buff *skb, | |||
42 | memset(eui64, 0, sizeof(eui64)); | 42 | memset(eui64, 0, sizeof(eui64)); |
43 | 43 | ||
44 | if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) { | 44 | if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) { |
45 | if (skb->nh.ipv6h->version == 0x6) { | 45 | if (ipv6_hdr(skb)->version == 0x6) { |
46 | memcpy(eui64, eth_hdr(skb)->h_source, 3); | 46 | memcpy(eui64, eth_hdr(skb)->h_source, 3); |
47 | memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); | 47 | memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); |
48 | eui64[3] = 0xff; | 48 | eui64[3] = 0xff; |
@@ -50,7 +50,7 @@ match(const struct sk_buff *skb, | |||
50 | eui64[0] |= 0x02; | 50 | eui64[0] |= 0x02; |
51 | 51 | ||
52 | i = 0; | 52 | i = 0; |
53 | while ((skb->nh.ipv6h->saddr.s6_addr[8+i] == eui64[i]) | 53 | while ((ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i]) |
54 | && (i < 8)) | 54 | && (i < 8)) |
55 | i++; | 55 | i++; |
56 | 56 | ||
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 37c8a4d4ed78..d606c0e6d6fd 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c | |||
@@ -25,7 +25,7 @@ static int match(const struct sk_buff *skb, | |||
25 | int offset, unsigned int protoff, int *hotdrop) | 25 | int offset, unsigned int protoff, int *hotdrop) |
26 | { | 26 | { |
27 | const struct ip6t_hl_info *info = matchinfo; | 27 | const struct ip6t_hl_info *info = matchinfo; |
28 | const struct ipv6hdr *ip6h = skb->nh.ipv6h; | 28 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
29 | 29 | ||
30 | switch (info->mode) { | 30 | switch (info->mode) { |
31 | case IP6T_HL_EQ: | 31 | case IP6T_HL_EQ: |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 700a11d25deb..fd6a0869099b 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -45,7 +45,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
45 | /* Make sure this isn't an evil packet */ | 45 | /* Make sure this isn't an evil packet */ |
46 | 46 | ||
47 | /* type of the 1st exthdr */ | 47 | /* type of the 1st exthdr */ |
48 | nexthdr = skb->nh.ipv6h->nexthdr; | 48 | nexthdr = ipv6_hdr(skb)->nexthdr; |
49 | /* pointer to the 1st exthdr */ | 49 | /* pointer to the 1st exthdr */ |
50 | ptr = sizeof(struct ipv6hdr); | 50 | ptr = sizeof(struct ipv6hdr); |
51 | /* available length */ | 51 | /* available length */ |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 112a21d0c6da..76f0cf66f95c 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -102,7 +102,7 @@ ip6t_local_out_hook(unsigned int hook, | |||
102 | #if 0 | 102 | #if 0 |
103 | /* root is playing with raw sockets. */ | 103 | /* root is playing with raw sockets. */ |
104 | if ((*pskb)->len < sizeof(struct iphdr) | 104 | if ((*pskb)->len < sizeof(struct iphdr) |
105 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { | 105 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { |
106 | if (net_ratelimit()) | 106 | if (net_ratelimit()) |
107 | printk("ip6t_hook: happy cracking.\n"); | 107 | printk("ip6t_hook: happy cracking.\n"); |
108 | return NF_ACCEPT; | 108 | return NF_ACCEPT; |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 0c468d35a937..a9f10e32c163 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -7,8 +7,6 @@ | |||
7 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | ||
11 | * Extended to all five netfilter hooks by Brad Chapman & Harald Welte | ||
12 | */ | 10 | */ |
13 | #include <linux/module.h> | 11 | #include <linux/module.h> |
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | 12 | #include <linux/netfilter_ipv6/ip6_tables.h> |
@@ -138,7 +136,7 @@ ip6t_local_hook(unsigned int hook, | |||
138 | #if 0 | 136 | #if 0 |
139 | /* root is playing with raw sockets. */ | 137 | /* root is playing with raw sockets. */ |
140 | if ((*pskb)->len < sizeof(struct iphdr) | 138 | if ((*pskb)->len < sizeof(struct iphdr) |
141 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { | 139 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { |
142 | if (net_ratelimit()) | 140 | if (net_ratelimit()) |
143 | printk("ip6t_hook: happy cracking.\n"); | 141 | printk("ip6t_hook: happy cracking.\n"); |
144 | return NF_ACCEPT; | 142 | return NF_ACCEPT; |
@@ -146,21 +144,21 @@ ip6t_local_hook(unsigned int hook, | |||
146 | #endif | 144 | #endif |
147 | 145 | ||
148 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ | 146 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ |
149 | memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); | 147 | memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr)); |
150 | memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); | 148 | memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr)); |
151 | mark = (*pskb)->mark; | 149 | mark = (*pskb)->mark; |
152 | hop_limit = (*pskb)->nh.ipv6h->hop_limit; | 150 | hop_limit = ipv6_hdr(*pskb)->hop_limit; |
153 | 151 | ||
154 | /* flowlabel and prio (includes version, which shouldn't change either */ | 152 | /* flowlabel and prio (includes version, which shouldn't change either */ |
155 | flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h); | 153 | flowlabel = *((u_int32_t *)ipv6_hdr(*pskb)); |
156 | 154 | ||
157 | ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); | 155 | ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); |
158 | 156 | ||
159 | if (ret != NF_DROP && ret != NF_STOLEN | 157 | if (ret != NF_DROP && ret != NF_STOLEN |
160 | && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) | 158 | && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr)) |
161 | || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) | 159 | || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr)) |
162 | || (*pskb)->mark != mark | 160 | || (*pskb)->mark != mark |
163 | || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) | 161 | || ipv6_hdr(*pskb)->hop_limit != hop_limit)) |
164 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; | 162 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; |
165 | 163 | ||
166 | return ret; | 164 | return ret; |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index d1102455668d..6d2a08205111 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -7,17 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Author: | 8 | * Author: |
9 | * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | 9 | * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> |
10 | * | ||
11 | * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
12 | * - support Layer 3 protocol independent connection tracking. | ||
13 | * Based on the original ip_conntrack code which had the following | ||
14 | * copyright information: | ||
15 | * (C) 1999-2001 Paul `Rusty' Russell | ||
16 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
17 | * | ||
18 | * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
19 | * - add get_features() to support various size of conntrack | ||
20 | * structures. | ||
21 | */ | 10 | */ |
22 | 11 | ||
23 | #include <linux/types.h> | 12 | #include <linux/types.h> |
@@ -138,16 +127,10 @@ static int | |||
138 | ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | 127 | ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, |
139 | u_int8_t *protonum) | 128 | u_int8_t *protonum) |
140 | { | 129 | { |
141 | unsigned int extoff; | 130 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; |
142 | unsigned char pnum; | 131 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; |
143 | int protoff; | 132 | int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, |
144 | 133 | (*pskb)->len - extoff); | |
145 | extoff = (u8*)((*pskb)->nh.ipv6h + 1) - (*pskb)->data; | ||
146 | pnum = (*pskb)->nh.ipv6h->nexthdr; | ||
147 | |||
148 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | ||
149 | (*pskb)->len - extoff); | ||
150 | |||
151 | /* | 134 | /* |
152 | * (protoff == (*pskb)->len) mean that the packet doesn't have no data | 135 | * (protoff == (*pskb)->len) mean that the packet doesn't have no data |
153 | * except of IPv6 & ext headers. but it's tracked anyway. - YK | 136 | * except of IPv6 & ext headers. but it's tracked anyway. - YK |
@@ -179,9 +162,8 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
179 | struct nf_conn_help *help; | 162 | struct nf_conn_help *help; |
180 | enum ip_conntrack_info ctinfo; | 163 | enum ip_conntrack_info ctinfo; |
181 | unsigned int ret, protoff; | 164 | unsigned int ret, protoff; |
182 | unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1) | 165 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; |
183 | - (*pskb)->data; | 166 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; |
184 | unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr; | ||
185 | 167 | ||
186 | 168 | ||
187 | /* This is where we call the helper: as the packet goes out. */ | 169 | /* This is where we call the helper: as the packet goes out. */ |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 075da4f287b8..0be790d250f9 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -7,13 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Author: | 8 | * Author: |
9 | * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | 9 | * Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> |
10 | * | ||
11 | * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
12 | * - ICMPv6 tracking support. Derived from the original ip_conntrack code | ||
13 | * net/ipv4/netfilter/ip_conntrack_proto_icmp.c which had the following | ||
14 | * copyright information: | ||
15 | * (C) 1999-2001 Paul `Rusty' Russell | ||
16 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
17 | */ | 10 | */ |
18 | 11 | ||
19 | #include <linux/types.h> | 12 | #include <linux/types.h> |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 15ab1e3e8b56..347ab7608231 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queue | |||
82 | struct sk_buff *fragments; | 82 | struct sk_buff *fragments; |
83 | int len; | 83 | int len; |
84 | int meat; | 84 | int meat; |
85 | struct timeval stamp; | 85 | ktime_t stamp; |
86 | unsigned int csum; | 86 | unsigned int csum; |
87 | __u8 last_in; /* has first/last segment arrived? */ | 87 | __u8 last_in; /* has first/last segment arrived? */ |
88 | #define COMPLETE 4 | 88 | #define COMPLETE 4 |
@@ -353,9 +353,7 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str | |||
353 | ipv6_addr_copy(&fq->saddr, src); | 353 | ipv6_addr_copy(&fq->saddr, src); |
354 | ipv6_addr_copy(&fq->daddr, dst); | 354 | ipv6_addr_copy(&fq->daddr, dst); |
355 | 355 | ||
356 | init_timer(&fq->timer); | 356 | setup_timer(&fq->timer, nf_ct_frag6_expire, (unsigned long)fq); |
357 | fq->timer.function = nf_ct_frag6_expire; | ||
358 | fq->timer.data = (long) fq; | ||
359 | spin_lock_init(&fq->lock); | 357 | spin_lock_init(&fq->lock); |
360 | atomic_set(&fq->refcnt, 1); | 358 | atomic_set(&fq->refcnt, 1); |
361 | 359 | ||
@@ -400,19 +398,20 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
400 | } | 398 | } |
401 | 399 | ||
402 | offset = ntohs(fhdr->frag_off) & ~0x7; | 400 | offset = ntohs(fhdr->frag_off) & ~0x7; |
403 | end = offset + (ntohs(skb->nh.ipv6h->payload_len) - | 401 | end = offset + (ntohs(ipv6_hdr(skb)->payload_len) - |
404 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); | 402 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); |
405 | 403 | ||
406 | if ((unsigned int)end > IPV6_MAXPLEN) { | 404 | if ((unsigned int)end > IPV6_MAXPLEN) { |
407 | DEBUGP("offset is too large.\n"); | 405 | DEBUGP("offset is too large.\n"); |
408 | return -1; | 406 | return -1; |
409 | } | 407 | } |
410 | 408 | ||
411 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 409 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
410 | const unsigned char *nh = skb_network_header(skb); | ||
412 | skb->csum = csum_sub(skb->csum, | 411 | skb->csum = csum_sub(skb->csum, |
413 | csum_partial(skb->nh.raw, | 412 | csum_partial(nh, (u8 *)(fhdr + 1) - nh, |
414 | (u8*)(fhdr + 1) - skb->nh.raw, | ||
415 | 0)); | 413 | 0)); |
414 | } | ||
416 | 415 | ||
417 | /* Is this the final fragment? */ | 416 | /* Is this the final fragment? */ |
418 | if (!(fhdr->frag_off & htons(IP6_MF))) { | 417 | if (!(fhdr->frag_off & htons(IP6_MF))) { |
@@ -542,7 +541,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
542 | fq->fragments = skb; | 541 | fq->fragments = skb; |
543 | 542 | ||
544 | skb->dev = NULL; | 543 | skb->dev = NULL; |
545 | skb_get_timestamp(skb, &fq->stamp); | 544 | fq->stamp = skb->tstamp; |
546 | fq->meat += skb->len; | 545 | fq->meat += skb->len; |
547 | atomic_add(skb->truesize, &nf_ct_frag6_mem); | 546 | atomic_add(skb->truesize, &nf_ct_frag6_mem); |
548 | 547 | ||
@@ -583,7 +582,9 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
583 | BUG_TRAP(NFCT_FRAG6_CB(head)->offset == 0); | 582 | BUG_TRAP(NFCT_FRAG6_CB(head)->offset == 0); |
584 | 583 | ||
585 | /* Unfragmented part is taken from the first segment. */ | 584 | /* Unfragmented part is taken from the first segment. */ |
586 | payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr); | 585 | payload_len = ((head->data - skb_network_header(head)) - |
586 | sizeof(struct ipv6hdr) + fq->len - | ||
587 | sizeof(struct frag_hdr)); | ||
587 | if (payload_len > IPV6_MAXPLEN) { | 588 | if (payload_len > IPV6_MAXPLEN) { |
588 | DEBUGP("payload len is too large.\n"); | 589 | DEBUGP("payload len is too large.\n"); |
589 | goto out_oversize; | 590 | goto out_oversize; |
@@ -624,15 +625,15 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
624 | 625 | ||
625 | /* We have to remove fragment header from datagram and to relocate | 626 | /* We have to remove fragment header from datagram and to relocate |
626 | * header in order to calculate ICV correctly. */ | 627 | * header in order to calculate ICV correctly. */ |
627 | head->nh.raw[fq->nhoffset] = head->h.raw[0]; | 628 | skb_network_header(head)[fq->nhoffset] = skb_transport_header(head)[0]; |
628 | memmove(head->head + sizeof(struct frag_hdr), head->head, | 629 | memmove(head->head + sizeof(struct frag_hdr), head->head, |
629 | (head->data - head->head) - sizeof(struct frag_hdr)); | 630 | (head->data - head->head) - sizeof(struct frag_hdr)); |
630 | head->mac.raw += sizeof(struct frag_hdr); | 631 | head->mac_header += sizeof(struct frag_hdr); |
631 | head->nh.raw += sizeof(struct frag_hdr); | 632 | head->network_header += sizeof(struct frag_hdr); |
632 | 633 | ||
633 | skb_shinfo(head)->frag_list = head->next; | 634 | skb_shinfo(head)->frag_list = head->next; |
634 | head->h.raw = head->data; | 635 | skb_reset_transport_header(head); |
635 | skb_push(head, head->data - head->nh.raw); | 636 | skb_push(head, head->data - skb_network_header(head)); |
636 | atomic_sub(head->truesize, &nf_ct_frag6_mem); | 637 | atomic_sub(head->truesize, &nf_ct_frag6_mem); |
637 | 638 | ||
638 | for (fp=head->next; fp; fp = fp->next) { | 639 | for (fp=head->next; fp; fp = fp->next) { |
@@ -648,12 +649,14 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
648 | 649 | ||
649 | head->next = NULL; | 650 | head->next = NULL; |
650 | head->dev = dev; | 651 | head->dev = dev; |
651 | skb_set_timestamp(head, &fq->stamp); | 652 | head->tstamp = fq->stamp; |
652 | head->nh.ipv6h->payload_len = htons(payload_len); | 653 | ipv6_hdr(head)->payload_len = htons(payload_len); |
653 | 654 | ||
654 | /* Yes, and fold redundant checksum back. 8) */ | 655 | /* Yes, and fold redundant checksum back. 8) */ |
655 | if (head->ip_summed == CHECKSUM_COMPLETE) | 656 | if (head->ip_summed == CHECKSUM_COMPLETE) |
656 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); | 657 | head->csum = csum_partial(skb_network_header(head), |
658 | skb_network_header_len(head), | ||
659 | head->csum); | ||
657 | 660 | ||
658 | fq->fragments = NULL; | 661 | fq->fragments = NULL; |
659 | 662 | ||
@@ -701,9 +704,10 @@ out_fail: | |||
701 | static int | 704 | static int |
702 | find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) | 705 | find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) |
703 | { | 706 | { |
704 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | 707 | u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
705 | u8 prev_nhoff = (u8 *)&skb->nh.ipv6h->nexthdr - skb->data; | 708 | const int netoff = skb_network_offset(skb); |
706 | int start = (u8 *)(skb->nh.ipv6h+1) - skb->data; | 709 | u8 prev_nhoff = netoff + offsetof(struct ipv6hdr, nexthdr); |
710 | int start = netoff + sizeof(struct ipv6hdr); | ||
707 | int len = skb->len - start; | 711 | int len = skb->len - start; |
708 | u8 prevhdr = NEXTHDR_IPV6; | 712 | u8 prevhdr = NEXTHDR_IPV6; |
709 | 713 | ||
@@ -759,7 +763,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
759 | struct sk_buff *ret_skb = NULL; | 763 | struct sk_buff *ret_skb = NULL; |
760 | 764 | ||
761 | /* Jumbo payload inhibits frag. header */ | 765 | /* Jumbo payload inhibits frag. header */ |
762 | if (skb->nh.ipv6h->payload_len == 0) { | 766 | if (ipv6_hdr(skb)->payload_len == 0) { |
763 | DEBUGP("payload len = 0\n"); | 767 | DEBUGP("payload len = 0\n"); |
764 | return skb; | 768 | return skb; |
765 | } | 769 | } |
@@ -780,9 +784,9 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
780 | goto ret_orig; | 784 | goto ret_orig; |
781 | } | 785 | } |
782 | 786 | ||
783 | clone->h.raw = clone->data + fhoff; | 787 | skb_set_transport_header(clone, fhoff); |
784 | hdr = clone->nh.ipv6h; | 788 | hdr = ipv6_hdr(clone); |
785 | fhdr = (struct frag_hdr *)clone->h.raw; | 789 | fhdr = (struct frag_hdr *)skb_transport_header(clone); |
786 | 790 | ||
787 | if (!(fhdr->frag_off & htons(0xFFF9))) { | 791 | if (!(fhdr->frag_off & htons(0xFFF9))) { |
788 | DEBUGP("Invalid fragment offset\n"); | 792 | DEBUGP("Invalid fragment offset\n"); |
@@ -864,8 +868,7 @@ int nf_ct_frag6_init(void) | |||
864 | nf_ct_frag6_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 868 | nf_ct_frag6_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ |
865 | (jiffies ^ (jiffies >> 6))); | 869 | (jiffies ^ (jiffies >> 6))); |
866 | 870 | ||
867 | init_timer(&nf_ct_frag6_secret_timer); | 871 | setup_timer(&nf_ct_frag6_secret_timer, nf_ct_frag6_secret_rebuild, 0); |
868 | nf_ct_frag6_secret_timer.function = nf_ct_frag6_secret_rebuild; | ||
869 | nf_ct_frag6_secret_timer.expires = jiffies | 872 | nf_ct_frag6_secret_timer.expires = jiffies |
870 | + nf_ct_frag6_secret_interval; | 873 | + nf_ct_frag6_secret_interval; |
871 | add_timer(&nf_ct_frag6_secret_timer); | 874 | add_timer(&nf_ct_frag6_secret_timer); |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index fa3fb509f187..acb306a5dd56 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -23,12 +23,12 @@ | |||
23 | #include <linux/proc_fs.h> | 23 | #include <linux/proc_fs.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/stddef.h> | 25 | #include <linux/stddef.h> |
26 | #include <net/ip.h> | ||
26 | #include <net/sock.h> | 27 | #include <net/sock.h> |
27 | #include <net/tcp.h> | 28 | #include <net/tcp.h> |
28 | #include <net/transp_v6.h> | 29 | #include <net/transp_v6.h> |
29 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
30 | 31 | ||
31 | #ifdef CONFIG_PROC_FS | ||
32 | static struct proc_dir_entry *proc_net_devsnmp6; | 32 | static struct proc_dir_entry *proc_net_devsnmp6; |
33 | 33 | ||
34 | static int fold_prot_inuse(struct proto *proto) | 34 | static int fold_prot_inuse(struct proto *proto) |
@@ -142,26 +142,13 @@ static struct snmp_mib snmp6_udplite6_list[] = { | |||
142 | SNMP_MIB_SENTINEL | 142 | SNMP_MIB_SENTINEL |
143 | }; | 143 | }; |
144 | 144 | ||
145 | static unsigned long | ||
146 | fold_field(void *mib[], int offt) | ||
147 | { | ||
148 | unsigned long res = 0; | ||
149 | int i; | ||
150 | |||
151 | for_each_possible_cpu(i) { | ||
152 | res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); | ||
153 | res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); | ||
154 | } | ||
155 | return res; | ||
156 | } | ||
157 | |||
158 | static inline void | 145 | static inline void |
159 | snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) | 146 | snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) |
160 | { | 147 | { |
161 | int i; | 148 | int i; |
162 | for (i=0; itemlist[i].name; i++) | 149 | for (i=0; itemlist[i].name; i++) |
163 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, | 150 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, |
164 | fold_field(mib, itemlist[i].entry)); | 151 | snmp_fold_field(mib, itemlist[i].entry)); |
165 | } | 152 | } |
166 | 153 | ||
167 | static int snmp6_seq_show(struct seq_file *seq, void *v) | 154 | static int snmp6_seq_show(struct seq_file *seq, void *v) |
@@ -271,47 +258,3 @@ void ipv6_misc_proc_exit(void) | |||
271 | proc_net_remove("snmp6"); | 258 | proc_net_remove("snmp6"); |
272 | } | 259 | } |
273 | 260 | ||
274 | #else /* CONFIG_PROC_FS */ | ||
275 | |||
276 | |||
277 | int snmp6_register_dev(struct inet6_dev *idev) | ||
278 | { | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | int snmp6_unregister_dev(struct inet6_dev *idev) | ||
283 | { | ||
284 | return 0; | ||
285 | } | ||
286 | #endif /* CONFIG_PROC_FS */ | ||
287 | |||
288 | int snmp6_alloc_dev(struct inet6_dev *idev) | ||
289 | { | ||
290 | int err = -ENOMEM; | ||
291 | |||
292 | if (!idev || !idev->dev) | ||
293 | return -EINVAL; | ||
294 | |||
295 | if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), | ||
296 | __alignof__(struct ipstats_mib)) < 0) | ||
297 | goto err_ip; | ||
298 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), | ||
299 | __alignof__(struct icmpv6_mib)) < 0) | ||
300 | goto err_icmp; | ||
301 | |||
302 | return 0; | ||
303 | |||
304 | err_icmp: | ||
305 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
306 | err_ip: | ||
307 | return err; | ||
308 | } | ||
309 | |||
310 | int snmp6_free_dev(struct inet6_dev *idev) | ||
311 | { | ||
312 | snmp6_mib_free((void **)idev->stats.icmpv6); | ||
313 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | |||
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index ef43bd57baed..f929f47b925e 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c | |||
@@ -60,6 +60,8 @@ int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol) | |||
60 | return ret; | 60 | return ret; |
61 | } | 61 | } |
62 | 62 | ||
63 | EXPORT_SYMBOL(inet6_add_protocol); | ||
64 | |||
63 | /* | 65 | /* |
64 | * Remove a protocol from the hash tables. | 66 | * Remove a protocol from the hash tables. |
65 | */ | 67 | */ |
@@ -83,3 +85,5 @@ int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol) | |||
83 | 85 | ||
84 | return ret; | 86 | return ret; |
85 | } | 87 | } |
88 | |||
89 | EXPORT_SYMBOL(inet6_del_protocol); | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 203e069e7fe9..009a1047fc3f 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -152,7 +152,7 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
152 | int delivered = 0; | 152 | int delivered = 0; |
153 | __u8 hash; | 153 | __u8 hash; |
154 | 154 | ||
155 | saddr = &skb->nh.ipv6h->saddr; | 155 | saddr = &ipv6_hdr(skb)->saddr; |
156 | daddr = saddr + 1; | 156 | daddr = saddr + 1; |
157 | 157 | ||
158 | hash = nexthdr & (MAX_INET_PROTOS - 1); | 158 | hash = nexthdr & (MAX_INET_PROTOS - 1); |
@@ -361,17 +361,18 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) | |||
361 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 361 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
362 | 362 | ||
363 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 363 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
364 | skb_postpull_rcsum(skb, skb->nh.raw, | 364 | skb_postpull_rcsum(skb, skb_network_header(skb), |
365 | skb->h.raw - skb->nh.raw); | 365 | skb_network_header_len(skb)); |
366 | if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 366 | if (!csum_ipv6_magic(&ipv6_hdr(skb)->saddr, |
367 | &skb->nh.ipv6h->daddr, | 367 | &ipv6_hdr(skb)->daddr, |
368 | skb->len, inet->num, skb->csum)) | 368 | skb->len, inet->num, skb->csum)) |
369 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 369 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
370 | } | 370 | } |
371 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 371 | if (!skb_csum_unnecessary(skb)) |
372 | skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 372 | skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, |
373 | &skb->nh.ipv6h->daddr, | 373 | &ipv6_hdr(skb)->daddr, |
374 | skb->len, inet->num, 0)); | 374 | skb->len, |
375 | inet->num, 0)); | ||
375 | 376 | ||
376 | if (inet->hdrincl) { | 377 | if (inet->hdrincl) { |
377 | if (skb_checksum_complete(skb)) { | 378 | if (skb_checksum_complete(skb)) { |
@@ -420,7 +421,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
420 | msg->msg_flags |= MSG_TRUNC; | 421 | msg->msg_flags |= MSG_TRUNC; |
421 | } | 422 | } |
422 | 423 | ||
423 | if (skb->ip_summed==CHECKSUM_UNNECESSARY) { | 424 | if (skb_csum_unnecessary(skb)) { |
424 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 425 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
425 | } else if (msg->msg_flags&MSG_TRUNC) { | 426 | } else if (msg->msg_flags&MSG_TRUNC) { |
426 | if (__skb_checksum_complete(skb)) | 427 | if (__skb_checksum_complete(skb)) |
@@ -438,7 +439,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
438 | if (sin6) { | 439 | if (sin6) { |
439 | sin6->sin6_family = AF_INET6; | 440 | sin6->sin6_family = AF_INET6; |
440 | sin6->sin6_port = 0; | 441 | sin6->sin6_port = 0; |
441 | ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); | 442 | ipv6_addr_copy(&sin6->sin6_addr, &ipv6_hdr(skb)->saddr); |
442 | sin6->sin6_flowinfo = 0; | 443 | sin6->sin6_flowinfo = 0; |
443 | sin6->sin6_scope_id = 0; | 444 | sin6->sin6_scope_id = 0; |
444 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 445 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -488,7 +489,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
488 | goto out; | 489 | goto out; |
489 | 490 | ||
490 | offset = rp->offset; | 491 | offset = rp->offset; |
491 | total_len = inet_sk(sk)->cork.length - (skb->nh.raw - skb->data); | 492 | total_len = inet_sk(sk)->cork.length - (skb_network_header(skb) - |
493 | skb->data); | ||
492 | if (offset >= total_len - 1) { | 494 | if (offset >= total_len - 1) { |
493 | err = -EINVAL; | 495 | err = -EINVAL; |
494 | ip6_flush_pending_frames(sk); | 496 | ip6_flush_pending_frames(sk); |
@@ -511,7 +513,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
511 | if (csum_skb) | 513 | if (csum_skb) |
512 | continue; | 514 | continue; |
513 | 515 | ||
514 | len = skb->len - (skb->h.raw - skb->data); | 516 | len = skb->len - skb_transport_offset(skb); |
515 | if (offset >= len) { | 517 | if (offset >= len) { |
516 | offset -= len; | 518 | offset -= len; |
517 | continue; | 519 | continue; |
@@ -523,7 +525,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
523 | skb = csum_skb; | 525 | skb = csum_skb; |
524 | } | 526 | } |
525 | 527 | ||
526 | offset += skb->h.raw - skb->data; | 528 | offset += skb_transport_offset(skb); |
527 | if (skb_copy_bits(skb, offset, &csum, 2)) | 529 | if (skb_copy_bits(skb, offset, &csum, 2)) |
528 | BUG(); | 530 | BUG(); |
529 | 531 | ||
@@ -575,11 +577,13 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
575 | skb->priority = sk->sk_priority; | 577 | skb->priority = sk->sk_priority; |
576 | skb->dst = dst_clone(&rt->u.dst); | 578 | skb->dst = dst_clone(&rt->u.dst); |
577 | 579 | ||
578 | skb->nh.ipv6h = iph = (struct ipv6hdr *)skb_put(skb, length); | 580 | skb_put(skb, length); |
581 | skb_reset_network_header(skb); | ||
582 | iph = ipv6_hdr(skb); | ||
579 | 583 | ||
580 | skb->ip_summed = CHECKSUM_NONE; | 584 | skb->ip_summed = CHECKSUM_NONE; |
581 | 585 | ||
582 | skb->h.raw = skb->nh.raw; | 586 | skb->transport_header = skb->network_header; |
583 | err = memcpy_fromiovecend((void *)iph, from, 0, length); | 587 | err = memcpy_fromiovecend((void *)iph, from, 0, length); |
584 | if (err) | 588 | if (err) |
585 | goto error_fault; | 589 | goto error_fault; |
@@ -878,7 +882,7 @@ static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, | |||
878 | return 0; | 882 | return 0; |
879 | default: | 883 | default: |
880 | return -ENOPROTOOPT; | 884 | return -ENOPROTOOPT; |
881 | }; | 885 | } |
882 | 886 | ||
883 | return 0; | 887 | return 0; |
884 | } | 888 | } |
@@ -903,7 +907,7 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, | |||
903 | return 0; | 907 | return 0; |
904 | default: | 908 | default: |
905 | return -ENOPROTOOPT; | 909 | return -ENOPROTOOPT; |
906 | }; | 910 | } |
907 | 911 | ||
908 | return 0; | 912 | return 0; |
909 | } | 913 | } |
@@ -957,7 +961,8 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
957 | default: | 961 | default: |
958 | return ipv6_setsockopt(sk, level, optname, optval, | 962 | return ipv6_setsockopt(sk, level, optname, optval, |
959 | optlen); | 963 | optlen); |
960 | }; | 964 | } |
965 | |||
961 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | 966 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
962 | } | 967 | } |
963 | 968 | ||
@@ -978,7 +983,7 @@ static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
978 | default: | 983 | default: |
979 | return compat_ipv6_setsockopt(sk, level, optname, | 984 | return compat_ipv6_setsockopt(sk, level, optname, |
980 | optval, optlen); | 985 | optval, optlen); |
981 | }; | 986 | } |
982 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); | 987 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
983 | } | 988 | } |
984 | #endif | 989 | #endif |
@@ -1031,7 +1036,8 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1031 | default: | 1036 | default: |
1032 | return ipv6_getsockopt(sk, level, optname, optval, | 1037 | return ipv6_getsockopt(sk, level, optname, optval, |
1033 | optlen); | 1038 | optlen); |
1034 | }; | 1039 | } |
1040 | |||
1035 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | 1041 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
1036 | } | 1042 | } |
1037 | 1043 | ||
@@ -1052,7 +1058,7 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
1052 | default: | 1058 | default: |
1053 | return compat_ipv6_getsockopt(sk, level, optname, | 1059 | return compat_ipv6_getsockopt(sk, level, optname, |
1054 | optval, optlen); | 1060 | optval, optlen); |
1055 | }; | 1061 | } |
1056 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); | 1062 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
1057 | } | 1063 | } |
1058 | #endif | 1064 | #endif |
@@ -1073,7 +1079,7 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1073 | spin_lock_bh(&sk->sk_receive_queue.lock); | 1079 | spin_lock_bh(&sk->sk_receive_queue.lock); |
1074 | skb = skb_peek(&sk->sk_receive_queue); | 1080 | skb = skb_peek(&sk->sk_receive_queue); |
1075 | if (skb != NULL) | 1081 | if (skb != NULL) |
1076 | amount = skb->tail - skb->h.raw; | 1082 | amount = skb->tail - skb->transport_header; |
1077 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 1083 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
1078 | return put_user(amount, (int __user *)arg); | 1084 | return put_user(amount, (int __user *)arg); |
1079 | } | 1085 | } |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 7034c54e5010..de795c04e34c 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -88,7 +88,7 @@ struct frag_queue | |||
88 | int len; | 88 | int len; |
89 | int meat; | 89 | int meat; |
90 | int iif; | 90 | int iif; |
91 | struct timeval stamp; | 91 | ktime_t stamp; |
92 | unsigned int csum; | 92 | unsigned int csum; |
93 | __u8 last_in; /* has first/last segment arrived? */ | 93 | __u8 last_in; /* has first/last segment arrived? */ |
94 | #define COMPLETE 4 | 94 | #define COMPLETE 4 |
@@ -430,19 +430,24 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
430 | goto err; | 430 | goto err; |
431 | 431 | ||
432 | offset = ntohs(fhdr->frag_off) & ~0x7; | 432 | offset = ntohs(fhdr->frag_off) & ~0x7; |
433 | end = offset + (ntohs(skb->nh.ipv6h->payload_len) - | 433 | end = offset + (ntohs(ipv6_hdr(skb)->payload_len) - |
434 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); | 434 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); |
435 | 435 | ||
436 | if ((unsigned int)end > IPV6_MAXPLEN) { | 436 | if ((unsigned int)end > IPV6_MAXPLEN) { |
437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
438 | IPSTATS_MIB_INHDRERRORS); | 438 | IPSTATS_MIB_INHDRERRORS); |
439 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); | 439 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
440 | ((u8 *)&fhdr->frag_off - | ||
441 | skb_network_header(skb))); | ||
440 | return; | 442 | return; |
441 | } | 443 | } |
442 | 444 | ||
443 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 445 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
446 | const unsigned char *nh = skb_network_header(skb); | ||
444 | skb->csum = csum_sub(skb->csum, | 447 | skb->csum = csum_sub(skb->csum, |
445 | csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0)); | 448 | csum_partial(nh, (u8 *)(fhdr + 1) - nh, |
449 | 0)); | ||
450 | } | ||
446 | 451 | ||
447 | /* Is this the final fragment? */ | 452 | /* Is this the final fragment? */ |
448 | if (!(fhdr->frag_off & htons(IP6_MF))) { | 453 | if (!(fhdr->frag_off & htons(IP6_MF))) { |
@@ -562,7 +567,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
562 | if (skb->dev) | 567 | if (skb->dev) |
563 | fq->iif = skb->dev->ifindex; | 568 | fq->iif = skb->dev->ifindex; |
564 | skb->dev = NULL; | 569 | skb->dev = NULL; |
565 | skb_get_timestamp(skb, &fq->stamp); | 570 | fq->stamp = skb->tstamp; |
566 | fq->meat += skb->len; | 571 | fq->meat += skb->len; |
567 | atomic_add(skb->truesize, &ip6_frag_mem); | 572 | atomic_add(skb->truesize, &ip6_frag_mem); |
568 | 573 | ||
@@ -605,7 +610,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
605 | BUG_TRAP(FRAG6_CB(head)->offset == 0); | 610 | BUG_TRAP(FRAG6_CB(head)->offset == 0); |
606 | 611 | ||
607 | /* Unfragmented part is taken from the first segment. */ | 612 | /* Unfragmented part is taken from the first segment. */ |
608 | payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr); | 613 | payload_len = ((head->data - skb_network_header(head)) - |
614 | sizeof(struct ipv6hdr) + fq->len - | ||
615 | sizeof(struct frag_hdr)); | ||
609 | if (payload_len > IPV6_MAXPLEN) | 616 | if (payload_len > IPV6_MAXPLEN) |
610 | goto out_oversize; | 617 | goto out_oversize; |
611 | 618 | ||
@@ -639,15 +646,15 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
639 | /* We have to remove fragment header from datagram and to relocate | 646 | /* We have to remove fragment header from datagram and to relocate |
640 | * header in order to calculate ICV correctly. */ | 647 | * header in order to calculate ICV correctly. */ |
641 | nhoff = fq->nhoffset; | 648 | nhoff = fq->nhoffset; |
642 | head->nh.raw[nhoff] = head->h.raw[0]; | 649 | skb_network_header(head)[nhoff] = skb_transport_header(head)[0]; |
643 | memmove(head->head + sizeof(struct frag_hdr), head->head, | 650 | memmove(head->head + sizeof(struct frag_hdr), head->head, |
644 | (head->data - head->head) - sizeof(struct frag_hdr)); | 651 | (head->data - head->head) - sizeof(struct frag_hdr)); |
645 | head->mac.raw += sizeof(struct frag_hdr); | 652 | head->mac_header += sizeof(struct frag_hdr); |
646 | head->nh.raw += sizeof(struct frag_hdr); | 653 | head->network_header += sizeof(struct frag_hdr); |
647 | 654 | ||
648 | skb_shinfo(head)->frag_list = head->next; | 655 | skb_shinfo(head)->frag_list = head->next; |
649 | head->h.raw = head->data; | 656 | skb_reset_transport_header(head); |
650 | skb_push(head, head->data - head->nh.raw); | 657 | skb_push(head, head->data - skb_network_header(head)); |
651 | atomic_sub(head->truesize, &ip6_frag_mem); | 658 | atomic_sub(head->truesize, &ip6_frag_mem); |
652 | 659 | ||
653 | for (fp=head->next; fp; fp = fp->next) { | 660 | for (fp=head->next; fp; fp = fp->next) { |
@@ -663,15 +670,17 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
663 | 670 | ||
664 | head->next = NULL; | 671 | head->next = NULL; |
665 | head->dev = dev; | 672 | head->dev = dev; |
666 | skb_set_timestamp(head, &fq->stamp); | 673 | head->tstamp = fq->stamp; |
667 | head->nh.ipv6h->payload_len = htons(payload_len); | 674 | ipv6_hdr(head)->payload_len = htons(payload_len); |
668 | IP6CB(head)->nhoff = nhoff; | 675 | IP6CB(head)->nhoff = nhoff; |
669 | 676 | ||
670 | *skb_in = head; | 677 | *skb_in = head; |
671 | 678 | ||
672 | /* Yes, and fold redundant checksum back. 8) */ | 679 | /* Yes, and fold redundant checksum back. 8) */ |
673 | if (head->ip_summed == CHECKSUM_COMPLETE) | 680 | if (head->ip_summed == CHECKSUM_COMPLETE) |
674 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); | 681 | head->csum = csum_partial(skb_network_header(head), |
682 | skb_network_header_len(head), | ||
683 | head->csum); | ||
675 | 684 | ||
676 | rcu_read_lock(); | 685 | rcu_read_lock(); |
677 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 686 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
@@ -699,33 +708,34 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
699 | struct net_device *dev = skb->dev; | 708 | struct net_device *dev = skb->dev; |
700 | struct frag_hdr *fhdr; | 709 | struct frag_hdr *fhdr; |
701 | struct frag_queue *fq; | 710 | struct frag_queue *fq; |
702 | struct ipv6hdr *hdr; | 711 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
703 | |||
704 | hdr = skb->nh.ipv6h; | ||
705 | 712 | ||
706 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); | 713 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); |
707 | 714 | ||
708 | /* Jumbo payload inhibits frag. header */ | 715 | /* Jumbo payload inhibits frag. header */ |
709 | if (hdr->payload_len==0) { | 716 | if (hdr->payload_len==0) { |
710 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | 717 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
711 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 718 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
719 | skb_network_header_len(skb)); | ||
712 | return -1; | 720 | return -1; |
713 | } | 721 | } |
714 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { | 722 | if (!pskb_may_pull(skb, (skb_transport_offset(skb) + |
723 | sizeof(struct frag_hdr)))) { | ||
715 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); | 724 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
716 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 725 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
726 | skb_network_header_len(skb)); | ||
717 | return -1; | 727 | return -1; |
718 | } | 728 | } |
719 | 729 | ||
720 | hdr = skb->nh.ipv6h; | 730 | hdr = ipv6_hdr(skb); |
721 | fhdr = (struct frag_hdr *)skb->h.raw; | 731 | fhdr = (struct frag_hdr *)skb_transport_header(skb); |
722 | 732 | ||
723 | if (!(fhdr->frag_off & htons(0xFFF9))) { | 733 | if (!(fhdr->frag_off & htons(0xFFF9))) { |
724 | /* It is not a fragmented frame */ | 734 | /* It is not a fragmented frame */ |
725 | skb->h.raw += sizeof(struct frag_hdr); | 735 | skb->transport_header += sizeof(struct frag_hdr); |
726 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); | 736 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); |
727 | 737 | ||
728 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; | 738 | IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); |
729 | return 1; | 739 | return 1; |
730 | } | 740 | } |
731 | 741 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aebb4e2d5ae3..b46ad53044ba 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -575,6 +575,8 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | |||
575 | return NULL; | 575 | return NULL; |
576 | } | 576 | } |
577 | 577 | ||
578 | EXPORT_SYMBOL(rt6_lookup); | ||
579 | |||
578 | /* ip6_ins_rt is called with FREE table->tb6_lock. | 580 | /* ip6_ins_rt is called with FREE table->tb6_lock. |
579 | It takes new route entry, the addition fails by any reason the | 581 | It takes new route entry, the addition fails by any reason the |
580 | route is freed. In any case, if caller does not hold it, it may | 582 | route is freed. In any case, if caller does not hold it, it may |
@@ -724,7 +726,7 @@ out2: | |||
724 | 726 | ||
725 | void ip6_route_input(struct sk_buff *skb) | 727 | void ip6_route_input(struct sk_buff *skb) |
726 | { | 728 | { |
727 | struct ipv6hdr *iph = skb->nh.ipv6h; | 729 | struct ipv6hdr *iph = ipv6_hdr(skb); |
728 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 730 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
729 | struct flowi fl = { | 731 | struct flowi fl = { |
730 | .iif = skb->dev->ifindex, | 732 | .iif = skb->dev->ifindex, |
@@ -829,6 +831,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
829 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); | 831 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); |
830 | } | 832 | } |
831 | 833 | ||
834 | EXPORT_SYMBOL(ip6_route_output); | ||
832 | 835 | ||
833 | /* | 836 | /* |
834 | * Destination cache support functions | 837 | * Destination cache support functions |
@@ -1757,7 +1760,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1757 | rtnl_unlock(); | 1760 | rtnl_unlock(); |
1758 | 1761 | ||
1759 | return err; | 1762 | return err; |
1760 | }; | 1763 | } |
1761 | 1764 | ||
1762 | return -EINVAL; | 1765 | return -EINVAL; |
1763 | } | 1766 | } |
@@ -1772,7 +1775,7 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code, | |||
1772 | int type; | 1775 | int type; |
1773 | switch (ipstats_mib_noroutes) { | 1776 | switch (ipstats_mib_noroutes) { |
1774 | case IPSTATS_MIB_INNOROUTES: | 1777 | case IPSTATS_MIB_INNOROUTES: |
1775 | type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1778 | type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); |
1776 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { | 1779 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { |
1777 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); | 1780 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); |
1778 | break; | 1781 | break; |
@@ -2012,7 +2015,7 @@ errout: | |||
2012 | return err; | 2015 | return err; |
2013 | } | 2016 | } |
2014 | 2017 | ||
2015 | int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2018 | static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2016 | { | 2019 | { |
2017 | struct fib6_config cfg; | 2020 | struct fib6_config cfg; |
2018 | int err; | 2021 | int err; |
@@ -2024,7 +2027,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
2024 | return ip6_route_del(&cfg); | 2027 | return ip6_route_del(&cfg); |
2025 | } | 2028 | } |
2026 | 2029 | ||
2027 | int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 2030 | static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
2028 | { | 2031 | { |
2029 | struct fib6_config cfg; | 2032 | struct fib6_config cfg; |
2030 | int err; | 2033 | int err; |
@@ -2161,7 +2164,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2161 | prefix, NLM_F_MULTI); | 2164 | prefix, NLM_F_MULTI); |
2162 | } | 2165 | } |
2163 | 2166 | ||
2164 | int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | 2167 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) |
2165 | { | 2168 | { |
2166 | struct nlattr *tb[RTA_MAX+1]; | 2169 | struct nlattr *tb[RTA_MAX+1]; |
2167 | struct rt6_info *rt; | 2170 | struct rt6_info *rt; |
@@ -2215,7 +2218,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | |||
2215 | /* Reserve room for dummy headers, this skb can pass | 2218 | /* Reserve room for dummy headers, this skb can pass |
2216 | through good chunk of routing engine. | 2219 | through good chunk of routing engine. |
2217 | */ | 2220 | */ |
2218 | skb->mac.raw = skb->data; | 2221 | skb_reset_mac_header(skb); |
2219 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2222 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2220 | 2223 | ||
2221 | rt = (struct rt6_info*) ip6_route_output(NULL, &fl); | 2224 | rt = (struct rt6_info*) ip6_route_output(NULL, &fl); |
@@ -2486,8 +2489,9 @@ ctl_table ipv6_route_table[] = { | |||
2486 | 2489 | ||
2487 | void __init ip6_route_init(void) | 2490 | void __init ip6_route_init(void) |
2488 | { | 2491 | { |
2492 | #ifdef CONFIG_PROC_FS | ||
2489 | struct proc_dir_entry *p; | 2493 | struct proc_dir_entry *p; |
2490 | 2494 | #endif | |
2491 | ip6_dst_ops.kmem_cachep = | 2495 | ip6_dst_ops.kmem_cachep = |
2492 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2496 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2493 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | 2497 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); |
@@ -2505,6 +2509,10 @@ void __init ip6_route_init(void) | |||
2505 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2509 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2506 | fib6_rules_init(); | 2510 | fib6_rules_init(); |
2507 | #endif | 2511 | #endif |
2512 | |||
2513 | __rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL); | ||
2514 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL); | ||
2515 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL); | ||
2508 | } | 2516 | } |
2509 | 2517 | ||
2510 | void ip6_route_cleanup(void) | 2518 | void ip6_route_cleanup(void) |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 08d6ed3396e4..1efa95a99f45 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -99,10 +99,10 @@ static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) | |||
99 | return NULL; | 99 | return NULL; |
100 | } | 100 | } |
101 | 101 | ||
102 | static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) | 102 | static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms) |
103 | { | 103 | { |
104 | __be32 remote = t->parms.iph.daddr; | 104 | __be32 remote = parms->iph.daddr; |
105 | __be32 local = t->parms.iph.saddr; | 105 | __be32 local = parms->iph.saddr; |
106 | unsigned h = 0; | 106 | unsigned h = 0; |
107 | int prio = 0; | 107 | int prio = 0; |
108 | 108 | ||
@@ -117,6 +117,11 @@ static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) | |||
117 | return &tunnels[prio][h]; | 117 | return &tunnels[prio][h]; |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline struct ip_tunnel **ipip6_bucket(struct ip_tunnel *t) | ||
121 | { | ||
122 | return __ipip6_bucket(&t->parms); | ||
123 | } | ||
124 | |||
120 | static void ipip6_tunnel_unlink(struct ip_tunnel *t) | 125 | static void ipip6_tunnel_unlink(struct ip_tunnel *t) |
121 | { | 126 | { |
122 | struct ip_tunnel **tp; | 127 | struct ip_tunnel **tp; |
@@ -147,19 +152,9 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int | |||
147 | __be32 local = parms->iph.saddr; | 152 | __be32 local = parms->iph.saddr; |
148 | struct ip_tunnel *t, **tp, *nt; | 153 | struct ip_tunnel *t, **tp, *nt; |
149 | struct net_device *dev; | 154 | struct net_device *dev; |
150 | unsigned h = 0; | ||
151 | int prio = 0; | ||
152 | char name[IFNAMSIZ]; | 155 | char name[IFNAMSIZ]; |
153 | 156 | ||
154 | if (remote) { | 157 | for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) { |
155 | prio |= 2; | ||
156 | h ^= HASH(remote); | ||
157 | } | ||
158 | if (local) { | ||
159 | prio |= 1; | ||
160 | h ^= HASH(local); | ||
161 | } | ||
162 | for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) { | ||
163 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 158 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) |
164 | return t; | 159 | return t; |
165 | } | 160 | } |
@@ -224,8 +219,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
224 | ICMP in the real Internet is absolutely infeasible. | 219 | ICMP in the real Internet is absolutely infeasible. |
225 | */ | 220 | */ |
226 | struct iphdr *iph = (struct iphdr*)skb->data; | 221 | struct iphdr *iph = (struct iphdr*)skb->data; |
227 | int type = skb->h.icmph->type; | 222 | const int type = icmp_hdr(skb)->type; |
228 | int code = skb->h.icmph->code; | 223 | const int code = icmp_hdr(skb)->code; |
229 | struct ip_tunnel *t; | 224 | struct ip_tunnel *t; |
230 | int err; | 225 | int err; |
231 | 226 | ||
@@ -280,8 +275,8 @@ out: | |||
280 | struct iphdr *iph = (struct iphdr*)dp; | 275 | struct iphdr *iph = (struct iphdr*)dp; |
281 | int hlen = iph->ihl<<2; | 276 | int hlen = iph->ihl<<2; |
282 | struct ipv6hdr *iph6; | 277 | struct ipv6hdr *iph6; |
283 | int type = skb->h.icmph->type; | 278 | const int type = icmp_hdr(skb)->type; |
284 | int code = skb->h.icmph->code; | 279 | const int code = icmp_hdr(skb)->code; |
285 | int rel_type = 0; | 280 | int rel_type = 0; |
286 | int rel_code = 0; | 281 | int rel_code = 0; |
287 | int rel_info = 0; | 282 | int rel_info = 0; |
@@ -296,14 +291,14 @@ out: | |||
296 | default: | 291 | default: |
297 | return; | 292 | return; |
298 | case ICMP_PARAMETERPROB: | 293 | case ICMP_PARAMETERPROB: |
299 | if (skb->h.icmph->un.gateway < hlen) | 294 | if (icmp_hdr(skb)->un.gateway < hlen) |
300 | return; | 295 | return; |
301 | 296 | ||
302 | /* So... This guy found something strange INSIDE encapsulated | 297 | /* So... This guy found something strange INSIDE encapsulated |
303 | packet. Well, he is fool, but what can we do ? | 298 | packet. Well, he is fool, but what can we do ? |
304 | */ | 299 | */ |
305 | rel_type = ICMPV6_PARAMPROB; | 300 | rel_type = ICMPV6_PARAMPROB; |
306 | rel_info = skb->h.icmph->un.gateway - hlen; | 301 | rel_info = icmp_hdr(skb)->un.gateway - hlen; |
307 | break; | 302 | break; |
308 | 303 | ||
309 | case ICMP_DEST_UNREACH: | 304 | case ICMP_DEST_UNREACH: |
@@ -340,7 +335,7 @@ out: | |||
340 | dst_release(skb2->dst); | 335 | dst_release(skb2->dst); |
341 | skb2->dst = NULL; | 336 | skb2->dst = NULL; |
342 | skb_pull(skb2, skb->data - (u8*)iph6); | 337 | skb_pull(skb2, skb->data - (u8*)iph6); |
343 | skb2->nh.raw = skb2->data; | 338 | skb_reset_network_header(skb2); |
344 | 339 | ||
345 | /* Try to guess incoming interface */ | 340 | /* Try to guess incoming interface */ |
346 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); | 341 | rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); |
@@ -366,7 +361,7 @@ out: | |||
366 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 361 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) |
367 | { | 362 | { |
368 | if (INET_ECN_is_ce(iph->tos)) | 363 | if (INET_ECN_is_ce(iph->tos)) |
369 | IP6_ECN_set_ce(skb->nh.ipv6h); | 364 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
370 | } | 365 | } |
371 | 366 | ||
372 | static int ipip6_rcv(struct sk_buff *skb) | 367 | static int ipip6_rcv(struct sk_buff *skb) |
@@ -377,13 +372,13 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
377 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 372 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
378 | goto out; | 373 | goto out; |
379 | 374 | ||
380 | iph = skb->nh.iph; | 375 | iph = ip_hdr(skb); |
381 | 376 | ||
382 | read_lock(&ipip6_lock); | 377 | read_lock(&ipip6_lock); |
383 | if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { | 378 | if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { |
384 | secpath_reset(skb); | 379 | secpath_reset(skb); |
385 | skb->mac.raw = skb->nh.raw; | 380 | skb->mac_header = skb->network_header; |
386 | skb->nh.raw = skb->data; | 381 | skb_reset_network_header(skb); |
387 | IPCB(skb)->flags = 0; | 382 | IPCB(skb)->flags = 0; |
388 | skb->protocol = htons(ETH_P_IPV6); | 383 | skb->protocol = htons(ETH_P_IPV6); |
389 | skb->pkt_type = PACKET_HOST; | 384 | skb->pkt_type = PACKET_HOST; |
@@ -430,7 +425,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
430 | struct ip_tunnel *tunnel = netdev_priv(dev); | 425 | struct ip_tunnel *tunnel = netdev_priv(dev); |
431 | struct net_device_stats *stats = &tunnel->stat; | 426 | struct net_device_stats *stats = &tunnel->stat; |
432 | struct iphdr *tiph = &tunnel->parms.iph; | 427 | struct iphdr *tiph = &tunnel->parms.iph; |
433 | struct ipv6hdr *iph6 = skb->nh.ipv6h; | 428 | struct ipv6hdr *iph6 = ipv6_hdr(skb); |
434 | u8 tos = tunnel->parms.iph.tos; | 429 | u8 tos = tunnel->parms.iph.tos; |
435 | struct rtable *rt; /* Route to the other host */ | 430 | struct rtable *rt; /* Route to the other host */ |
436 | struct net_device *tdev; /* Device to other host */ | 431 | struct net_device *tdev; /* Device to other host */ |
@@ -468,7 +463,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
468 | addr_type = ipv6_addr_type(addr6); | 463 | addr_type = ipv6_addr_type(addr6); |
469 | 464 | ||
470 | if (addr_type == IPV6_ADDR_ANY) { | 465 | if (addr_type == IPV6_ADDR_ANY) { |
471 | addr6 = &skb->nh.ipv6h->daddr; | 466 | addr6 = &ipv6_hdr(skb)->daddr; |
472 | addr_type = ipv6_addr_type(addr6); | 467 | addr_type = ipv6_addr_type(addr6); |
473 | } | 468 | } |
474 | 469 | ||
@@ -550,11 +545,12 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
550 | skb_set_owner_w(new_skb, skb->sk); | 545 | skb_set_owner_w(new_skb, skb->sk); |
551 | dev_kfree_skb(skb); | 546 | dev_kfree_skb(skb); |
552 | skb = new_skb; | 547 | skb = new_skb; |
553 | iph6 = skb->nh.ipv6h; | 548 | iph6 = ipv6_hdr(skb); |
554 | } | 549 | } |
555 | 550 | ||
556 | skb->h.raw = skb->nh.raw; | 551 | skb->transport_header = skb->network_header; |
557 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 552 | skb_push(skb, sizeof(struct iphdr)); |
553 | skb_reset_network_header(skb); | ||
558 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 554 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
559 | IPCB(skb)->flags = 0; | 555 | IPCB(skb)->flags = 0; |
560 | dst_release(skb->dst); | 556 | dst_release(skb->dst); |
@@ -564,7 +560,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
564 | * Push down and install the IPIP header. | 560 | * Push down and install the IPIP header. |
565 | */ | 561 | */ |
566 | 562 | ||
567 | iph = skb->nh.iph; | 563 | iph = ip_hdr(skb); |
568 | iph->version = 4; | 564 | iph->version = 4; |
569 | iph->ihl = sizeof(struct iphdr)>>2; | 565 | iph->ihl = sizeof(struct iphdr)>>2; |
570 | if (mtu > IPV6_MIN_MTU) | 566 | if (mtu > IPV6_MIN_MTU) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 92f99927d12d..e2f25ea43b68 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -115,10 +115,10 @@ static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len, | |||
115 | 115 | ||
116 | static __u32 tcp_v6_init_sequence(struct sk_buff *skb) | 116 | static __u32 tcp_v6_init_sequence(struct sk_buff *skb) |
117 | { | 117 | { |
118 | return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, | 118 | return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, |
119 | skb->nh.ipv6h->saddr.s6_addr32, | 119 | ipv6_hdr(skb)->saddr.s6_addr32, |
120 | skb->h.th->dest, | 120 | tcp_hdr(skb)->dest, |
121 | skb->h.th->source); | 121 | tcp_hdr(skb)->source); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | 124 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, |
@@ -486,7 +486,9 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
486 | struct sk_buff *pktopts = treq->pktopts; | 486 | struct sk_buff *pktopts = treq->pktopts; |
487 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); | 487 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); |
488 | if (rxopt->srcrt) | 488 | if (rxopt->srcrt) |
489 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt)); | 489 | opt = ipv6_invert_rthdr(sk, |
490 | (struct ipv6_rt_hdr *)(skb_network_header(pktopts) + | ||
491 | rxopt->srcrt)); | ||
490 | } | 492 | } |
491 | 493 | ||
492 | if (opt && opt->srcrt) { | 494 | if (opt && opt->srcrt) { |
@@ -507,7 +509,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
507 | 509 | ||
508 | skb = tcp_make_synack(sk, dst, req); | 510 | skb = tcp_make_synack(sk, dst, req); |
509 | if (skb) { | 511 | if (skb) { |
510 | struct tcphdr *th = skb->h.th; | 512 | struct tcphdr *th = tcp_hdr(skb); |
511 | 513 | ||
512 | th->check = tcp_v6_check(th, skb->len, | 514 | th->check = tcp_v6_check(th, skb->len, |
513 | &treq->loc_addr, &treq->rmt_addr, | 515 | &treq->loc_addr, &treq->rmt_addr, |
@@ -835,8 +837,8 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
835 | { | 837 | { |
836 | __u8 *hash_location = NULL; | 838 | __u8 *hash_location = NULL; |
837 | struct tcp_md5sig_key *hash_expected; | 839 | struct tcp_md5sig_key *hash_expected; |
838 | struct ipv6hdr *ip6h = skb->nh.ipv6h; | 840 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
839 | struct tcphdr *th = skb->h.th; | 841 | struct tcphdr *th = tcp_hdr(skb); |
840 | int length = (th->doff << 2) - sizeof (*th); | 842 | int length = (th->doff << 2) - sizeof (*th); |
841 | int genhash; | 843 | int genhash; |
842 | u8 *ptr; | 844 | u8 *ptr; |
@@ -944,10 +946,11 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { | |||
944 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) | 946 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) |
945 | { | 947 | { |
946 | struct ipv6_pinfo *np = inet6_sk(sk); | 948 | struct ipv6_pinfo *np = inet6_sk(sk); |
947 | struct tcphdr *th = skb->h.th; | 949 | struct tcphdr *th = tcp_hdr(skb); |
948 | 950 | ||
949 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 951 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
950 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); | 952 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); |
953 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
951 | skb->csum_offset = offsetof(struct tcphdr, check); | 954 | skb->csum_offset = offsetof(struct tcphdr, check); |
952 | } else { | 955 | } else { |
953 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, | 956 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, |
@@ -964,12 +967,13 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
964 | if (!pskb_may_pull(skb, sizeof(*th))) | 967 | if (!pskb_may_pull(skb, sizeof(*th))) |
965 | return -EINVAL; | 968 | return -EINVAL; |
966 | 969 | ||
967 | ipv6h = skb->nh.ipv6h; | 970 | ipv6h = ipv6_hdr(skb); |
968 | th = skb->h.th; | 971 | th = tcp_hdr(skb); |
969 | 972 | ||
970 | th->check = 0; | 973 | th->check = 0; |
971 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, | 974 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, |
972 | IPPROTO_TCP, 0); | 975 | IPPROTO_TCP, 0); |
976 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
973 | skb->csum_offset = offsetof(struct tcphdr, check); | 977 | skb->csum_offset = offsetof(struct tcphdr, check); |
974 | skb->ip_summed = CHECKSUM_PARTIAL; | 978 | skb->ip_summed = CHECKSUM_PARTIAL; |
975 | return 0; | 979 | return 0; |
@@ -977,7 +981,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
977 | 981 | ||
978 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | 982 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) |
979 | { | 983 | { |
980 | struct tcphdr *th = skb->h.th, *t1; | 984 | struct tcphdr *th = tcp_hdr(skb), *t1; |
981 | struct sk_buff *buff; | 985 | struct sk_buff *buff; |
982 | struct flowi fl; | 986 | struct flowi fl; |
983 | int tot_len = sizeof(*th); | 987 | int tot_len = sizeof(*th); |
@@ -993,7 +997,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
993 | 997 | ||
994 | #ifdef CONFIG_TCP_MD5SIG | 998 | #ifdef CONFIG_TCP_MD5SIG |
995 | if (sk) | 999 | if (sk) |
996 | key = tcp_v6_md5_do_lookup(sk, &skb->nh.ipv6h->daddr); | 1000 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); |
997 | else | 1001 | else |
998 | key = NULL; | 1002 | key = NULL; |
999 | 1003 | ||
@@ -1037,20 +1041,18 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1037 | (TCPOPT_NOP << 16) | | 1041 | (TCPOPT_NOP << 16) | |
1038 | (TCPOPT_MD5SIG << 8) | | 1042 | (TCPOPT_MD5SIG << 8) | |
1039 | TCPOLEN_MD5SIG); | 1043 | TCPOLEN_MD5SIG); |
1040 | tcp_v6_do_calc_md5_hash((__u8*)&opt[1], | 1044 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, |
1041 | key, | 1045 | &ipv6_hdr(skb)->daddr, |
1042 | &skb->nh.ipv6h->daddr, | 1046 | &ipv6_hdr(skb)->saddr, |
1043 | &skb->nh.ipv6h->saddr, | 1047 | t1, IPPROTO_TCP, tot_len); |
1044 | t1, IPPROTO_TCP, | ||
1045 | tot_len); | ||
1046 | } | 1048 | } |
1047 | #endif | 1049 | #endif |
1048 | 1050 | ||
1049 | buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); | 1051 | buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); |
1050 | 1052 | ||
1051 | memset(&fl, 0, sizeof(fl)); | 1053 | memset(&fl, 0, sizeof(fl)); |
1052 | ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr); | 1054 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
1053 | ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr); | 1055 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
1054 | 1056 | ||
1055 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, | 1057 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, |
1056 | sizeof(*t1), IPPROTO_TCP, | 1058 | sizeof(*t1), IPPROTO_TCP, |
@@ -1079,7 +1081,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1079 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | 1081 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, |
1080 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1082 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) |
1081 | { | 1083 | { |
1082 | struct tcphdr *th = skb->h.th, *t1; | 1084 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1083 | struct sk_buff *buff; | 1085 | struct sk_buff *buff; |
1084 | struct flowi fl; | 1086 | struct flowi fl; |
1085 | int tot_len = sizeof(struct tcphdr); | 1087 | int tot_len = sizeof(struct tcphdr); |
@@ -1091,7 +1093,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1091 | 1093 | ||
1092 | #ifdef CONFIG_TCP_MD5SIG | 1094 | #ifdef CONFIG_TCP_MD5SIG |
1093 | if (!tw && skb->sk) { | 1095 | if (!tw && skb->sk) { |
1094 | key = tcp_v6_md5_do_lookup(skb->sk, &skb->nh.ipv6h->daddr); | 1096 | key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr); |
1095 | } else if (tw && tw->tw_md5_keylen) { | 1097 | } else if (tw && tw->tw_md5_keylen) { |
1096 | tw_key.key = tw->tw_md5_key; | 1098 | tw_key.key = tw->tw_md5_key; |
1097 | tw_key.keylen = tw->tw_md5_keylen; | 1099 | tw_key.keylen = tw->tw_md5_keylen; |
@@ -1140,20 +1142,18 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1140 | if (key) { | 1142 | if (key) { |
1141 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 1143 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
1142 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); | 1144 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); |
1143 | tcp_v6_do_calc_md5_hash((__u8 *)topt, | 1145 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, |
1144 | key, | 1146 | &ipv6_hdr(skb)->daddr, |
1145 | &skb->nh.ipv6h->daddr, | 1147 | &ipv6_hdr(skb)->saddr, |
1146 | &skb->nh.ipv6h->saddr, | 1148 | t1, IPPROTO_TCP, tot_len); |
1147 | t1, IPPROTO_TCP, | ||
1148 | tot_len); | ||
1149 | } | 1149 | } |
1150 | #endif | 1150 | #endif |
1151 | 1151 | ||
1152 | buff->csum = csum_partial((char *)t1, tot_len, 0); | 1152 | buff->csum = csum_partial((char *)t1, tot_len, 0); |
1153 | 1153 | ||
1154 | memset(&fl, 0, sizeof(fl)); | 1154 | memset(&fl, 0, sizeof(fl)); |
1155 | ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr); | 1155 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
1156 | ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr); | 1156 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
1157 | 1157 | ||
1158 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, | 1158 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, |
1159 | tot_len, IPPROTO_TCP, | 1159 | tot_len, IPPROTO_TCP, |
@@ -1197,18 +1197,18 @@ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | |||
1197 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | 1197 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) |
1198 | { | 1198 | { |
1199 | struct request_sock *req, **prev; | 1199 | struct request_sock *req, **prev; |
1200 | const struct tcphdr *th = skb->h.th; | 1200 | const struct tcphdr *th = tcp_hdr(skb); |
1201 | struct sock *nsk; | 1201 | struct sock *nsk; |
1202 | 1202 | ||
1203 | /* Find possible connection requests. */ | 1203 | /* Find possible connection requests. */ |
1204 | req = inet6_csk_search_req(sk, &prev, th->source, | 1204 | req = inet6_csk_search_req(sk, &prev, th->source, |
1205 | &skb->nh.ipv6h->saddr, | 1205 | &ipv6_hdr(skb)->saddr, |
1206 | &skb->nh.ipv6h->daddr, inet6_iif(skb)); | 1206 | &ipv6_hdr(skb)->daddr, inet6_iif(skb)); |
1207 | if (req) | 1207 | if (req) |
1208 | return tcp_check_req(sk, skb, req, prev); | 1208 | return tcp_check_req(sk, skb, req, prev); |
1209 | 1209 | ||
1210 | nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr, | 1210 | nsk = __inet6_lookup_established(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, |
1211 | th->source, &skb->nh.ipv6h->daddr, | 1211 | th->source, &ipv6_hdr(skb)->daddr, |
1212 | ntohs(th->dest), inet6_iif(skb)); | 1212 | ntohs(th->dest), inet6_iif(skb)); |
1213 | 1213 | ||
1214 | if (nsk) { | 1214 | if (nsk) { |
@@ -1275,9 +1275,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1275 | tcp_openreq_init(req, &tmp_opt, skb); | 1275 | tcp_openreq_init(req, &tmp_opt, skb); |
1276 | 1276 | ||
1277 | treq = inet6_rsk(req); | 1277 | treq = inet6_rsk(req); |
1278 | ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr); | 1278 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1279 | ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr); | 1279 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1280 | TCP_ECN_create_request(req, skb->h.th); | 1280 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1281 | treq->pktopts = NULL; | 1281 | treq->pktopts = NULL; |
1282 | if (ipv6_opt_accepted(sk, skb) || | 1282 | if (ipv6_opt_accepted(sk, skb) || |
1283 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1283 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
@@ -1363,7 +1363,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1363 | newnp->pktoptions = NULL; | 1363 | newnp->pktoptions = NULL; |
1364 | newnp->opt = NULL; | 1364 | newnp->opt = NULL; |
1365 | newnp->mcast_oif = inet6_iif(skb); | 1365 | newnp->mcast_oif = inet6_iif(skb); |
1366 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1366 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1367 | 1367 | ||
1368 | /* | 1368 | /* |
1369 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count | 1369 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
@@ -1389,7 +1389,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1389 | opt == NULL && treq->pktopts) { | 1389 | opt == NULL && treq->pktopts) { |
1390 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); | 1390 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); |
1391 | if (rxopt->srcrt) | 1391 | if (rxopt->srcrt) |
1392 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt)); | 1392 | opt = ipv6_invert_rthdr(sk, |
1393 | (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) + | ||
1394 | rxopt->srcrt)); | ||
1393 | } | 1395 | } |
1394 | 1396 | ||
1395 | if (dst == NULL) { | 1397 | if (dst == NULL) { |
@@ -1469,7 +1471,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1469 | } | 1471 | } |
1470 | newnp->opt = NULL; | 1472 | newnp->opt = NULL; |
1471 | newnp->mcast_oif = inet6_iif(skb); | 1473 | newnp->mcast_oif = inet6_iif(skb); |
1472 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1474 | newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; |
1473 | 1475 | ||
1474 | /* Clone native IPv6 options from listening socket (if any) | 1476 | /* Clone native IPv6 options from listening socket (if any) |
1475 | 1477 | ||
@@ -1528,15 +1530,16 @@ out: | |||
1528 | static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) | 1530 | static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) |
1529 | { | 1531 | { |
1530 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 1532 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
1531 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1533 | if (!tcp_v6_check(tcp_hdr(skb), skb->len, &ipv6_hdr(skb)->saddr, |
1532 | &skb->nh.ipv6h->daddr,skb->csum)) { | 1534 | &ipv6_hdr(skb)->daddr, skb->csum)) { |
1533 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1535 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1534 | return 0; | 1536 | return 0; |
1535 | } | 1537 | } |
1536 | } | 1538 | } |
1537 | 1539 | ||
1538 | skb->csum = ~csum_unfold(tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1540 | skb->csum = ~csum_unfold(tcp_v6_check(tcp_hdr(skb), skb->len, |
1539 | &skb->nh.ipv6h->daddr, 0)); | 1541 | &ipv6_hdr(skb)->saddr, |
1542 | &ipv6_hdr(skb)->daddr, 0)); | ||
1540 | 1543 | ||
1541 | if (skb->len <= 76) { | 1544 | if (skb->len <= 76) { |
1542 | return __skb_checksum_complete(skb); | 1545 | return __skb_checksum_complete(skb); |
@@ -1600,7 +1603,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1600 | 1603 | ||
1601 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1604 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1602 | TCP_CHECK_TIMER(sk); | 1605 | TCP_CHECK_TIMER(sk); |
1603 | if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) | 1606 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1604 | goto reset; | 1607 | goto reset; |
1605 | TCP_CHECK_TIMER(sk); | 1608 | TCP_CHECK_TIMER(sk); |
1606 | if (opt_skb) | 1609 | if (opt_skb) |
@@ -1608,7 +1611,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1608 | return 0; | 1611 | return 0; |
1609 | } | 1612 | } |
1610 | 1613 | ||
1611 | if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb)) | 1614 | if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb)) |
1612 | goto csum_err; | 1615 | goto csum_err; |
1613 | 1616 | ||
1614 | if (sk->sk_state == TCP_LISTEN) { | 1617 | if (sk->sk_state == TCP_LISTEN) { |
@@ -1631,7 +1634,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1631 | } | 1634 | } |
1632 | 1635 | ||
1633 | TCP_CHECK_TIMER(sk); | 1636 | TCP_CHECK_TIMER(sk); |
1634 | if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) | 1637 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1635 | goto reset; | 1638 | goto reset; |
1636 | TCP_CHECK_TIMER(sk); | 1639 | TCP_CHECK_TIMER(sk); |
1637 | if (opt_skb) | 1640 | if (opt_skb) |
@@ -1664,7 +1667,7 @@ ipv6_pktoptions: | |||
1664 | if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo) | 1667 | if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo) |
1665 | np->mcast_oif = inet6_iif(opt_skb); | 1668 | np->mcast_oif = inet6_iif(opt_skb); |
1666 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) | 1669 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) |
1667 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; | 1670 | np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; |
1668 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1671 | if (ipv6_opt_accepted(sk, opt_skb)) { |
1669 | skb_set_owner_r(opt_skb, sk); | 1672 | skb_set_owner_r(opt_skb, sk); |
1670 | opt_skb = xchg(&np->pktoptions, opt_skb); | 1673 | opt_skb = xchg(&np->pktoptions, opt_skb); |
@@ -1697,28 +1700,27 @@ static int tcp_v6_rcv(struct sk_buff **pskb) | |||
1697 | if (!pskb_may_pull(skb, sizeof(struct tcphdr))) | 1700 | if (!pskb_may_pull(skb, sizeof(struct tcphdr))) |
1698 | goto discard_it; | 1701 | goto discard_it; |
1699 | 1702 | ||
1700 | th = skb->h.th; | 1703 | th = tcp_hdr(skb); |
1701 | 1704 | ||
1702 | if (th->doff < sizeof(struct tcphdr)/4) | 1705 | if (th->doff < sizeof(struct tcphdr)/4) |
1703 | goto bad_packet; | 1706 | goto bad_packet; |
1704 | if (!pskb_may_pull(skb, th->doff*4)) | 1707 | if (!pskb_may_pull(skb, th->doff*4)) |
1705 | goto discard_it; | 1708 | goto discard_it; |
1706 | 1709 | ||
1707 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY && | 1710 | if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb)) |
1708 | tcp_v6_checksum_init(skb))) | ||
1709 | goto bad_packet; | 1711 | goto bad_packet; |
1710 | 1712 | ||
1711 | th = skb->h.th; | 1713 | th = tcp_hdr(skb); |
1712 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1714 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
1713 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | 1715 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + |
1714 | skb->len - th->doff*4); | 1716 | skb->len - th->doff*4); |
1715 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1717 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
1716 | TCP_SKB_CB(skb)->when = 0; | 1718 | TCP_SKB_CB(skb)->when = 0; |
1717 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); | 1719 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1718 | TCP_SKB_CB(skb)->sacked = 0; | 1720 | TCP_SKB_CB(skb)->sacked = 0; |
1719 | 1721 | ||
1720 | sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source, | 1722 | sk = __inet6_lookup(&tcp_hashinfo, &ipv6_hdr(skb)->saddr, th->source, |
1721 | &skb->nh.ipv6h->daddr, ntohs(th->dest), | 1723 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), |
1722 | inet6_iif(skb)); | 1724 | inet6_iif(skb)); |
1723 | 1725 | ||
1724 | if (!sk) | 1726 | if (!sk) |
@@ -1798,7 +1800,7 @@ do_time_wait: | |||
1798 | struct sock *sk2; | 1800 | struct sock *sk2; |
1799 | 1801 | ||
1800 | sk2 = inet6_lookup_listener(&tcp_hashinfo, | 1802 | sk2 = inet6_lookup_listener(&tcp_hashinfo, |
1801 | &skb->nh.ipv6h->daddr, | 1803 | &ipv6_hdr(skb)->daddr, |
1802 | ntohs(th->dest), inet6_iif(skb)); | 1804 | ntohs(th->dest), inet6_iif(skb)); |
1803 | if (sk2 != NULL) { | 1805 | if (sk2 != NULL) { |
1804 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1806 | struct inet_timewait_sock *tw = inet_twsk(sk); |
@@ -1945,6 +1947,7 @@ static int tcp_v6_destroy_sock(struct sock *sk) | |||
1945 | return inet6_destroy_sock(sk); | 1947 | return inet6_destroy_sock(sk); |
1946 | } | 1948 | } |
1947 | 1949 | ||
1950 | #ifdef CONFIG_PROC_FS | ||
1948 | /* Proc filesystem TCPv6 sock list dumping. */ | 1951 | /* Proc filesystem TCPv6 sock list dumping. */ |
1949 | static void get_openreq6(struct seq_file *seq, | 1952 | static void get_openreq6(struct seq_file *seq, |
1950 | struct sock *sk, struct request_sock *req, int i, int uid) | 1953 | struct sock *sk, struct request_sock *req, int i, int uid) |
@@ -2061,7 +2064,6 @@ static void get_timewait6_sock(struct seq_file *seq, | |||
2061 | atomic_read(&tw->tw_refcnt), tw); | 2064 | atomic_read(&tw->tw_refcnt), tw); |
2062 | } | 2065 | } |
2063 | 2066 | ||
2064 | #ifdef CONFIG_PROC_FS | ||
2065 | static int tcp6_seq_show(struct seq_file *seq, void *v) | 2067 | static int tcp6_seq_show(struct seq_file *seq, void *v) |
2066 | { | 2068 | { |
2067 | struct tcp_iter_state *st; | 2069 | struct tcp_iter_state *st; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index f590db57a7c9..b083c09e3d2d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -93,10 +93,10 @@ static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, | |||
93 | continue; | 93 | continue; |
94 | score++; | 94 | score++; |
95 | } | 95 | } |
96 | if(score == 4) { | 96 | if (score == 4) { |
97 | result = sk; | 97 | result = sk; |
98 | break; | 98 | break; |
99 | } else if(score > badness) { | 99 | } else if (score > badness) { |
100 | result = sk; | 100 | result = sk; |
101 | badness = score; | 101 | badness = score; |
102 | } | 102 | } |
@@ -120,8 +120,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
120 | struct ipv6_pinfo *np = inet6_sk(sk); | 120 | struct ipv6_pinfo *np = inet6_sk(sk); |
121 | struct inet_sock *inet = inet_sk(sk); | 121 | struct inet_sock *inet = inet_sk(sk); |
122 | struct sk_buff *skb; | 122 | struct sk_buff *skb; |
123 | size_t copied; | 123 | unsigned int ulen, copied; |
124 | int err, copy_only, is_udplite = IS_UDPLITE(sk); | 124 | int err; |
125 | int is_udplite = IS_UDPLITE(sk); | ||
125 | 126 | ||
126 | if (addr_len) | 127 | if (addr_len) |
127 | *addr_len=sizeof(struct sockaddr_in6); | 128 | *addr_len=sizeof(struct sockaddr_in6); |
@@ -134,24 +135,25 @@ try_again: | |||
134 | if (!skb) | 135 | if (!skb) |
135 | goto out; | 136 | goto out; |
136 | 137 | ||
137 | copied = skb->len - sizeof(struct udphdr); | 138 | ulen = skb->len - sizeof(struct udphdr); |
138 | if (copied > len) { | 139 | copied = len; |
139 | copied = len; | 140 | if (copied > ulen) |
141 | copied = ulen; | ||
142 | else if (copied < ulen) | ||
140 | msg->msg_flags |= MSG_TRUNC; | 143 | msg->msg_flags |= MSG_TRUNC; |
141 | } | ||
142 | 144 | ||
143 | /* | 145 | /* |
144 | * Decide whether to checksum and/or copy data. | 146 | * If checksum is needed at all, try to do it while copying the |
147 | * data. If the data is truncated, or if we only want a partial | ||
148 | * coverage checksum (UDP-Lite), do it before the copy. | ||
145 | */ | 149 | */ |
146 | copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY); | ||
147 | 150 | ||
148 | if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) { | 151 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
149 | if (__udp_lib_checksum_complete(skb)) | 152 | if (udp_lib_checksum_complete(skb)) |
150 | goto csum_copy_err; | 153 | goto csum_copy_err; |
151 | copy_only = 1; | ||
152 | } | 154 | } |
153 | 155 | ||
154 | if (copy_only) | 156 | if (skb_csum_unnecessary(skb)) |
155 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 157 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
156 | msg->msg_iov, copied ); | 158 | msg->msg_iov, copied ); |
157 | else { | 159 | else { |
@@ -170,15 +172,16 @@ try_again: | |||
170 | 172 | ||
171 | sin6 = (struct sockaddr_in6 *) msg->msg_name; | 173 | sin6 = (struct sockaddr_in6 *) msg->msg_name; |
172 | sin6->sin6_family = AF_INET6; | 174 | sin6->sin6_family = AF_INET6; |
173 | sin6->sin6_port = skb->h.uh->source; | 175 | sin6->sin6_port = udp_hdr(skb)->source; |
174 | sin6->sin6_flowinfo = 0; | 176 | sin6->sin6_flowinfo = 0; |
175 | sin6->sin6_scope_id = 0; | 177 | sin6->sin6_scope_id = 0; |
176 | 178 | ||
177 | if (skb->protocol == htons(ETH_P_IP)) | 179 | if (skb->protocol == htons(ETH_P_IP)) |
178 | ipv6_addr_set(&sin6->sin6_addr, 0, 0, | 180 | ipv6_addr_set(&sin6->sin6_addr, 0, 0, |
179 | htonl(0xffff), skb->nh.iph->saddr); | 181 | htonl(0xffff), ip_hdr(skb)->saddr); |
180 | else { | 182 | else { |
181 | ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); | 183 | ipv6_addr_copy(&sin6->sin6_addr, |
184 | &ipv6_hdr(skb)->saddr); | ||
182 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 185 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
183 | sin6->sin6_scope_id = IP6CB(skb)->iif; | 186 | sin6->sin6_scope_id = IP6CB(skb)->iif; |
184 | } | 187 | } |
@@ -194,7 +197,7 @@ try_again: | |||
194 | 197 | ||
195 | err = copied; | 198 | err = copied; |
196 | if (flags & MSG_TRUNC) | 199 | if (flags & MSG_TRUNC) |
197 | err = skb->len - sizeof(struct udphdr); | 200 | err = ulen; |
198 | 201 | ||
199 | out_free: | 202 | out_free: |
200 | skb_free_datagram(sk, skb); | 203 | skb_free_datagram(sk, skb); |
@@ -279,8 +282,10 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
279 | } | 282 | } |
280 | } | 283 | } |
281 | 284 | ||
282 | if (udp_lib_checksum_complete(skb)) | 285 | if (sk->sk_filter) { |
283 | goto drop; | 286 | if (udp_lib_checksum_complete(skb)) |
287 | goto drop; | ||
288 | } | ||
284 | 289 | ||
285 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { | 290 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { |
286 | /* Note that an ENOMEM error is charged twice */ | 291 | /* Note that an ENOMEM error is charged twice */ |
@@ -325,7 +330,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
325 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 330 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
326 | continue; | 331 | continue; |
327 | } | 332 | } |
328 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) | 333 | if (!inet6_mc_check(s, loc_addr, rmt_addr)) |
329 | continue; | 334 | continue; |
330 | return s; | 335 | return s; |
331 | } | 336 | } |
@@ -341,7 +346,7 @@ static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr, | |||
341 | struct in6_addr *daddr, struct hlist_head udptable[]) | 346 | struct in6_addr *daddr, struct hlist_head udptable[]) |
342 | { | 347 | { |
343 | struct sock *sk, *sk2; | 348 | struct sock *sk, *sk2; |
344 | const struct udphdr *uh = skb->h.uh; | 349 | const struct udphdr *uh = udp_hdr(skb); |
345 | int dif; | 350 | int dif; |
346 | 351 | ||
347 | read_lock(&udp_hash_lock); | 352 | read_lock(&udp_hash_lock); |
@@ -366,9 +371,20 @@ out: | |||
366 | return 0; | 371 | return 0; |
367 | } | 372 | } |
368 | 373 | ||
369 | static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) | 374 | static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, |
370 | 375 | int proto) | |
371 | { | 376 | { |
377 | int err; | ||
378 | |||
379 | UDP_SKB_CB(skb)->partial_cov = 0; | ||
380 | UDP_SKB_CB(skb)->cscov = skb->len; | ||
381 | |||
382 | if (proto == IPPROTO_UDPLITE) { | ||
383 | err = udplite_checksum_init(skb, uh); | ||
384 | if (err) | ||
385 | return err; | ||
386 | } | ||
387 | |||
372 | if (uh->check == 0) { | 388 | if (uh->check == 0) { |
373 | /* RFC 2460 section 8.1 says that we SHOULD log | 389 | /* RFC 2460 section 8.1 says that we SHOULD log |
374 | this error. Well, it is reasonable. | 390 | this error. Well, it is reasonable. |
@@ -377,21 +393,20 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) | |||
377 | return 1; | 393 | return 1; |
378 | } | 394 | } |
379 | if (skb->ip_summed == CHECKSUM_COMPLETE && | 395 | if (skb->ip_summed == CHECKSUM_COMPLETE && |
380 | !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, | 396 | !csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
381 | skb->len, IPPROTO_UDP, skb->csum )) | 397 | skb->len, proto, skb->csum)) |
382 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 398 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
383 | 399 | ||
384 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 400 | if (!skb_csum_unnecessary(skb)) |
385 | skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 401 | skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, |
386 | &skb->nh.ipv6h->daddr, | 402 | &ipv6_hdr(skb)->daddr, |
387 | skb->len, IPPROTO_UDP, | 403 | skb->len, proto, 0)); |
388 | 0)); | ||
389 | 404 | ||
390 | return (UDP_SKB_CB(skb)->partial_cov = 0); | 405 | return 0; |
391 | } | 406 | } |
392 | 407 | ||
393 | int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | 408 | int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], |
394 | int is_udplite) | 409 | int proto) |
395 | { | 410 | { |
396 | struct sk_buff *skb = *pskb; | 411 | struct sk_buff *skb = *pskb; |
397 | struct sock *sk; | 412 | struct sock *sk; |
@@ -403,15 +418,16 @@ int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | |||
403 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 418 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
404 | goto short_packet; | 419 | goto short_packet; |
405 | 420 | ||
406 | saddr = &skb->nh.ipv6h->saddr; | 421 | saddr = &ipv6_hdr(skb)->saddr; |
407 | daddr = &skb->nh.ipv6h->daddr; | 422 | daddr = &ipv6_hdr(skb)->daddr; |
408 | uh = skb->h.uh; | 423 | uh = udp_hdr(skb); |
409 | 424 | ||
410 | ulen = ntohs(uh->len); | 425 | ulen = ntohs(uh->len); |
411 | if (ulen > skb->len) | 426 | if (ulen > skb->len) |
412 | goto short_packet; | 427 | goto short_packet; |
413 | 428 | ||
414 | if(! is_udplite ) { /* UDP validates ulen. */ | 429 | if (proto == IPPROTO_UDP) { |
430 | /* UDP validates ulen. */ | ||
415 | 431 | ||
416 | /* Check for jumbo payload */ | 432 | /* Check for jumbo payload */ |
417 | if (ulen == 0) | 433 | if (ulen == 0) |
@@ -423,19 +439,15 @@ int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | |||
423 | if (ulen < skb->len) { | 439 | if (ulen < skb->len) { |
424 | if (pskb_trim_rcsum(skb, ulen)) | 440 | if (pskb_trim_rcsum(skb, ulen)) |
425 | goto short_packet; | 441 | goto short_packet; |
426 | saddr = &skb->nh.ipv6h->saddr; | 442 | saddr = &ipv6_hdr(skb)->saddr; |
427 | daddr = &skb->nh.ipv6h->daddr; | 443 | daddr = &ipv6_hdr(skb)->daddr; |
428 | uh = skb->h.uh; | 444 | uh = udp_hdr(skb); |
429 | } | 445 | } |
430 | |||
431 | if (udp6_csum_init(skb, uh)) | ||
432 | goto discard; | ||
433 | |||
434 | } else { /* UDP-Lite validates cscov. */ | ||
435 | if (udplite6_csum_init(skb, uh)) | ||
436 | goto discard; | ||
437 | } | 446 | } |
438 | 447 | ||
448 | if (udp6_csum_init(skb, uh, proto)) | ||
449 | goto discard; | ||
450 | |||
439 | /* | 451 | /* |
440 | * Multicast receive code | 452 | * Multicast receive code |
441 | */ | 453 | */ |
@@ -457,33 +469,34 @@ int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | |||
457 | 469 | ||
458 | if (udp_lib_checksum_complete(skb)) | 470 | if (udp_lib_checksum_complete(skb)) |
459 | goto discard; | 471 | goto discard; |
460 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite); | 472 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); |
461 | 473 | ||
462 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); | 474 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); |
463 | 475 | ||
464 | kfree_skb(skb); | 476 | kfree_skb(skb); |
465 | return(0); | 477 | return 0; |
466 | } | 478 | } |
467 | 479 | ||
468 | /* deliver */ | 480 | /* deliver */ |
469 | 481 | ||
470 | udpv6_queue_rcv_skb(sk, skb); | 482 | udpv6_queue_rcv_skb(sk, skb); |
471 | sock_put(sk); | 483 | sock_put(sk); |
472 | return(0); | 484 | return 0; |
473 | 485 | ||
474 | short_packet: | 486 | short_packet: |
475 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", | 487 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", |
476 | is_udplite? "-Lite" : "", ulen, skb->len); | 488 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
489 | ulen, skb->len); | ||
477 | 490 | ||
478 | discard: | 491 | discard: |
479 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); | 492 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
480 | kfree_skb(skb); | 493 | kfree_skb(skb); |
481 | return(0); | 494 | return 0; |
482 | } | 495 | } |
483 | 496 | ||
484 | static __inline__ int udpv6_rcv(struct sk_buff **pskb) | 497 | static __inline__ int udpv6_rcv(struct sk_buff **pskb) |
485 | { | 498 | { |
486 | return __udp6_lib_rcv(pskb, udp_hash, 0); | 499 | return __udp6_lib_rcv(pskb, udp_hash, IPPROTO_UDP); |
487 | } | 500 | } |
488 | 501 | ||
489 | /* | 502 | /* |
@@ -521,7 +534,7 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
521 | /* | 534 | /* |
522 | * Create a UDP header | 535 | * Create a UDP header |
523 | */ | 536 | */ |
524 | uh = skb->h.uh; | 537 | uh = udp_hdr(skb); |
525 | uh->source = fl->fl_ip_sport; | 538 | uh->source = fl->fl_ip_sport; |
526 | uh->dest = fl->fl_ip_dport; | 539 | uh->dest = fl->fl_ip_dport; |
527 | uh->len = htons(up->len); | 540 | uh->len = htons(up->len); |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 629f97162fbc..f54016a55004 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -19,7 +19,7 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; | |||
19 | 19 | ||
20 | static int udplitev6_rcv(struct sk_buff **pskb) | 20 | static int udplitev6_rcv(struct sk_buff **pskb) |
21 | { | 21 | { |
22 | return __udp6_lib_rcv(pskb, udplite_hash, 1); | 22 | return __udp6_lib_rcv(pskb, udplite_hash, IPPROTO_UDPLITE); |
23 | } | 23 | } |
24 | 24 | ||
25 | static void udplitev6_err(struct sk_buff *skb, | 25 | static void udplitev6_err(struct sk_buff *skb, |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 31f651f95096..d7ed8aa56ec1 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -28,14 +28,14 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
28 | unsigned int nhoff; | 28 | unsigned int nhoff; |
29 | 29 | ||
30 | nhoff = IP6CB(skb)->nhoff; | 30 | nhoff = IP6CB(skb)->nhoff; |
31 | nexthdr = skb->nh.raw[nhoff]; | 31 | nexthdr = skb_network_header(skb)[nhoff]; |
32 | 32 | ||
33 | seq = 0; | 33 | seq = 0; |
34 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) | 34 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) |
35 | goto drop; | 35 | goto drop; |
36 | 36 | ||
37 | do { | 37 | do { |
38 | struct ipv6hdr *iph = skb->nh.ipv6h; | 38 | struct ipv6hdr *iph = ipv6_hdr(skb); |
39 | 39 | ||
40 | if (xfrm_nr == XFRM_MAX_DEPTH) | 40 | if (xfrm_nr == XFRM_MAX_DEPTH) |
41 | goto drop; | 41 | goto drop; |
@@ -58,7 +58,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
58 | if (nexthdr <= 0) | 58 | if (nexthdr <= 0) |
59 | goto drop_unlock; | 59 | goto drop_unlock; |
60 | 60 | ||
61 | skb->nh.raw[nhoff] = nexthdr; | 61 | skb_network_header(skb)[nhoff] = nexthdr; |
62 | 62 | ||
63 | if (x->props.replay_window) | 63 | if (x->props.replay_window) |
64 | xfrm_replay_advance(x, seq); | 64 | xfrm_replay_advance(x, seq); |
@@ -112,8 +112,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) | |||
112 | return -1; | 112 | return -1; |
113 | } else { | 113 | } else { |
114 | #ifdef CONFIG_NETFILTER | 114 | #ifdef CONFIG_NETFILTER |
115 | skb->nh.ipv6h->payload_len = htons(skb->len); | 115 | ipv6_hdr(skb)->payload_len = htons(skb->len); |
116 | __skb_push(skb, skb->data - skb->nh.raw); | 116 | __skb_push(skb, skb->data - skb_network_header(skb)); |
117 | 117 | ||
118 | NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, | 118 | NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, |
119 | ip6_rcv_finish); | 119 | ip6_rcv_finish); |
@@ -140,19 +140,19 @@ int xfrm6_rcv(struct sk_buff **pskb) | |||
140 | return xfrm6_rcv_spi(*pskb, 0); | 140 | return xfrm6_rcv_spi(*pskb, 0); |
141 | } | 141 | } |
142 | 142 | ||
143 | EXPORT_SYMBOL(xfrm6_rcv); | ||
144 | |||
143 | int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | 145 | int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, |
144 | xfrm_address_t *saddr, u8 proto) | 146 | xfrm_address_t *saddr, u8 proto) |
145 | { | 147 | { |
146 | struct xfrm_state *x = NULL; | 148 | struct xfrm_state *x = NULL; |
147 | int wildcard = 0; | 149 | int wildcard = 0; |
148 | struct in6_addr any; | ||
149 | xfrm_address_t *xany; | 150 | xfrm_address_t *xany; |
150 | struct xfrm_state *xfrm_vec_one = NULL; | 151 | struct xfrm_state *xfrm_vec_one = NULL; |
151 | int nh = 0; | 152 | int nh = 0; |
152 | int i = 0; | 153 | int i = 0; |
153 | 154 | ||
154 | ipv6_addr_set(&any, 0, 0, 0, 0); | 155 | xany = (xfrm_address_t *)&in6addr_any; |
155 | xany = (xfrm_address_t *)&any; | ||
156 | 156 | ||
157 | for (i = 0; i < 3; i++) { | 157 | for (i = 0; i < 3; i++) { |
158 | xfrm_address_t *dst, *src; | 158 | xfrm_address_t *dst, *src; |
@@ -247,3 +247,5 @@ drop: | |||
247 | xfrm_state_put(xfrm_vec_one); | 247 | xfrm_state_put(xfrm_vec_one); |
248 | return -1; | 248 | return -1; |
249 | } | 249 | } |
250 | |||
251 | EXPORT_SYMBOL(xfrm6_input_addr); | ||
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index edcfffa9e87b..2e61d6ddece3 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -38,17 +38,18 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
38 | int hdr_len; | 38 | int hdr_len; |
39 | 39 | ||
40 | skb_push(skb, x->props.header_len); | 40 | skb_push(skb, x->props.header_len); |
41 | iph = skb->nh.ipv6h; | 41 | iph = ipv6_hdr(skb); |
42 | 42 | ||
43 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); | 43 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); |
44 | skb->nh.raw = prevhdr - x->props.header_len; | 44 | skb_set_network_header(skb, |
45 | skb->h.raw = skb->data + hdr_len; | 45 | (prevhdr - x->props.header_len) - skb->data); |
46 | skb_set_transport_header(skb, hdr_len); | ||
46 | memmove(skb->data, iph, hdr_len); | 47 | memmove(skb->data, iph, hdr_len); |
47 | 48 | ||
48 | skb->nh.raw = skb->data; | 49 | skb_reset_network_header(skb); |
49 | top_iph = skb->nh.ipv6h; | 50 | top_iph = ipv6_hdr(skb); |
50 | skb->nh.raw = &top_iph->nexthdr; | 51 | skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); |
51 | skb->h.ipv6h = top_iph + 1; | 52 | skb->network_header += offsetof(struct ipv6hdr, nexthdr); |
52 | 53 | ||
53 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | 54 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); |
54 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | 55 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); |
@@ -59,6 +60,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
59 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | 60 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) |
60 | { | 61 | { |
61 | struct ipv6hdr *ip6h; | 62 | struct ipv6hdr *ip6h; |
63 | const unsigned char *old_mac; | ||
62 | int size = sizeof(struct ipv6hdr); | 64 | int size = sizeof(struct ipv6hdr); |
63 | int err = -EINVAL; | 65 | int err = -EINVAL; |
64 | 66 | ||
@@ -66,13 +68,14 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
66 | goto out; | 68 | goto out; |
67 | 69 | ||
68 | skb_push(skb, size); | 70 | skb_push(skb, size); |
69 | memmove(skb->data, skb->nh.raw, size); | 71 | memmove(skb->data, skb_network_header(skb), size); |
70 | skb->nh.raw = skb->data; | 72 | skb_reset_network_header(skb); |
71 | 73 | ||
72 | skb->mac.raw = memmove(skb->data - skb->mac_len, | 74 | old_mac = skb_mac_header(skb); |
73 | skb->mac.raw, skb->mac_len); | 75 | skb_set_mac_header(skb, -skb->mac_len); |
76 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
74 | 77 | ||
75 | ip6h = skb->nh.ipv6h; | 78 | ip6h = ipv6_hdr(skb); |
76 | ip6h->payload_len = htons(skb->len - size); | 79 | ip6h->payload_len = htons(skb->len - size); |
77 | ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); | 80 | ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); |
78 | ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); | 81 | ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); |
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c index 6031c16d46ca..6ad6d7ac6bd7 100644 --- a/net/ipv6/xfrm6_mode_ro.c +++ b/net/ipv6/xfrm6_mode_ro.c | |||
@@ -50,11 +50,12 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) | |||
50 | int hdr_len; | 50 | int hdr_len; |
51 | 51 | ||
52 | skb_push(skb, x->props.header_len); | 52 | skb_push(skb, x->props.header_len); |
53 | iph = skb->nh.ipv6h; | 53 | iph = ipv6_hdr(skb); |
54 | 54 | ||
55 | hdr_len = x->type->hdr_offset(x, skb, &prevhdr); | 55 | hdr_len = x->type->hdr_offset(x, skb, &prevhdr); |
56 | skb->nh.raw = prevhdr - x->props.header_len; | 56 | skb_set_network_header(skb, |
57 | skb->h.raw = skb->data + hdr_len; | 57 | (prevhdr - x->props.header_len) - skb->data); |
58 | skb_set_transport_header(skb, hdr_len); | ||
58 | memmove(skb->data, iph, hdr_len); | 59 | memmove(skb->data, iph, hdr_len); |
59 | return 0; | 60 | return 0; |
60 | } | 61 | } |
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c index 3a4b39b12bad..c026bfea820a 100644 --- a/net/ipv6/xfrm6_mode_transport.c +++ b/net/ipv6/xfrm6_mode_transport.c | |||
@@ -32,11 +32,12 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) | |||
32 | int hdr_len; | 32 | int hdr_len; |
33 | 33 | ||
34 | skb_push(skb, x->props.header_len); | 34 | skb_push(skb, x->props.header_len); |
35 | iph = skb->nh.ipv6h; | 35 | iph = ipv6_hdr(skb); |
36 | 36 | ||
37 | hdr_len = x->type->hdr_offset(x, skb, &prevhdr); | 37 | hdr_len = x->type->hdr_offset(x, skb, &prevhdr); |
38 | skb->nh.raw = prevhdr - x->props.header_len; | 38 | skb_set_network_header(skb, |
39 | skb->h.raw = skb->data + hdr_len; | 39 | (prevhdr - x->props.header_len) - skb->data); |
40 | skb_set_transport_header(skb, hdr_len); | ||
40 | memmove(skb->data, iph, hdr_len); | 41 | memmove(skb->data, iph, hdr_len); |
41 | return 0; | 42 | return 0; |
42 | } | 43 | } |
@@ -51,13 +52,16 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) | |||
51 | */ | 52 | */ |
52 | static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) | 53 | static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) |
53 | { | 54 | { |
54 | int ihl = skb->data - skb->h.raw; | 55 | int ihl = skb->data - skb_transport_header(skb); |
55 | 56 | ||
56 | if (skb->h.raw != skb->nh.raw) | 57 | if (skb->transport_header != skb->network_header) { |
57 | skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl); | 58 | memmove(skb_transport_header(skb), |
58 | skb->nh.ipv6h->payload_len = htons(skb->len + ihl - | 59 | skb_network_header(skb), ihl); |
60 | skb->network_header = skb->transport_header; | ||
61 | } | ||
62 | ipv6_hdr(skb)->payload_len = htons(skb->len + ihl - | ||
59 | sizeof(struct ipv6hdr)); | 63 | sizeof(struct ipv6hdr)); |
60 | skb->h.raw = skb->data; | 64 | skb_reset_transport_header(skb); |
61 | return 0; | 65 | return 0; |
62 | } | 66 | } |
63 | 67 | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 0bc866c0d83c..a6c0cdf46ad6 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -18,8 +18,8 @@ | |||
18 | 18 | ||
19 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | 19 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) |
20 | { | 20 | { |
21 | struct ipv6hdr *outer_iph = skb->nh.ipv6h; | 21 | struct ipv6hdr *outer_iph = ipv6_hdr(skb); |
22 | struct ipv6hdr *inner_iph = skb->h.ipv6h; | 22 | struct ipv6hdr *inner_iph = ipipv6_hdr(skb); |
23 | 23 | ||
24 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | 24 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) |
25 | IP6_ECN_set_ce(inner_iph); | 25 | IP6_ECN_set_ce(inner_iph); |
@@ -27,8 +27,8 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | |||
27 | 27 | ||
28 | static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb) | 28 | static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb) |
29 | { | 29 | { |
30 | if (INET_ECN_is_ce(ipv6_get_dsfield(skb->nh.ipv6h))) | 30 | if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6_hdr(skb)))) |
31 | IP_ECN_set_ce(skb->h.ipiph); | 31 | IP_ECN_set_ce(ipip_hdr(skb)); |
32 | } | 32 | } |
33 | 33 | ||
34 | /* Add encapsulation header. | 34 | /* Add encapsulation header. |
@@ -51,12 +51,12 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
51 | int dsfield; | 51 | int dsfield; |
52 | 52 | ||
53 | skb_push(skb, x->props.header_len); | 53 | skb_push(skb, x->props.header_len); |
54 | iph = skb->nh.ipv6h; | 54 | iph = ipv6_hdr(skb); |
55 | 55 | ||
56 | skb->nh.raw = skb->data; | 56 | skb_reset_network_header(skb); |
57 | top_iph = skb->nh.ipv6h; | 57 | top_iph = ipv6_hdr(skb); |
58 | skb->nh.raw = &top_iph->nexthdr; | 58 | skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); |
59 | skb->h.ipv6h = top_iph + 1; | 59 | skb->network_header += offsetof(struct ipv6hdr, nexthdr); |
60 | 60 | ||
61 | top_iph->version = 6; | 61 | top_iph->version = 6; |
62 | if (xdst->route->ops->family == AF_INET6) { | 62 | if (xdst->route->ops->family == AF_INET6) { |
@@ -86,9 +86,11 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
86 | static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 86 | static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
87 | { | 87 | { |
88 | int err = -EINVAL; | 88 | int err = -EINVAL; |
89 | const unsigned char *old_mac; | ||
90 | const unsigned char *nh = skb_network_header(skb); | ||
89 | 91 | ||
90 | if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6 | 92 | if (nh[IP6CB(skb)->nhoff] != IPPROTO_IPV6 && |
91 | && skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPIP) | 93 | nh[IP6CB(skb)->nhoff] != IPPROTO_IPIP) |
92 | goto out; | 94 | goto out; |
93 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 95 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
94 | goto out; | 96 | goto out; |
@@ -97,9 +99,10 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
97 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 99 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
98 | goto out; | 100 | goto out; |
99 | 101 | ||
100 | if (skb->nh.raw[IP6CB(skb)->nhoff] == IPPROTO_IPV6) { | 102 | nh = skb_network_header(skb); |
103 | if (nh[IP6CB(skb)->nhoff] == IPPROTO_IPV6) { | ||
101 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | 104 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
102 | ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h); | 105 | ipv6_copy_dscp(ipv6_hdr(skb), ipipv6_hdr(skb)); |
103 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 106 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
104 | ipip6_ecn_decapsulate(skb); | 107 | ipip6_ecn_decapsulate(skb); |
105 | } else { | 108 | } else { |
@@ -107,9 +110,10 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
107 | ip6ip_ecn_decapsulate(skb); | 110 | ip6ip_ecn_decapsulate(skb); |
108 | skb->protocol = htons(ETH_P_IP); | 111 | skb->protocol = htons(ETH_P_IP); |
109 | } | 112 | } |
110 | skb->mac.raw = memmove(skb->data - skb->mac_len, | 113 | old_mac = skb_mac_header(skb); |
111 | skb->mac.raw, skb->mac_len); | 114 | skb_set_mac_header(skb, -skb->mac_len); |
112 | skb->nh.raw = skb->data; | 115 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); |
116 | skb_reset_network_header(skb); | ||
113 | err = 0; | 117 | err = 0; |
114 | 118 | ||
115 | out: | 119 | out: |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index d6d786b89d2b..56364a5f676a 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -23,6 +23,8 @@ int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, | |||
23 | return ip6_find_1stfragopt(skb, prevhdr); | 23 | return ip6_find_1stfragopt(skb, prevhdr); |
24 | } | 24 | } |
25 | 25 | ||
26 | EXPORT_SYMBOL(xfrm6_find_1stfragopt); | ||
27 | |||
26 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) | 28 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) |
27 | { | 29 | { |
28 | int mtu, ret = 0; | 30 | int mtu, ret = 0; |
@@ -76,11 +78,11 @@ static int xfrm6_output_one(struct sk_buff *skb) | |||
76 | x->curlft.bytes += skb->len; | 78 | x->curlft.bytes += skb->len; |
77 | x->curlft.packets++; | 79 | x->curlft.packets++; |
78 | if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) | 80 | if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) |
79 | x->lastused = (u64)xtime.tv_sec; | 81 | x->lastused = get_seconds(); |
80 | 82 | ||
81 | spin_unlock_bh(&x->lock); | 83 | spin_unlock_bh(&x->lock); |
82 | 84 | ||
83 | skb->nh.raw = skb->data; | 85 | skb_reset_network_header(skb); |
84 | 86 | ||
85 | if (!(skb->dst = dst_pop(dst))) { | 87 | if (!(skb->dst = dst_pop(dst))) { |
86 | err = -EHOSTUNREACH; | 88 | err = -EHOSTUNREACH; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index d8a585bd2cb4..1faa2ea80afc 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -240,7 +240,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int | |||
240 | if (!afinfo) { | 240 | if (!afinfo) { |
241 | dst = *dst_p; | 241 | dst = *dst_p; |
242 | goto error; | 242 | goto error; |
243 | }; | 243 | } |
244 | |||
244 | dst_prev->output = afinfo->output; | 245 | dst_prev->output = afinfo->output; |
245 | xfrm_state_put_afinfo(afinfo); | 246 | xfrm_state_put_afinfo(afinfo); |
246 | /* Sheit... I remember I did this right. Apparently, | 247 | /* Sheit... I remember I did this right. Apparently, |
@@ -270,17 +271,19 @@ error: | |||
270 | static inline void | 271 | static inline void |
271 | _decode_session6(struct sk_buff *skb, struct flowi *fl) | 272 | _decode_session6(struct sk_buff *skb, struct flowi *fl) |
272 | { | 273 | { |
273 | u16 offset = skb->h.raw - skb->nh.raw; | 274 | u16 offset = skb_network_header_len(skb); |
274 | struct ipv6hdr *hdr = skb->nh.ipv6h; | 275 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
275 | struct ipv6_opt_hdr *exthdr; | 276 | struct ipv6_opt_hdr *exthdr; |
276 | u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff]; | 277 | const unsigned char *nh = skb_network_header(skb); |
278 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | ||
277 | 279 | ||
278 | memset(fl, 0, sizeof(struct flowi)); | 280 | memset(fl, 0, sizeof(struct flowi)); |
279 | ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); | 281 | ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); |
280 | ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); | 282 | ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); |
281 | 283 | ||
282 | while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { | 284 | while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { |
283 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 285 | nh = skb_network_header(skb); |
286 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); | ||
284 | 287 | ||
285 | switch (nexthdr) { | 288 | switch (nexthdr) { |
286 | case NEXTHDR_ROUTING: | 289 | case NEXTHDR_ROUTING: |
@@ -288,7 +291,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
288 | case NEXTHDR_DEST: | 291 | case NEXTHDR_DEST: |
289 | offset += ipv6_optlen(exthdr); | 292 | offset += ipv6_optlen(exthdr); |
290 | nexthdr = exthdr->nexthdr; | 293 | nexthdr = exthdr->nexthdr; |
291 | exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); | 294 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
292 | break; | 295 | break; |
293 | 296 | ||
294 | case IPPROTO_UDP: | 297 | case IPPROTO_UDP: |
@@ -296,7 +299,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
296 | case IPPROTO_TCP: | 299 | case IPPROTO_TCP: |
297 | case IPPROTO_SCTP: | 300 | case IPPROTO_SCTP: |
298 | case IPPROTO_DCCP: | 301 | case IPPROTO_DCCP: |
299 | if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { | 302 | if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) { |
300 | __be16 *ports = (__be16 *)exthdr; | 303 | __be16 *ports = (__be16 *)exthdr; |
301 | 304 | ||
302 | fl->fl_ip_sport = ports[0]; | 305 | fl->fl_ip_sport = ports[0]; |
@@ -306,7 +309,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
306 | return; | 309 | return; |
307 | 310 | ||
308 | case IPPROTO_ICMPV6: | 311 | case IPPROTO_ICMPV6: |
309 | if (pskb_may_pull(skb, skb->nh.raw + offset + 2 - skb->data)) { | 312 | if (pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
310 | u8 *icmp = (u8 *)exthdr; | 313 | u8 *icmp = (u8 *)exthdr; |
311 | 314 | ||
312 | fl->fl_icmp_type = icmp[0]; | 315 | fl->fl_icmp_type = icmp[0]; |
@@ -317,7 +320,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
317 | 320 | ||
318 | #ifdef CONFIG_IPV6_MIP6 | 321 | #ifdef CONFIG_IPV6_MIP6 |
319 | case IPPROTO_MH: | 322 | case IPPROTO_MH: |
320 | if (pskb_may_pull(skb, skb->nh.raw + offset + 3 - skb->data)) { | 323 | if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
321 | struct ip6_mh *mh; | 324 | struct ip6_mh *mh; |
322 | mh = (struct ip6_mh *)exthdr; | 325 | mh = (struct ip6_mh *)exthdr; |
323 | 326 | ||
@@ -335,7 +338,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
335 | fl->fl_ipsec_spi = 0; | 338 | fl->fl_ipsec_spi = 0; |
336 | fl->proto = nexthdr; | 339 | fl->proto = nexthdr; |
337 | return; | 340 | return; |
338 | }; | 341 | } |
339 | } | 342 | } |
340 | } | 343 | } |
341 | 344 | ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 93c42232aa39..538499a89975 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -257,7 +257,7 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
257 | 257 | ||
258 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) | 258 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) |
259 | { | 259 | { |
260 | struct ipv6hdr *iph = skb->nh.ipv6h; | 260 | struct ipv6hdr *iph = ipv6_hdr(skb); |
261 | __be32 spi; | 261 | __be32 spi; |
262 | 262 | ||
263 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); | 263 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); |