diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:55:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:55:56 -0400 |
commit | d0b952a9837f81cd89e756b1b34293fa6e1cb59d (patch) | |
tree | fbe488bc5f407afa0e91cefb262d9e9ee69062ac /net/ipv6 | |
parent | d90125bfe958ed0451c6b98f831c86aba08b43d5 (diff) | |
parent | 47552c4e555eefe381f3d45140b59a2ea4b16486 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (109 commits)
[ETHTOOL]: Fix UFO typo
[SCTP]: Fix persistent slowdown in sctp when a gap ack consumes rx buffer.
[SCTP]: Send only 1 window update SACK per message.
[SCTP]: Don't do CRC32C checksum over loopback.
[SCTP] Reset rtt_in_progress for the chunk when processing its sack.
[SCTP]: Reject sctp packets with broadcast addresses.
[SCTP]: Limit association max_retrans setting in setsockopt.
[PFKEYV2]: Fix inconsistent typing in struct sadb_x_kmprivate.
[IPV6]: Sum real space for RTAs.
[IRDA]: Use put_unaligned() in irlmp_do_discovery().
[BRIDGE]: Add support for NETIF_F_HW_CSUM devices
[NET]: Add NETIF_F_GEN_CSUM and NETIF_F_ALL_CSUM
[TG3]: Convert to non-LLTX
[TG3]: Remove unnecessary tx_lock
[TCP]: Add tcp_slow_start_after_idle sysctl.
[BNX2]: Update version and reldate
[BNX2]: Use CPU native page size
[BNX2]: Use compressed firmware
[BNX2]: Add firmware decompression
[BNX2]: Allow WoL settings on new 5708 chips
...
Manual fixup for conflict in drivers/net/tulip/winbond-840.c
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/Kconfig | 20 | ||||
-rw-r--r-- | net/ipv6/Makefile | 2 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 28 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 10 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 20 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 3 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 38 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 10 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 | ||||
-rw-r--r-- | net/ipv6/xfrm6_input.c | 29 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_transport.c | 88 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 121 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 63 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 1 |
17 files changed, 294 insertions, 161 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index f8a107ab559..e923d4dea41 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -106,6 +106,26 @@ config INET6_TUNNEL | |||
106 | tristate | 106 | tristate |
107 | default n | 107 | default n |
108 | 108 | ||
109 | config INET6_XFRM_MODE_TRANSPORT | ||
110 | tristate "IPv6: IPsec transport mode" | ||
111 | depends on IPV6 | ||
112 | default IPV6 | ||
113 | select XFRM | ||
114 | ---help--- | ||
115 | Support for IPsec transport mode. | ||
116 | |||
117 | If unsure, say Y. | ||
118 | |||
119 | config INET6_XFRM_MODE_TUNNEL | ||
120 | tristate "IPv6: IPsec tunnel mode" | ||
121 | depends on IPV6 | ||
122 | default IPV6 | ||
123 | select XFRM | ||
124 | ---help--- | ||
125 | Support for IPsec tunnel mode. | ||
126 | |||
127 | If unsure, say Y. | ||
128 | |||
109 | config IPV6_TUNNEL | 129 | config IPV6_TUNNEL |
110 | tristate "IPv6: IPv6-in-IPv6 tunnel" | 130 | tristate "IPv6: IPv6-in-IPv6 tunnel" |
111 | select INET6_TUNNEL | 131 | select INET6_TUNNEL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index a760b0988fb..386e0a62694 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -20,6 +20,8 @@ obj-$(CONFIG_INET6_ESP) += esp6.o | |||
20 | obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o | 20 | obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o |
21 | obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o | 21 | obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o |
22 | obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o | 22 | obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o |
23 | obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o | ||
24 | obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | ||
23 | obj-$(CONFIG_NETFILTER) += netfilter/ | 25 | obj-$(CONFIG_NETFILTER) += netfilter/ |
24 | 26 | ||
25 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 27 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 445006ee452..c2c26fa0943 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2860,6 +2860,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
2860 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); | 2860 | return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); |
2861 | } | 2861 | } |
2862 | 2862 | ||
2863 | /* Maximum length of ifa_cacheinfo attributes */ | ||
2864 | #define INET6_IFADDR_RTA_SPACE \ | ||
2865 | RTA_SPACE(16) /* IFA_ADDRESS */ + \ | ||
2866 | RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */ | ||
2867 | |||
2863 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 2868 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, |
2864 | u32 pid, u32 seq, int event, unsigned int flags) | 2869 | u32 pid, u32 seq, int event, unsigned int flags) |
2865 | { | 2870 | { |
@@ -3092,7 +3097,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
3092 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | 3097 | static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) |
3093 | { | 3098 | { |
3094 | struct sk_buff *skb; | 3099 | struct sk_buff *skb; |
3095 | int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128); | 3100 | int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); |
3096 | 3101 | ||
3097 | skb = alloc_skb(size, GFP_ATOMIC); | 3102 | skb = alloc_skb(size, GFP_ATOMIC); |
3098 | if (!skb) { | 3103 | if (!skb) { |
@@ -3142,6 +3147,17 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3142 | #endif | 3147 | #endif |
3143 | } | 3148 | } |
3144 | 3149 | ||
3150 | /* Maximum length of ifinfomsg attributes */ | ||
3151 | #define INET6_IFINFO_RTA_SPACE \ | ||
3152 | RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ | ||
3153 | RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ | ||
3154 | RTA_SPACE(sizeof(u32)) /* MTU */ + \ | ||
3155 | RTA_SPACE(sizeof(int)) /* LINK */ + \ | ||
3156 | RTA_SPACE(0) /* PROTINFO */ + \ | ||
3157 | RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ | ||
3158 | RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ | ||
3159 | RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ | ||
3160 | |||
3145 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3161 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
3146 | u32 pid, u32 seq, int event, unsigned int flags) | 3162 | u32 pid, u32 seq, int event, unsigned int flags) |
3147 | { | 3163 | { |
@@ -3235,8 +3251,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
3235 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3251 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) |
3236 | { | 3252 | { |
3237 | struct sk_buff *skb; | 3253 | struct sk_buff *skb; |
3238 | /* 128 bytes ?? */ | 3254 | int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE); |
3239 | int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128); | ||
3240 | 3255 | ||
3241 | skb = alloc_skb(size, GFP_ATOMIC); | 3256 | skb = alloc_skb(size, GFP_ATOMIC); |
3242 | if (!skb) { | 3257 | if (!skb) { |
@@ -3252,6 +3267,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3252 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); | 3267 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); |
3253 | } | 3268 | } |
3254 | 3269 | ||
3270 | /* Maximum length of prefix_cacheinfo attributes */ | ||
3271 | #define INET6_PREFIX_RTA_SPACE \ | ||
3272 | RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ | ||
3273 | RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ | ||
3274 | |||
3255 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | 3275 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, |
3256 | struct prefix_info *pinfo, u32 pid, u32 seq, | 3276 | struct prefix_info *pinfo, u32 pid, u32 seq, |
3257 | int event, unsigned int flags) | 3277 | int event, unsigned int flags) |
@@ -3296,7 +3316,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3296 | struct prefix_info *pinfo) | 3316 | struct prefix_info *pinfo) |
3297 | { | 3317 | { |
3298 | struct sk_buff *skb; | 3318 | struct sk_buff *skb; |
3299 | int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128); | 3319 | int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE); |
3300 | 3320 | ||
3301 | skb = alloc_skb(size, GFP_ATOMIC); | 3321 | skb = alloc_skb(size, GFP_ATOMIC); |
3302 | if (!skb) { | 3322 | if (!skb) { |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 6778173a3dd..d31c0d6c044 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -292,7 +292,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
292 | 292 | ||
293 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 293 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
294 | memset(ah->auth_data, 0, ahp->icv_trunc_len); | 294 | memset(ah->auth_data, 0, ahp->icv_trunc_len); |
295 | skb_push(skb, skb->data - skb->nh.raw); | 295 | skb_push(skb, hdr_len); |
296 | ahp->icv(ahp, skb, ah->auth_data); | 296 | ahp->icv(ahp, skb, ah->auth_data); |
297 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { | 297 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { |
298 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); | 298 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); |
@@ -301,12 +301,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
301 | } | 301 | } |
302 | } | 302 | } |
303 | 303 | ||
304 | skb->nh.raw = skb_pull(skb, ah_hlen); | 304 | skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len); |
305 | memcpy(skb->nh.raw, tmp_hdr, hdr_len); | 305 | __skb_pull(skb, ah_hlen + hdr_len); |
306 | skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | ||
307 | skb_pull(skb, hdr_len); | ||
308 | skb->h.raw = skb->data; | ||
309 | |||
310 | 306 | ||
311 | kfree(tmp_hdr); | 307 | kfree(tmp_hdr); |
312 | 308 | ||
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 22f04607903..a15a6f320f7 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -142,25 +142,17 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
142 | 142 | ||
143 | int hdr_len = skb->h.raw - skb->nh.raw; | 143 | int hdr_len = skb->h.raw - skb->nh.raw; |
144 | int nfrags; | 144 | int nfrags; |
145 | unsigned char *tmp_hdr = NULL; | ||
146 | int ret = 0; | 145 | int ret = 0; |
147 | 146 | ||
148 | if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) { | 147 | if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) { |
149 | ret = -EINVAL; | 148 | ret = -EINVAL; |
150 | goto out_nofree; | 149 | goto out; |
151 | } | 150 | } |
152 | 151 | ||
153 | if (elen <= 0 || (elen & (blksize-1))) { | 152 | if (elen <= 0 || (elen & (blksize-1))) { |
154 | ret = -EINVAL; | 153 | ret = -EINVAL; |
155 | goto out_nofree; | 154 | goto out; |
156 | } | ||
157 | |||
158 | tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); | ||
159 | if (!tmp_hdr) { | ||
160 | ret = -ENOMEM; | ||
161 | goto out_nofree; | ||
162 | } | 155 | } |
163 | memcpy(tmp_hdr, skb->nh.raw, hdr_len); | ||
164 | 156 | ||
165 | /* If integrity check is required, do this. */ | 157 | /* If integrity check is required, do this. */ |
166 | if (esp->auth.icv_full_len) { | 158 | if (esp->auth.icv_full_len) { |
@@ -222,16 +214,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
222 | /* ... check padding bits here. Silly. :-) */ | 214 | /* ... check padding bits here. Silly. :-) */ |
223 | 215 | ||
224 | pskb_trim(skb, skb->len - alen - padlen - 2); | 216 | pskb_trim(skb, skb->len - alen - padlen - 2); |
225 | skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen); | ||
226 | skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; | ||
227 | memcpy(skb->nh.raw, tmp_hdr, hdr_len); | ||
228 | skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | ||
229 | ret = nexthdr[1]; | 217 | ret = nexthdr[1]; |
230 | } | 218 | } |
231 | 219 | ||
220 | skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len; | ||
221 | |||
232 | out: | 222 | out: |
233 | kfree(tmp_hdr); | ||
234 | out_nofree: | ||
235 | return ret; | 223 | return ret; |
236 | } | 224 | } |
237 | 225 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index e46048974f3..d29620f4910 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/in6.h> | 39 | #include <linux/in6.h> |
40 | #include <linux/tcp.h> | 40 | #include <linux/tcp.h> |
41 | #include <linux/route.h> | 41 | #include <linux/route.h> |
42 | #include <linux/module.h> | ||
42 | 43 | ||
43 | #include <linux/netfilter.h> | 44 | #include <linux/netfilter.h> |
44 | #include <linux/netfilter_ipv6.h> | 45 | #include <linux/netfilter_ipv6.h> |
@@ -458,6 +459,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
458 | nf_bridge_get(to->nf_bridge); | 459 | nf_bridge_get(to->nf_bridge); |
459 | #endif | 460 | #endif |
460 | #endif | 461 | #endif |
462 | skb_copy_secmark(to, from); | ||
461 | } | 463 | } |
462 | 464 | ||
463 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 465 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
@@ -488,6 +490,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | |||
488 | 490 | ||
489 | return offset; | 491 | return offset; |
490 | } | 492 | } |
493 | EXPORT_SYMBOL_GPL(ip6_find_1stfragopt); | ||
491 | 494 | ||
492 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 495 | static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) |
493 | { | 496 | { |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 48636436028..f28cd37feed 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -65,38 +65,25 @@ static LIST_HEAD(ipcomp6_tfms_list); | |||
65 | 65 | ||
66 | static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) | 66 | static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) |
67 | { | 67 | { |
68 | int err = 0; | 68 | int err = -ENOMEM; |
69 | u8 nexthdr = 0; | ||
70 | int hdr_len = skb->h.raw - skb->nh.raw; | ||
71 | unsigned char *tmp_hdr = NULL; | ||
72 | struct ipv6hdr *iph; | 69 | struct ipv6hdr *iph; |
70 | struct ipv6_comp_hdr *ipch; | ||
73 | int plen, dlen; | 71 | int plen, dlen; |
74 | struct ipcomp_data *ipcd = x->data; | 72 | struct ipcomp_data *ipcd = x->data; |
75 | u8 *start, *scratch; | 73 | u8 *start, *scratch; |
76 | struct crypto_tfm *tfm; | 74 | struct crypto_tfm *tfm; |
77 | int cpu; | 75 | int cpu; |
78 | 76 | ||
79 | if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && | 77 | if (skb_linearize_cow(skb)) |
80 | skb_linearize(skb, GFP_ATOMIC) != 0) { | ||
81 | err = -ENOMEM; | ||
82 | goto out; | 78 | goto out; |
83 | } | ||
84 | 79 | ||
85 | skb->ip_summed = CHECKSUM_NONE; | 80 | skb->ip_summed = CHECKSUM_NONE; |
86 | 81 | ||
87 | /* Remove ipcomp header and decompress original payload */ | 82 | /* Remove ipcomp header and decompress original payload */ |
88 | iph = skb->nh.ipv6h; | 83 | iph = skb->nh.ipv6h; |
89 | tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); | 84 | ipch = (void *)skb->data; |
90 | if (!tmp_hdr) | 85 | skb->h.raw = skb->nh.raw + sizeof(*ipch); |
91 | goto out; | 86 | __skb_pull(skb, sizeof(*ipch)); |
92 | memcpy(tmp_hdr, iph, hdr_len); | ||
93 | nexthdr = *(u8 *)skb->data; | ||
94 | skb_pull(skb, sizeof(struct ipv6_comp_hdr)); | ||
95 | skb->nh.raw += sizeof(struct ipv6_comp_hdr); | ||
96 | memcpy(skb->nh.raw, tmp_hdr, hdr_len); | ||
97 | iph = skb->nh.ipv6h; | ||
98 | iph->payload_len = htons(ntohs(iph->payload_len) - sizeof(struct ipv6_comp_hdr)); | ||
99 | skb->h.raw = skb->data; | ||
100 | 87 | ||
101 | /* decompression */ | 88 | /* decompression */ |
102 | plen = skb->len; | 89 | plen = skb->len; |
@@ -125,18 +112,11 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
125 | 112 | ||
126 | skb_put(skb, dlen - plen); | 113 | skb_put(skb, dlen - plen); |
127 | memcpy(skb->data, scratch, dlen); | 114 | memcpy(skb->data, scratch, dlen); |
115 | err = ipch->nexthdr; | ||
128 | 116 | ||
129 | iph = skb->nh.ipv6h; | ||
130 | iph->payload_len = htons(skb->len); | ||
131 | |||
132 | out_put_cpu: | 117 | out_put_cpu: |
133 | put_cpu(); | 118 | put_cpu(); |
134 | out: | 119 | out: |
135 | kfree(tmp_hdr); | ||
136 | if (err) | ||
137 | goto error_out; | ||
138 | return nexthdr; | ||
139 | error_out: | ||
140 | return err; | 120 | return err; |
141 | } | 121 | } |
142 | 122 | ||
@@ -159,10 +139,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
159 | goto out_ok; | 139 | goto out_ok; |
160 | } | 140 | } |
161 | 141 | ||
162 | if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && | 142 | if (skb_linearize_cow(skb)) |
163 | skb_linearize(skb, GFP_ATOMIC) != 0) { | ||
164 | goto out_ok; | 143 | goto out_ok; |
165 | } | ||
166 | 144 | ||
167 | /* compression */ | 145 | /* compression */ |
168 | plen = skb->len - hdr_len; | 146 | plen = skb->len - hdr_len; |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 93bae36f266..2a71c3b669f 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -189,7 +189,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
189 | 189 | ||
190 | /* This is where we call the helper: as the packet goes out. */ | 190 | /* This is where we call the helper: as the packet goes out. */ |
191 | ct = nf_ct_get(*pskb, &ctinfo); | 191 | ct = nf_ct_get(*pskb, &ctinfo); |
192 | if (!ct) | 192 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) |
193 | goto out; | 193 | goto out; |
194 | 194 | ||
195 | help = nfct_help(ct); | 195 | help = nfct_help(ct); |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 86c6703265d..ef18a7b7014 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -233,7 +233,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, | |||
233 | return -NF_ACCEPT; | 233 | return -NF_ACCEPT; |
234 | } | 234 | } |
235 | 235 | ||
236 | if (hooknum == NF_IP6_PRE_ROUTING && | 236 | if (nf_conntrack_checksum && hooknum == NF_IP6_PRE_ROUTING && |
237 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { | 237 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { |
238 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 238 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, |
239 | "nf_ct_icmpv6: ICMPv6 checksum failed\n"); | 239 | "nf_ct_icmpv6: ICMPv6 checksum failed\n"); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 3e319035f82..c32a029e43f 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -456,13 +456,9 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
456 | DEBUGP("queue: message is too short.\n"); | 456 | DEBUGP("queue: message is too short.\n"); |
457 | goto err; | 457 | goto err; |
458 | } | 458 | } |
459 | if (end-offset < skb->len) { | 459 | if (pskb_trim_rcsum(skb, end - offset)) { |
460 | if (pskb_trim(skb, end - offset)) { | 460 | DEBUGP("Can't trim\n"); |
461 | DEBUGP("Can't trim\n"); | 461 | goto err; |
462 | goto err; | ||
463 | } | ||
464 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
465 | skb->ip_summed = CHECKSUM_NONE; | ||
466 | } | 462 | } |
467 | 463 | ||
468 | /* Find out which fragments are in front and at the back of us | 464 | /* Find out which fragments are in front and at the back of us |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 301eee726b0..a50eb306e9e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1218,8 +1218,16 @@ process: | |||
1218 | bh_lock_sock(sk); | 1218 | bh_lock_sock(sk); |
1219 | ret = 0; | 1219 | ret = 0; |
1220 | if (!sock_owned_by_user(sk)) { | 1220 | if (!sock_owned_by_user(sk)) { |
1221 | if (!tcp_prequeue(sk, skb)) | 1221 | #ifdef CONFIG_NET_DMA |
1222 | ret = tcp_v6_do_rcv(sk, skb); | 1222 | struct tcp_sock *tp = tcp_sk(sk); |
1223 | if (tp->ucopy.dma_chan) | ||
1224 | ret = tcp_v6_do_rcv(sk, skb); | ||
1225 | else | ||
1226 | #endif | ||
1227 | { | ||
1228 | if (!tcp_prequeue(sk, skb)) | ||
1229 | ret = tcp_v6_do_rcv(sk, skb); | ||
1230 | } | ||
1223 | } else | 1231 | } else |
1224 | sk_add_backlog(sk, skb); | 1232 | sk_add_backlog(sk, skb); |
1225 | bh_unlock_sock(sk); | 1233 | bh_unlock_sock(sk); |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 00cfdee18dc..0405d74ff91 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -13,21 +13,9 @@ | |||
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/netfilter.h> | 14 | #include <linux/netfilter.h> |
15 | #include <linux/netfilter_ipv6.h> | 15 | #include <linux/netfilter_ipv6.h> |
16 | #include <net/dsfield.h> | ||
17 | #include <net/inet_ecn.h> | ||
18 | #include <net/ip.h> | ||
19 | #include <net/ipv6.h> | 16 | #include <net/ipv6.h> |
20 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
21 | 18 | ||
22 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | ||
23 | { | ||
24 | struct ipv6hdr *outer_iph = skb->nh.ipv6h; | ||
25 | struct ipv6hdr *inner_iph = skb->h.ipv6h; | ||
26 | |||
27 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | ||
28 | IP6_ECN_set_ce(inner_iph); | ||
29 | } | ||
30 | |||
31 | int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) | 19 | int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) |
32 | { | 20 | { |
33 | int err; | 21 | int err; |
@@ -81,21 +69,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) | |||
81 | 69 | ||
82 | xfrm_vec[xfrm_nr++] = x; | 70 | xfrm_vec[xfrm_nr++] = x; |
83 | 71 | ||
72 | if (x->mode->input(x, skb)) | ||
73 | goto drop; | ||
74 | |||
84 | if (x->props.mode) { /* XXX */ | 75 | if (x->props.mode) { /* XXX */ |
85 | if (nexthdr != IPPROTO_IPV6) | ||
86 | goto drop; | ||
87 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
88 | goto drop; | ||
89 | if (skb_cloned(skb) && | ||
90 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | ||
91 | goto drop; | ||
92 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | ||
93 | ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h); | ||
94 | if (!(x->props.flags & XFRM_STATE_NOECN)) | ||
95 | ipip6_ecn_decapsulate(skb); | ||
96 | skb->mac.raw = memmove(skb->data - skb->mac_len, | ||
97 | skb->mac.raw, skb->mac_len); | ||
98 | skb->nh.raw = skb->data; | ||
99 | decaps = 1; | 76 | decaps = 1; |
100 | break; | 77 | break; |
101 | } | 78 | } |
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c new file mode 100644 index 00000000000..711d713e36d --- /dev/null +++ b/net/ipv6/xfrm6_mode_transport.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6. | ||
3 | * | ||
4 | * Copyright (C) 2002 USAGI/WIDE Project | ||
5 | * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/stringify.h> | ||
13 | #include <net/dst.h> | ||
14 | #include <net/ipv6.h> | ||
15 | #include <net/xfrm.h> | ||
16 | |||
17 | /* Add encapsulation header. | ||
18 | * | ||
19 | * The IP header and mutable extension headers will be moved forward to make | ||
20 | * space for the encapsulation header. | ||
21 | * | ||
22 | * On exit, skb->h will be set to the start of the encapsulation header to be | ||
23 | * filled in by x->type->output and skb->nh will be set to the nextheader field | ||
24 | * of the extension header directly preceding the encapsulation header, or in | ||
25 | * its absence, that of the top IP header. The value of skb->data will always | ||
26 | * point to the top IP header. | ||
27 | */ | ||
28 | static int xfrm6_transport_output(struct sk_buff *skb) | ||
29 | { | ||
30 | struct xfrm_state *x = skb->dst->xfrm; | ||
31 | struct ipv6hdr *iph; | ||
32 | u8 *prevhdr; | ||
33 | int hdr_len; | ||
34 | |||
35 | skb_push(skb, x->props.header_len); | ||
36 | iph = skb->nh.ipv6h; | ||
37 | |||
38 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); | ||
39 | skb->nh.raw = prevhdr - x->props.header_len; | ||
40 | skb->h.raw = skb->data + hdr_len; | ||
41 | memmove(skb->data, iph, hdr_len); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | /* Remove encapsulation header. | ||
46 | * | ||
47 | * The IP header will be moved over the top of the encapsulation header. | ||
48 | * | ||
49 | * On entry, skb->h shall point to where the IP header should be and skb->nh | ||
50 | * shall be set to where the IP header currently is. skb->data shall point | ||
51 | * to the start of the payload. | ||
52 | */ | ||
53 | static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) | ||
54 | { | ||
55 | int ihl = skb->data - skb->h.raw; | ||
56 | |||
57 | if (skb->h.raw != skb->nh.raw) | ||
58 | skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl); | ||
59 | skb->nh.ipv6h->payload_len = htons(skb->len + ihl - | ||
60 | sizeof(struct ipv6hdr)); | ||
61 | skb->h.raw = skb->data; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static struct xfrm_mode xfrm6_transport_mode = { | ||
66 | .input = xfrm6_transport_input, | ||
67 | .output = xfrm6_transport_output, | ||
68 | .owner = THIS_MODULE, | ||
69 | .encap = XFRM_MODE_TRANSPORT, | ||
70 | }; | ||
71 | |||
72 | static int __init xfrm6_transport_init(void) | ||
73 | { | ||
74 | return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6); | ||
75 | } | ||
76 | |||
77 | static void __exit xfrm6_transport_exit(void) | ||
78 | { | ||
79 | int err; | ||
80 | |||
81 | err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6); | ||
82 | BUG_ON(err); | ||
83 | } | ||
84 | |||
85 | module_init(xfrm6_transport_init); | ||
86 | module_exit(xfrm6_transport_exit); | ||
87 | MODULE_LICENSE("GPL"); | ||
88 | MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT); | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c new file mode 100644 index 00000000000..8af79be2edc --- /dev/null +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6. | ||
3 | * | ||
4 | * Copyright (C) 2002 USAGI/WIDE Project | ||
5 | * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/stringify.h> | ||
13 | #include <net/dsfield.h> | ||
14 | #include <net/dst.h> | ||
15 | #include <net/inet_ecn.h> | ||
16 | #include <net/ipv6.h> | ||
17 | #include <net/xfrm.h> | ||
18 | |||
19 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | ||
20 | { | ||
21 | struct ipv6hdr *outer_iph = skb->nh.ipv6h; | ||
22 | struct ipv6hdr *inner_iph = skb->h.ipv6h; | ||
23 | |||
24 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | ||
25 | IP6_ECN_set_ce(inner_iph); | ||
26 | } | ||
27 | |||
28 | /* Add encapsulation header. | ||
29 | * | ||
30 | * The top IP header will be constructed per RFC 2401. The following fields | ||
31 | * in it shall be filled in by x->type->output: | ||
32 | * payload_len | ||
33 | * | ||
34 | * On exit, skb->h will be set to the start of the encapsulation header to be | ||
35 | * filled in by x->type->output and skb->nh will be set to the nextheader field | ||
36 | * of the extension header directly preceding the encapsulation header, or in | ||
37 | * its absence, that of the top IP header. The value of skb->data will always | ||
38 | * point to the top IP header. | ||
39 | */ | ||
40 | static int xfrm6_tunnel_output(struct sk_buff *skb) | ||
41 | { | ||
42 | struct dst_entry *dst = skb->dst; | ||
43 | struct xfrm_state *x = dst->xfrm; | ||
44 | struct ipv6hdr *iph, *top_iph; | ||
45 | int dsfield; | ||
46 | |||
47 | skb_push(skb, x->props.header_len); | ||
48 | iph = skb->nh.ipv6h; | ||
49 | |||
50 | skb->nh.raw = skb->data; | ||
51 | top_iph = skb->nh.ipv6h; | ||
52 | skb->nh.raw = &top_iph->nexthdr; | ||
53 | skb->h.ipv6h = top_iph + 1; | ||
54 | |||
55 | top_iph->version = 6; | ||
56 | top_iph->priority = iph->priority; | ||
57 | top_iph->flow_lbl[0] = iph->flow_lbl[0]; | ||
58 | top_iph->flow_lbl[1] = iph->flow_lbl[1]; | ||
59 | top_iph->flow_lbl[2] = iph->flow_lbl[2]; | ||
60 | dsfield = ipv6_get_dsfield(top_iph); | ||
61 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); | ||
62 | if (x->props.flags & XFRM_STATE_NOECN) | ||
63 | dsfield &= ~INET_ECN_MASK; | ||
64 | ipv6_change_dsfield(top_iph, 0, dsfield); | ||
65 | top_iph->nexthdr = IPPROTO_IPV6; | ||
66 | top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); | ||
67 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | ||
68 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | ||
73 | { | ||
74 | int err = -EINVAL; | ||
75 | |||
76 | if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6) | ||
77 | goto out; | ||
78 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
79 | goto out; | ||
80 | |||
81 | if (skb_cloned(skb) && | ||
82 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | ||
83 | goto out; | ||
84 | |||
85 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | ||
86 | ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h); | ||
87 | if (!(x->props.flags & XFRM_STATE_NOECN)) | ||
88 | ipip6_ecn_decapsulate(skb); | ||
89 | skb->mac.raw = memmove(skb->data - skb->mac_len, | ||
90 | skb->mac.raw, skb->mac_len); | ||
91 | skb->nh.raw = skb->data; | ||
92 | err = 0; | ||
93 | |||
94 | out: | ||
95 | return err; | ||
96 | } | ||
97 | |||
98 | static struct xfrm_mode xfrm6_tunnel_mode = { | ||
99 | .input = xfrm6_tunnel_input, | ||
100 | .output = xfrm6_tunnel_output, | ||
101 | .owner = THIS_MODULE, | ||
102 | .encap = XFRM_MODE_TUNNEL, | ||
103 | }; | ||
104 | |||
105 | static int __init xfrm6_tunnel_init(void) | ||
106 | { | ||
107 | return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6); | ||
108 | } | ||
109 | |||
110 | static void __exit xfrm6_tunnel_exit(void) | ||
111 | { | ||
112 | int err; | ||
113 | |||
114 | err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6); | ||
115 | BUG_ON(err); | ||
116 | } | ||
117 | |||
118 | module_init(xfrm6_tunnel_init); | ||
119 | module_exit(xfrm6_tunnel_exit); | ||
120 | MODULE_LICENSE("GPL"); | ||
121 | MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL); | ||
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 80242172a5d..16e84254a25 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -14,68 +14,9 @@ | |||
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/icmpv6.h> | 15 | #include <linux/icmpv6.h> |
16 | #include <linux/netfilter_ipv6.h> | 16 | #include <linux/netfilter_ipv6.h> |
17 | #include <net/dsfield.h> | ||
18 | #include <net/inet_ecn.h> | ||
19 | #include <net/ipv6.h> | 17 | #include <net/ipv6.h> |
20 | #include <net/xfrm.h> | 18 | #include <net/xfrm.h> |
21 | 19 | ||
22 | /* Add encapsulation header. | ||
23 | * | ||
24 | * In transport mode, the IP header and mutable extension headers will be moved | ||
25 | * forward to make space for the encapsulation header. | ||
26 | * | ||
27 | * In tunnel mode, the top IP header will be constructed per RFC 2401. | ||
28 | * The following fields in it shall be filled in by x->type->output: | ||
29 | * payload_len | ||
30 | * | ||
31 | * On exit, skb->h will be set to the start of the encapsulation header to be | ||
32 | * filled in by x->type->output and skb->nh will be set to the nextheader field | ||
33 | * of the extension header directly preceding the encapsulation header, or in | ||
34 | * its absence, that of the top IP header. The value of skb->data will always | ||
35 | * point to the top IP header. | ||
36 | */ | ||
37 | static void xfrm6_encap(struct sk_buff *skb) | ||
38 | { | ||
39 | struct dst_entry *dst = skb->dst; | ||
40 | struct xfrm_state *x = dst->xfrm; | ||
41 | struct ipv6hdr *iph, *top_iph; | ||
42 | int dsfield; | ||
43 | |||
44 | skb_push(skb, x->props.header_len); | ||
45 | iph = skb->nh.ipv6h; | ||
46 | |||
47 | if (!x->props.mode) { | ||
48 | u8 *prevhdr; | ||
49 | int hdr_len; | ||
50 | |||
51 | hdr_len = ip6_find_1stfragopt(skb, &prevhdr); | ||
52 | skb->nh.raw = prevhdr - x->props.header_len; | ||
53 | skb->h.raw = skb->data + hdr_len; | ||
54 | memmove(skb->data, iph, hdr_len); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | skb->nh.raw = skb->data; | ||
59 | top_iph = skb->nh.ipv6h; | ||
60 | skb->nh.raw = &top_iph->nexthdr; | ||
61 | skb->h.ipv6h = top_iph + 1; | ||
62 | |||
63 | top_iph->version = 6; | ||
64 | top_iph->priority = iph->priority; | ||
65 | top_iph->flow_lbl[0] = iph->flow_lbl[0]; | ||
66 | top_iph->flow_lbl[1] = iph->flow_lbl[1]; | ||
67 | top_iph->flow_lbl[2] = iph->flow_lbl[2]; | ||
68 | dsfield = ipv6_get_dsfield(top_iph); | ||
69 | dsfield = INET_ECN_encapsulate(dsfield, dsfield); | ||
70 | if (x->props.flags & XFRM_STATE_NOECN) | ||
71 | dsfield &= ~INET_ECN_MASK; | ||
72 | ipv6_change_dsfield(top_iph, 0, dsfield); | ||
73 | top_iph->nexthdr = IPPROTO_IPV6; | ||
74 | top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); | ||
75 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | ||
76 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | ||
77 | } | ||
78 | |||
79 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) | 20 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) |
80 | { | 21 | { |
81 | int mtu, ret = 0; | 22 | int mtu, ret = 0; |
@@ -118,7 +59,9 @@ static int xfrm6_output_one(struct sk_buff *skb) | |||
118 | if (err) | 59 | if (err) |
119 | goto error; | 60 | goto error; |
120 | 61 | ||
121 | xfrm6_encap(skb); | 62 | err = x->mode->output(skb); |
63 | if (err) | ||
64 | goto error; | ||
122 | 65 | ||
123 | err = x->type->output(x, skb); | 66 | err = x->type->output(x, skb); |
124 | if (err) | 67 | if (err) |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 88c840f1beb..ee715f2691e 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -23,8 +23,6 @@ | |||
23 | static struct dst_ops xfrm6_dst_ops; | 23 | static struct dst_ops xfrm6_dst_ops; |
24 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 24 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
25 | 25 | ||
26 | static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED }; | ||
27 | |||
28 | static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) | 26 | static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) |
29 | { | 27 | { |
30 | int err = 0; | 28 | int err = 0; |
@@ -249,9 +247,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
249 | 247 | ||
250 | static inline int xfrm6_garbage_collect(void) | 248 | static inline int xfrm6_garbage_collect(void) |
251 | { | 249 | { |
252 | read_lock(&xfrm6_policy_afinfo.lock); | ||
253 | xfrm6_policy_afinfo.garbage_collect(); | 250 | xfrm6_policy_afinfo.garbage_collect(); |
254 | read_unlock(&xfrm6_policy_afinfo.lock); | ||
255 | return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); | 251 | return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); |
256 | } | 252 | } |
257 | 253 | ||
@@ -311,8 +307,6 @@ static struct dst_ops xfrm6_dst_ops = { | |||
311 | 307 | ||
312 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | 308 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { |
313 | .family = AF_INET6, | 309 | .family = AF_INET6, |
314 | .lock = RW_LOCK_UNLOCKED, | ||
315 | .type_map = &xfrm6_type_map, | ||
316 | .dst_ops = &xfrm6_dst_ops, | 310 | .dst_ops = &xfrm6_dst_ops, |
317 | .dst_lookup = xfrm6_dst_lookup, | 311 | .dst_lookup = xfrm6_dst_lookup, |
318 | .find_bundle = __xfrm6_find_bundle, | 312 | .find_bundle = __xfrm6_find_bundle, |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index a5723024d3b..b33296b3f6d 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -135,7 +135,6 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, | |||
135 | 135 | ||
136 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 136 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
137 | .family = AF_INET6, | 137 | .family = AF_INET6, |
138 | .lock = RW_LOCK_UNLOCKED, | ||
139 | .init_tempsel = __xfrm6_init_tempsel, | 138 | .init_tempsel = __xfrm6_init_tempsel, |
140 | .state_lookup = __xfrm6_state_lookup, | 139 | .state_lookup = __xfrm6_state_lookup, |
141 | .find_acq = __xfrm6_find_acq, | 140 | .find_acq = __xfrm6_find_acq, |