diff options
Diffstat (limited to 'net')
40 files changed, 712 insertions, 122 deletions
diff --git a/net/802/Makefile b/net/802/Makefile index 01861929591a..977704a54f68 100644 --- a/net/802/Makefile +++ b/net/802/Makefile | |||
@@ -2,8 +2,6 @@ | |||
2 | # Makefile for the Linux 802.x protocol layers. | 2 | # Makefile for the Linux 802.x protocol layers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := p8023.o | ||
6 | |||
7 | # Check the p8022 selections against net/core/Makefile. | 5 | # Check the p8022 selections against net/core/Makefile. |
8 | obj-$(CONFIG_SYSCTL) += sysctl_net_802.o | 6 | obj-$(CONFIG_SYSCTL) += sysctl_net_802.o |
9 | obj-$(CONFIG_LLC) += p8022.o psnap.o | 7 | obj-$(CONFIG_LLC) += p8022.o psnap.o |
@@ -11,5 +9,5 @@ obj-$(CONFIG_TR) += p8022.o psnap.o tr.o sysctl_net_802.o | |||
11 | obj-$(CONFIG_NET_FC) += fc.o | 9 | obj-$(CONFIG_NET_FC) += fc.o |
12 | obj-$(CONFIG_FDDI) += fddi.o | 10 | obj-$(CONFIG_FDDI) += fddi.o |
13 | obj-$(CONFIG_HIPPI) += hippi.o | 11 | obj-$(CONFIG_HIPPI) += hippi.o |
14 | obj-$(CONFIG_IPX) += p8022.o psnap.o | 12 | obj-$(CONFIG_IPX) += p8022.o psnap.o p8023.o |
15 | obj-$(CONFIG_ATALK) += p8022.o psnap.o | 13 | obj-$(CONFIG_ATALK) += p8022.o psnap.o |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 3f244670764a..00f983226672 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -986,6 +986,7 @@ int dccp_v4_rcv(struct sk_buff *skb) | |||
986 | 986 | ||
987 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | 987 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
988 | goto discard_and_relse; | 988 | goto discard_and_relse; |
989 | nf_reset(skb); | ||
989 | 990 | ||
990 | return sk_receive_skb(sk, skb); | 991 | return sk_receive_skb(sk, skb); |
991 | 992 | ||
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index c609dc78f487..df074259f9c3 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
28 | #include <net/protocol.h> | 28 | #include <net/protocol.h> |
29 | #include <net/transp_v6.h> | 29 | #include <net/transp_v6.h> |
30 | #include <net/ip6_checksum.h> | ||
30 | #include <net/xfrm.h> | 31 | #include <net/xfrm.h> |
31 | 32 | ||
32 | #include "dccp.h" | 33 | #include "dccp.h" |
@@ -1028,7 +1029,7 @@ discard: | |||
1028 | return 0; | 1029 | return 0; |
1029 | } | 1030 | } |
1030 | 1031 | ||
1031 | static int dccp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 1032 | static int dccp_v6_rcv(struct sk_buff **pskb) |
1032 | { | 1033 | { |
1033 | const struct dccp_hdr *dh; | 1034 | const struct dccp_hdr *dh; |
1034 | struct sk_buff *skb = *pskb; | 1035 | struct sk_buff *skb = *pskb; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 912c42f57c79..de16e944777f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -832,6 +832,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
832 | skb->h.raw = skb->nh.raw; | 832 | skb->h.raw = skb->nh.raw; |
833 | skb->nh.raw = skb_push(skb, gre_hlen); | 833 | skb->nh.raw = skb_push(skb, gre_hlen); |
834 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 834 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
835 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | ||
835 | dst_release(skb->dst); | 836 | dst_release(skb->dst); |
836 | skb->dst = &rt->u.dst; | 837 | skb->dst = &rt->u.dst; |
837 | 838 | ||
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index e45846ae570b..18d7fad474d7 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -185,7 +185,6 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
185 | raw_rcv(last, skb2); | 185 | raw_rcv(last, skb2); |
186 | } | 186 | } |
187 | last = sk; | 187 | last = sk; |
188 | nf_reset(skb); | ||
189 | } | 188 | } |
190 | } | 189 | } |
191 | 190 | ||
@@ -204,10 +203,6 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) | |||
204 | 203 | ||
205 | __skb_pull(skb, ihl); | 204 | __skb_pull(skb, ihl); |
206 | 205 | ||
207 | /* Free reference early: we don't need it any more, and it may | ||
208 | hold ip_conntrack module loaded indefinitely. */ | ||
209 | nf_reset(skb); | ||
210 | |||
211 | /* Point into the IP datagram, just past the header. */ | 206 | /* Point into the IP datagram, just past the header. */ |
212 | skb->h.raw = skb->data; | 207 | skb->h.raw = skb->data; |
213 | 208 | ||
@@ -232,10 +227,12 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) | |||
232 | if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { | 227 | if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { |
233 | int ret; | 228 | int ret; |
234 | 229 | ||
235 | if (!ipprot->no_policy && | 230 | if (!ipprot->no_policy) { |
236 | !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 231 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
237 | kfree_skb(skb); | 232 | kfree_skb(skb); |
238 | goto out; | 233 | goto out; |
234 | } | ||
235 | nf_reset(skb); | ||
239 | } | 236 | } |
240 | ret = ipprot->handler(skb); | 237 | ret = ipprot->handler(skb); |
241 | if (ret < 0) { | 238 | if (ret < 0) { |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8b1c9bd0091e..c2169b47ddfd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -85,6 +85,8 @@ | |||
85 | 85 | ||
86 | int sysctl_ip_default_ttl = IPDEFTTL; | 86 | int sysctl_ip_default_ttl = IPDEFTTL; |
87 | 87 | ||
88 | static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)); | ||
89 | |||
88 | /* Generate a checksum for an outgoing IP datagram. */ | 90 | /* Generate a checksum for an outgoing IP datagram. */ |
89 | __inline__ void ip_send_check(struct iphdr *iph) | 91 | __inline__ void ip_send_check(struct iphdr *iph) |
90 | { | 92 | { |
@@ -202,6 +204,11 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
202 | 204 | ||
203 | static inline int ip_finish_output(struct sk_buff *skb) | 205 | static inline int ip_finish_output(struct sk_buff *skb) |
204 | { | 206 | { |
207 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | ||
208 | /* Policy lookup after SNAT yielded a new policy */ | ||
209 | if (skb->dst->xfrm != NULL) | ||
210 | return xfrm4_output_finish(skb); | ||
211 | #endif | ||
205 | if (skb->len > dst_mtu(skb->dst) && | 212 | if (skb->len > dst_mtu(skb->dst) && |
206 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | 213 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) |
207 | return ip_fragment(skb, ip_finish_output2); | 214 | return ip_fragment(skb, ip_finish_output2); |
@@ -409,7 +416,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
409 | * single device frame, and queue such a frame for sending. | 416 | * single device frame, and queue such a frame for sending. |
410 | */ | 417 | */ |
411 | 418 | ||
412 | int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) | 419 | static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) |
413 | { | 420 | { |
414 | struct iphdr *iph; | 421 | struct iphdr *iph; |
415 | int raw = 0; | 422 | int raw = 0; |
@@ -1391,7 +1398,6 @@ void __init ip_init(void) | |||
1391 | #endif | 1398 | #endif |
1392 | } | 1399 | } |
1393 | 1400 | ||
1394 | EXPORT_SYMBOL(ip_fragment); | ||
1395 | EXPORT_SYMBOL(ip_generic_getfrag); | 1401 | EXPORT_SYMBOL(ip_generic_getfrag); |
1396 | EXPORT_SYMBOL(ip_queue_xmit); | 1402 | EXPORT_SYMBOL(ip_queue_xmit); |
1397 | EXPORT_SYMBOL(ip_send_check); | 1403 | EXPORT_SYMBOL(ip_send_check); |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 35571cff81c6..bbd85f5ec985 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -621,6 +621,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
621 | skb->h.raw = skb->nh.raw; | 621 | skb->h.raw = skb->nh.raw; |
622 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 622 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
623 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 623 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
624 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED); | ||
624 | dst_release(skb->dst); | 625 | dst_release(skb->dst); |
625 | skb->dst = &rt->u.dst; | 626 | skb->dst = &rt->u.dst; |
626 | 627 | ||
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index ae0779d82c5d..3321092b0914 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -7,11 +7,13 @@ | |||
7 | #include <linux/netfilter.h> | 7 | #include <linux/netfilter.h> |
8 | #include <linux/netfilter_ipv4.h> | 8 | #include <linux/netfilter_ipv4.h> |
9 | 9 | ||
10 | #include <linux/ip.h> | ||
10 | #include <linux/tcp.h> | 11 | #include <linux/tcp.h> |
11 | #include <linux/udp.h> | 12 | #include <linux/udp.h> |
12 | #include <linux/icmp.h> | 13 | #include <linux/icmp.h> |
13 | #include <net/route.h> | 14 | #include <net/route.h> |
14 | #include <linux/ip.h> | 15 | #include <net/xfrm.h> |
16 | #include <net/ip.h> | ||
15 | 17 | ||
16 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ | 18 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ |
17 | int ip_route_me_harder(struct sk_buff **pskb) | 19 | int ip_route_me_harder(struct sk_buff **pskb) |
@@ -33,7 +35,6 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
33 | #ifdef CONFIG_IP_ROUTE_FWMARK | 35 | #ifdef CONFIG_IP_ROUTE_FWMARK |
34 | fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark; | 36 | fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark; |
35 | #endif | 37 | #endif |
36 | fl.proto = iph->protocol; | ||
37 | if (ip_route_output_key(&rt, &fl) != 0) | 38 | if (ip_route_output_key(&rt, &fl) != 0) |
38 | return -1; | 39 | return -1; |
39 | 40 | ||
@@ -60,6 +61,13 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
60 | if ((*pskb)->dst->error) | 61 | if ((*pskb)->dst->error) |
61 | return -1; | 62 | return -1; |
62 | 63 | ||
64 | #ifdef CONFIG_XFRM | ||
65 | if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) && | ||
66 | xfrm_decode_session(*pskb, &fl, AF_INET) == 0) | ||
67 | if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0)) | ||
68 | return -1; | ||
69 | #endif | ||
70 | |||
63 | /* Change in oif may mean change in hh_len. */ | 71 | /* Change in oif may mean change in hh_len. */ |
64 | hh_len = (*pskb)->dst->dev->hard_header_len; | 72 | hh_len = (*pskb)->dst->dev->hard_header_len; |
65 | if (skb_headroom(*pskb) < hh_len) { | 73 | if (skb_headroom(*pskb) < hh_len) { |
@@ -78,6 +86,9 @@ int ip_route_me_harder(struct sk_buff **pskb) | |||
78 | } | 86 | } |
79 | EXPORT_SYMBOL(ip_route_me_harder); | 87 | EXPORT_SYMBOL(ip_route_me_harder); |
80 | 88 | ||
89 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | ||
90 | EXPORT_SYMBOL(ip_nat_decode_session); | ||
91 | |||
81 | /* | 92 | /* |
82 | * Extra routing may needed on local out, as the QUEUE target never | 93 | * Extra routing may needed on local out, as the QUEUE target never |
83 | * returns control to the table. | 94 | * returns control to the table. |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 88a60650e6b8..a9893ec03e02 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -487,6 +487,16 @@ config IP_NF_MATCH_STRING | |||
487 | 487 | ||
488 | To compile it as a module, choose M here. If unsure, say N. | 488 | To compile it as a module, choose M here. If unsure, say N. |
489 | 489 | ||
490 | config IP_NF_MATCH_POLICY | ||
491 | tristate "IPsec policy match support" | ||
492 | depends on IP_NF_IPTABLES && XFRM | ||
493 | help | ||
494 | Policy matching allows you to match packets based on the | ||
495 | IPsec policy that was used during decapsulation/will | ||
496 | be used during encapsulation. | ||
497 | |||
498 | To compile it as a module, choose M here. If unsure, say N. | ||
499 | |||
490 | # `filter', generic and specific targets | 500 | # `filter', generic and specific targets |
491 | config IP_NF_FILTER | 501 | config IP_NF_FILTER |
492 | tristate "Packet filtering" | 502 | tristate "Packet filtering" |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index d0a447e520a2..549b01a648b3 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -72,6 +72,7 @@ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o | |||
72 | obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o | 72 | obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o |
73 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o | 73 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o |
74 | obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o | 74 | obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o |
75 | obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o | ||
75 | obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o | 76 | obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o |
76 | obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o | 77 | obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o |
77 | 78 | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 977fb59d4563..0b25050981a1 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
19 | #include <linux/interrupt.h> | ||
19 | #include <linux/netfilter.h> | 20 | #include <linux/netfilter.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/in.h> | 22 | #include <linux/in.h> |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index f04111f74e09..8b8a1f00bbf4 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -55,6 +55,44 @@ | |||
55 | : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ | 55 | : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ |
56 | : "*ERROR*"))) | 56 | : "*ERROR*"))) |
57 | 57 | ||
58 | #ifdef CONFIG_XFRM | ||
59 | static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | ||
60 | { | ||
61 | struct ip_conntrack *ct; | ||
62 | struct ip_conntrack_tuple *t; | ||
63 | enum ip_conntrack_info ctinfo; | ||
64 | enum ip_conntrack_dir dir; | ||
65 | unsigned long statusbit; | ||
66 | |||
67 | ct = ip_conntrack_get(skb, &ctinfo); | ||
68 | if (ct == NULL) | ||
69 | return; | ||
70 | dir = CTINFO2DIR(ctinfo); | ||
71 | t = &ct->tuplehash[dir].tuple; | ||
72 | |||
73 | if (dir == IP_CT_DIR_ORIGINAL) | ||
74 | statusbit = IPS_DST_NAT; | ||
75 | else | ||
76 | statusbit = IPS_SRC_NAT; | ||
77 | |||
78 | if (ct->status & statusbit) { | ||
79 | fl->fl4_dst = t->dst.ip; | ||
80 | if (t->dst.protonum == IPPROTO_TCP || | ||
81 | t->dst.protonum == IPPROTO_UDP) | ||
82 | fl->fl_ip_dport = t->dst.u.tcp.port; | ||
83 | } | ||
84 | |||
85 | statusbit ^= IPS_NAT_MASK; | ||
86 | |||
87 | if (ct->status & statusbit) { | ||
88 | fl->fl4_src = t->src.ip; | ||
89 | if (t->dst.protonum == IPPROTO_TCP || | ||
90 | t->dst.protonum == IPPROTO_UDP) | ||
91 | fl->fl_ip_sport = t->src.u.tcp.port; | ||
92 | } | ||
93 | } | ||
94 | #endif | ||
95 | |||
58 | static unsigned int | 96 | static unsigned int |
59 | ip_nat_fn(unsigned int hooknum, | 97 | ip_nat_fn(unsigned int hooknum, |
60 | struct sk_buff **pskb, | 98 | struct sk_buff **pskb, |
@@ -162,18 +200,20 @@ ip_nat_in(unsigned int hooknum, | |||
162 | const struct net_device *out, | 200 | const struct net_device *out, |
163 | int (*okfn)(struct sk_buff *)) | 201 | int (*okfn)(struct sk_buff *)) |
164 | { | 202 | { |
165 | u_int32_t saddr, daddr; | 203 | struct ip_conntrack *ct; |
204 | enum ip_conntrack_info ctinfo; | ||
166 | unsigned int ret; | 205 | unsigned int ret; |
167 | 206 | ||
168 | saddr = (*pskb)->nh.iph->saddr; | ||
169 | daddr = (*pskb)->nh.iph->daddr; | ||
170 | |||
171 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 207 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
172 | if (ret != NF_DROP && ret != NF_STOLEN | 208 | if (ret != NF_DROP && ret != NF_STOLEN |
173 | && ((*pskb)->nh.iph->saddr != saddr | 209 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { |
174 | || (*pskb)->nh.iph->daddr != daddr)) { | 210 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
175 | dst_release((*pskb)->dst); | 211 | |
176 | (*pskb)->dst = NULL; | 212 | if (ct->tuplehash[dir].tuple.src.ip != |
213 | ct->tuplehash[!dir].tuple.dst.ip) { | ||
214 | dst_release((*pskb)->dst); | ||
215 | (*pskb)->dst = NULL; | ||
216 | } | ||
177 | } | 217 | } |
178 | return ret; | 218 | return ret; |
179 | } | 219 | } |
@@ -185,12 +225,30 @@ ip_nat_out(unsigned int hooknum, | |||
185 | const struct net_device *out, | 225 | const struct net_device *out, |
186 | int (*okfn)(struct sk_buff *)) | 226 | int (*okfn)(struct sk_buff *)) |
187 | { | 227 | { |
228 | struct ip_conntrack *ct; | ||
229 | enum ip_conntrack_info ctinfo; | ||
230 | unsigned int ret; | ||
231 | |||
188 | /* root is playing with raw sockets. */ | 232 | /* root is playing with raw sockets. */ |
189 | if ((*pskb)->len < sizeof(struct iphdr) | 233 | if ((*pskb)->len < sizeof(struct iphdr) |
190 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) | 234 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) |
191 | return NF_ACCEPT; | 235 | return NF_ACCEPT; |
192 | 236 | ||
193 | return ip_nat_fn(hooknum, pskb, in, out, okfn); | 237 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
238 | if (ret != NF_DROP && ret != NF_STOLEN | ||
239 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | ||
240 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
241 | |||
242 | if (ct->tuplehash[dir].tuple.src.ip != | ||
243 | ct->tuplehash[!dir].tuple.dst.ip | ||
244 | #ifdef CONFIG_XFRM | ||
245 | || ct->tuplehash[dir].tuple.src.u.all != | ||
246 | ct->tuplehash[!dir].tuple.dst.u.all | ||
247 | #endif | ||
248 | ) | ||
249 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | ||
250 | } | ||
251 | return ret; | ||
194 | } | 252 | } |
195 | 253 | ||
196 | static unsigned int | 254 | static unsigned int |
@@ -200,7 +258,8 @@ ip_nat_local_fn(unsigned int hooknum, | |||
200 | const struct net_device *out, | 258 | const struct net_device *out, |
201 | int (*okfn)(struct sk_buff *)) | 259 | int (*okfn)(struct sk_buff *)) |
202 | { | 260 | { |
203 | u_int32_t saddr, daddr; | 261 | struct ip_conntrack *ct; |
262 | enum ip_conntrack_info ctinfo; | ||
204 | unsigned int ret; | 263 | unsigned int ret; |
205 | 264 | ||
206 | /* root is playing with raw sockets. */ | 265 | /* root is playing with raw sockets. */ |
@@ -208,14 +267,20 @@ ip_nat_local_fn(unsigned int hooknum, | |||
208 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) | 267 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) |
209 | return NF_ACCEPT; | 268 | return NF_ACCEPT; |
210 | 269 | ||
211 | saddr = (*pskb)->nh.iph->saddr; | ||
212 | daddr = (*pskb)->nh.iph->daddr; | ||
213 | |||
214 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 270 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
215 | if (ret != NF_DROP && ret != NF_STOLEN | 271 | if (ret != NF_DROP && ret != NF_STOLEN |
216 | && ((*pskb)->nh.iph->saddr != saddr | 272 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { |
217 | || (*pskb)->nh.iph->daddr != daddr)) | 273 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
218 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 274 | |
275 | if (ct->tuplehash[dir].tuple.dst.ip != | ||
276 | ct->tuplehash[!dir].tuple.src.ip | ||
277 | #ifdef CONFIG_XFRM | ||
278 | || ct->tuplehash[dir].tuple.dst.u.all != | ||
279 | ct->tuplehash[dir].tuple.src.u.all | ||
280 | #endif | ||
281 | ) | ||
282 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | ||
283 | } | ||
219 | return ret; | 284 | return ret; |
220 | } | 285 | } |
221 | 286 | ||
@@ -303,10 +368,14 @@ static int init_or_cleanup(int init) | |||
303 | 368 | ||
304 | if (!init) goto cleanup; | 369 | if (!init) goto cleanup; |
305 | 370 | ||
371 | #ifdef CONFIG_XFRM | ||
372 | BUG_ON(ip_nat_decode_session != NULL); | ||
373 | ip_nat_decode_session = nat_decode_session; | ||
374 | #endif | ||
306 | ret = ip_nat_rule_init(); | 375 | ret = ip_nat_rule_init(); |
307 | if (ret < 0) { | 376 | if (ret < 0) { |
308 | printk("ip_nat_init: can't setup rules.\n"); | 377 | printk("ip_nat_init: can't setup rules.\n"); |
309 | goto cleanup_nothing; | 378 | goto cleanup_decode_session; |
310 | } | 379 | } |
311 | ret = nf_register_hook(&ip_nat_in_ops); | 380 | ret = nf_register_hook(&ip_nat_in_ops); |
312 | if (ret < 0) { | 381 | if (ret < 0) { |
@@ -354,7 +423,11 @@ static int init_or_cleanup(int init) | |||
354 | nf_unregister_hook(&ip_nat_in_ops); | 423 | nf_unregister_hook(&ip_nat_in_ops); |
355 | cleanup_rule_init: | 424 | cleanup_rule_init: |
356 | ip_nat_rule_cleanup(); | 425 | ip_nat_rule_cleanup(); |
357 | cleanup_nothing: | 426 | cleanup_decode_session: |
427 | #ifdef CONFIG_XFRM | ||
428 | ip_nat_decode_session = NULL; | ||
429 | synchronize_net(); | ||
430 | #endif | ||
358 | return ret; | 431 | return ret; |
359 | } | 432 | } |
360 | 433 | ||
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c new file mode 100644 index 000000000000..709debcc69c9 --- /dev/null +++ b/net/ipv4/netfilter/ipt_policy.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* IP tables module for matching IPsec policy | ||
2 | * | ||
3 | * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <net/xfrm.h> | ||
16 | |||
17 | #include <linux/netfilter_ipv4.h> | ||
18 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
19 | #include <linux/netfilter_ipv4/ipt_policy.h> | ||
20 | |||
21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
22 | MODULE_DESCRIPTION("IPtables IPsec policy matching module"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | |||
26 | static inline int | ||
27 | match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e) | ||
28 | { | ||
29 | #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) | ||
30 | |||
31 | return MATCH(saddr, x->props.saddr.a4 & e->smask) && | ||
32 | MATCH(daddr, x->id.daddr.a4 & e->dmask) && | ||
33 | MATCH(proto, x->id.proto) && | ||
34 | MATCH(mode, x->props.mode) && | ||
35 | MATCH(spi, x->id.spi) && | ||
36 | MATCH(reqid, x->props.reqid); | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info) | ||
41 | { | ||
42 | const struct ipt_policy_elem *e; | ||
43 | struct sec_path *sp = skb->sp; | ||
44 | int strict = info->flags & IPT_POLICY_MATCH_STRICT; | ||
45 | int i, pos; | ||
46 | |||
47 | if (sp == NULL) | ||
48 | return -1; | ||
49 | if (strict && info->len != sp->len) | ||
50 | return 0; | ||
51 | |||
52 | for (i = sp->len - 1; i >= 0; i--) { | ||
53 | pos = strict ? i - sp->len + 1 : 0; | ||
54 | if (pos >= info->len) | ||
55 | return 0; | ||
56 | e = &info->pol[pos]; | ||
57 | |||
58 | if (match_xfrm_state(sp->x[i].xvec, e)) { | ||
59 | if (!strict) | ||
60 | return 1; | ||
61 | } else if (strict) | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | return strict ? 1 : 0; | ||
66 | } | ||
67 | |||
68 | static int | ||
69 | match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) | ||
70 | { | ||
71 | const struct ipt_policy_elem *e; | ||
72 | struct dst_entry *dst = skb->dst; | ||
73 | int strict = info->flags & IPT_POLICY_MATCH_STRICT; | ||
74 | int i, pos; | ||
75 | |||
76 | if (dst->xfrm == NULL) | ||
77 | return -1; | ||
78 | |||
79 | for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { | ||
80 | pos = strict ? i : 0; | ||
81 | if (pos >= info->len) | ||
82 | return 0; | ||
83 | e = &info->pol[pos]; | ||
84 | |||
85 | if (match_xfrm_state(dst->xfrm, e)) { | ||
86 | if (!strict) | ||
87 | return 1; | ||
88 | } else if (strict) | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | return strict ? 1 : 0; | ||
93 | } | ||
94 | |||
95 | static int match(const struct sk_buff *skb, | ||
96 | const struct net_device *in, | ||
97 | const struct net_device *out, | ||
98 | const void *matchinfo, int offset, int *hotdrop) | ||
99 | { | ||
100 | const struct ipt_policy_info *info = matchinfo; | ||
101 | int ret; | ||
102 | |||
103 | if (info->flags & IPT_POLICY_MATCH_IN) | ||
104 | ret = match_policy_in(skb, info); | ||
105 | else | ||
106 | ret = match_policy_out(skb, info); | ||
107 | |||
108 | if (ret < 0) | ||
109 | ret = info->flags & IPT_POLICY_MATCH_NONE ? 1 : 0; | ||
110 | else if (info->flags & IPT_POLICY_MATCH_NONE) | ||
111 | ret = 0; | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | ||
117 | void *matchinfo, unsigned int matchsize, | ||
118 | unsigned int hook_mask) | ||
119 | { | ||
120 | struct ipt_policy_info *info = matchinfo; | ||
121 | |||
122 | if (matchsize != IPT_ALIGN(sizeof(*info))) { | ||
123 | printk(KERN_ERR "ipt_policy: matchsize %u != %zu\n", | ||
124 | matchsize, IPT_ALIGN(sizeof(*info))); | ||
125 | return 0; | ||
126 | } | ||
127 | if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))) { | ||
128 | printk(KERN_ERR "ipt_policy: neither incoming nor " | ||
129 | "outgoing policy selected\n"); | ||
130 | return 0; | ||
131 | } | ||
132 | if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN) | ||
133 | && info->flags & IPT_POLICY_MATCH_OUT) { | ||
134 | printk(KERN_ERR "ipt_policy: output policy not valid in " | ||
135 | "PRE_ROUTING and INPUT\n"); | ||
136 | return 0; | ||
137 | } | ||
138 | if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT) | ||
139 | && info->flags & IPT_POLICY_MATCH_IN) { | ||
140 | printk(KERN_ERR "ipt_policy: input policy not valid in " | ||
141 | "POST_ROUTING and OUTPUT\n"); | ||
142 | return 0; | ||
143 | } | ||
144 | if (info->len > IPT_POLICY_MAX_ELEM) { | ||
145 | printk(KERN_ERR "ipt_policy: too many policy elements\n"); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | return 1; | ||
150 | } | ||
151 | |||
152 | static struct ipt_match policy_match = { | ||
153 | .name = "policy", | ||
154 | .match = match, | ||
155 | .checkentry = checkentry, | ||
156 | .me = THIS_MODULE, | ||
157 | }; | ||
158 | |||
159 | static int __init init(void) | ||
160 | { | ||
161 | return ipt_register_match(&policy_match); | ||
162 | } | ||
163 | |||
164 | static void __exit fini(void) | ||
165 | { | ||
166 | ipt_unregister_match(&policy_match); | ||
167 | } | ||
168 | |||
169 | module_init(init); | ||
170 | module_exit(fini); | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 4b0d7e4d6269..165a4d81efa4 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -255,6 +255,7 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb) | |||
255 | kfree_skb(skb); | 255 | kfree_skb(skb); |
256 | return NET_RX_DROP; | 256 | return NET_RX_DROP; |
257 | } | 257 | } |
258 | nf_reset(skb); | ||
258 | 259 | ||
259 | skb_push(skb, skb->data - skb->nh.raw); | 260 | skb_push(skb, skb->data - skb->nh.raw); |
260 | 261 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e9f83e5b28ce..6ea353907af5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1080,6 +1080,7 @@ process: | |||
1080 | 1080 | ||
1081 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | 1081 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
1082 | goto discard_and_relse; | 1082 | goto discard_and_relse; |
1083 | nf_reset(skb); | ||
1083 | 1084 | ||
1084 | if (sk_filter(sk, skb, 0)) | 1085 | if (sk_filter(sk, skb, 0)) |
1085 | goto discard_and_relse; | 1086 | goto discard_and_relse; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 223abaa72bc5..00840474a449 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -989,6 +989,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
989 | kfree_skb(skb); | 989 | kfree_skb(skb); |
990 | return -1; | 990 | return -1; |
991 | } | 991 | } |
992 | nf_reset(skb); | ||
992 | 993 | ||
993 | if (up->encap_type) { | 994 | if (up->encap_type) { |
994 | /* | 995 | /* |
@@ -1149,6 +1150,7 @@ int udp_rcv(struct sk_buff *skb) | |||
1149 | 1150 | ||
1150 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) | 1151 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) |
1151 | goto drop; | 1152 | goto drop; |
1153 | nf_reset(skb); | ||
1152 | 1154 | ||
1153 | /* No socket. Drop packet silently, if checksum is wrong */ | 1155 | /* No socket. Drop packet silently, if checksum is wrong */ |
1154 | if (udp_checksum_complete(skb)) | 1156 | if (udp_checksum_complete(skb)) |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 2d3849c38a0f..850d919591d1 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv4.h> | ||
14 | #include <net/inet_ecn.h> | 16 | #include <net/inet_ecn.h> |
15 | #include <net/ip.h> | 17 | #include <net/ip.h> |
16 | #include <net/xfrm.h> | 18 | #include <net/xfrm.h> |
@@ -45,6 +47,23 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) | |||
45 | return xfrm_parse_spi(skb, nexthdr, spi, seq); | 47 | return xfrm_parse_spi(skb, nexthdr, spi, seq); |
46 | } | 48 | } |
47 | 49 | ||
50 | #ifdef CONFIG_NETFILTER | ||
51 | static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb) | ||
52 | { | ||
53 | struct iphdr *iph = skb->nh.iph; | ||
54 | |||
55 | if (skb->dst == NULL) { | ||
56 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | ||
57 | skb->dev)) | ||
58 | goto drop; | ||
59 | } | ||
60 | return dst_input(skb); | ||
61 | drop: | ||
62 | kfree_skb(skb); | ||
63 | return NET_RX_DROP; | ||
64 | } | ||
65 | #endif | ||
66 | |||
48 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 67 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) |
49 | { | 68 | { |
50 | int err; | 69 | int err; |
@@ -137,6 +156,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
137 | memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); | 156 | memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); |
138 | skb->sp->len += xfrm_nr; | 157 | skb->sp->len += xfrm_nr; |
139 | 158 | ||
159 | nf_reset(skb); | ||
160 | |||
140 | if (decaps) { | 161 | if (decaps) { |
141 | if (!(skb->dev->flags&IFF_LOOPBACK)) { | 162 | if (!(skb->dev->flags&IFF_LOOPBACK)) { |
142 | dst_release(skb->dst); | 163 | dst_release(skb->dst); |
@@ -145,7 +166,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | |||
145 | netif_rx(skb); | 166 | netif_rx(skb); |
146 | return 0; | 167 | return 0; |
147 | } else { | 168 | } else { |
169 | #ifdef CONFIG_NETFILTER | ||
170 | __skb_push(skb, skb->data - skb->nh.raw); | ||
171 | skb->nh.iph->tot_len = htons(skb->len); | ||
172 | ip_send_check(skb->nh.iph); | ||
173 | |||
174 | NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, | ||
175 | xfrm4_rcv_encap_finish); | ||
176 | return 0; | ||
177 | #else | ||
148 | return -skb->nh.iph->protocol; | 178 | return -skb->nh.iph->protocol; |
179 | #endif | ||
149 | } | 180 | } |
150 | 181 | ||
151 | drop_unlock: | 182 | drop_unlock: |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 66620a95942a..d4df0ddd424b 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -8,8 +8,10 @@ | |||
8 | * 2 of the License, or (at your option) any later version. | 8 | * 2 of the License, or (at your option) any later version. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/compiler.h> | ||
11 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
12 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/netfilter_ipv4.h> | ||
13 | #include <net/inet_ecn.h> | 15 | #include <net/inet_ecn.h> |
14 | #include <net/ip.h> | 16 | #include <net/ip.h> |
15 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
@@ -95,7 +97,7 @@ out: | |||
95 | return ret; | 97 | return ret; |
96 | } | 98 | } |
97 | 99 | ||
98 | int xfrm4_output(struct sk_buff *skb) | 100 | static int xfrm4_output_one(struct sk_buff *skb) |
99 | { | 101 | { |
100 | struct dst_entry *dst = skb->dst; | 102 | struct dst_entry *dst = skb->dst; |
101 | struct xfrm_state *x = dst->xfrm; | 103 | struct xfrm_state *x = dst->xfrm; |
@@ -113,27 +115,33 @@ int xfrm4_output(struct sk_buff *skb) | |||
113 | goto error_nolock; | 115 | goto error_nolock; |
114 | } | 116 | } |
115 | 117 | ||
116 | spin_lock_bh(&x->lock); | 118 | do { |
117 | err = xfrm_state_check(x, skb); | 119 | spin_lock_bh(&x->lock); |
118 | if (err) | 120 | err = xfrm_state_check(x, skb); |
119 | goto error; | 121 | if (err) |
122 | goto error; | ||
120 | 123 | ||
121 | xfrm4_encap(skb); | 124 | xfrm4_encap(skb); |
122 | 125 | ||
123 | err = x->type->output(x, skb); | 126 | err = x->type->output(x, skb); |
124 | if (err) | 127 | if (err) |
125 | goto error; | 128 | goto error; |
126 | 129 | ||
127 | x->curlft.bytes += skb->len; | 130 | x->curlft.bytes += skb->len; |
128 | x->curlft.packets++; | 131 | x->curlft.packets++; |
129 | 132 | ||
130 | spin_unlock_bh(&x->lock); | 133 | spin_unlock_bh(&x->lock); |
131 | 134 | ||
132 | if (!(skb->dst = dst_pop(dst))) { | 135 | if (!(skb->dst = dst_pop(dst))) { |
133 | err = -EHOSTUNREACH; | 136 | err = -EHOSTUNREACH; |
134 | goto error_nolock; | 137 | goto error_nolock; |
135 | } | 138 | } |
136 | err = NET_XMIT_BYPASS; | 139 | dst = skb->dst; |
140 | x = dst->xfrm; | ||
141 | } while (x && !x->props.mode); | ||
142 | |||
143 | IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; | ||
144 | err = 0; | ||
137 | 145 | ||
138 | out_exit: | 146 | out_exit: |
139 | return err; | 147 | return err; |
@@ -143,3 +151,33 @@ error_nolock: | |||
143 | kfree_skb(skb); | 151 | kfree_skb(skb); |
144 | goto out_exit; | 152 | goto out_exit; |
145 | } | 153 | } |
154 | |||
155 | int xfrm4_output_finish(struct sk_buff *skb) | ||
156 | { | ||
157 | int err; | ||
158 | |||
159 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | ||
160 | nf_reset(skb); | ||
161 | |||
162 | err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL, | ||
163 | skb->dst->dev, dst_output); | ||
164 | if (unlikely(err != 1)) | ||
165 | break; | ||
166 | |||
167 | if (!skb->dst->xfrm) | ||
168 | return dst_output(skb); | ||
169 | |||
170 | err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL, | ||
171 | skb->dst->dev, xfrm4_output_finish); | ||
172 | if (unlikely(err != 1)) | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | return err; | ||
177 | } | ||
178 | |||
179 | int xfrm4_output(struct sk_buff *skb) | ||
180 | { | ||
181 | return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, | ||
182 | xfrm4_output_finish); | ||
183 | } | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 704fb73e6c5f..e53e421eeee9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1228,7 +1228,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
1228 | 1228 | ||
1229 | /* Gets referenced address, destroys ifaddr */ | 1229 | /* Gets referenced address, destroys ifaddr */ |
1230 | 1230 | ||
1231 | void addrconf_dad_stop(struct inet6_ifaddr *ifp) | 1231 | static void addrconf_dad_stop(struct inet6_ifaddr *ifp) |
1232 | { | 1232 | { |
1233 | if (ifp->flags&IFA_F_PERMANENT) { | 1233 | if (ifp->flags&IFA_F_PERMANENT) { |
1234 | spin_lock_bh(&ifp->lock); | 1234 | spin_lock_bh(&ifp->lock); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 68afc53be662..25c3fe5005d9 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -689,11 +689,11 @@ snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) | |||
689 | if (ptr == NULL) | 689 | if (ptr == NULL) |
690 | return -EINVAL; | 690 | return -EINVAL; |
691 | 691 | ||
692 | ptr[0] = __alloc_percpu(mibsize, mibalign); | 692 | ptr[0] = __alloc_percpu(mibsize); |
693 | if (!ptr[0]) | 693 | if (!ptr[0]) |
694 | goto err0; | 694 | goto err0; |
695 | 695 | ||
696 | ptr[1] = __alloc_percpu(mibsize, mibalign); | 696 | ptr[1] = __alloc_percpu(mibsize); |
697 | if (!ptr[1]) | 697 | if (!ptr[1]) |
698 | goto err1; | 698 | goto err1; |
699 | 699 | ||
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 113374dc342c..2a1e7e45b890 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -152,7 +152,7 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = { | |||
152 | {-1, NULL} | 152 | {-1, NULL} |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | 155 | static int ipv6_destopt_rcv(struct sk_buff **skbp) |
156 | { | 156 | { |
157 | struct sk_buff *skb = *skbp; | 157 | struct sk_buff *skb = *skbp; |
158 | struct inet6_skb_parm *opt = IP6CB(skb); | 158 | struct inet6_skb_parm *opt = IP6CB(skb); |
@@ -169,7 +169,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | |||
169 | 169 | ||
170 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { | 170 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { |
171 | skb->h.raw += ((skb->h.raw[1]+1)<<3); | 171 | skb->h.raw += ((skb->h.raw[1]+1)<<3); |
172 | *nhoffp = opt->dst1; | 172 | opt->nhoff = opt->dst1; |
173 | return 1; | 173 | return 1; |
174 | } | 174 | } |
175 | 175 | ||
@@ -192,7 +192,7 @@ void __init ipv6_destopt_init(void) | |||
192 | NONE header. No data in packet. | 192 | NONE header. No data in packet. |
193 | ********************************/ | 193 | ********************************/ |
194 | 194 | ||
195 | static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | 195 | static int ipv6_nodata_rcv(struct sk_buff **skbp) |
196 | { | 196 | { |
197 | struct sk_buff *skb = *skbp; | 197 | struct sk_buff *skb = *skbp; |
198 | 198 | ||
@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void) | |||
215 | Routing header. | 215 | Routing header. |
216 | ********************************/ | 216 | ********************************/ |
217 | 217 | ||
218 | static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | 218 | static int ipv6_rthdr_rcv(struct sk_buff **skbp) |
219 | { | 219 | { |
220 | struct sk_buff *skb = *skbp; | 220 | struct sk_buff *skb = *skbp; |
221 | struct inet6_skb_parm *opt = IP6CB(skb); | 221 | struct inet6_skb_parm *opt = IP6CB(skb); |
@@ -249,7 +249,7 @@ looped_back: | |||
249 | skb->h.raw += (hdr->hdrlen + 1) << 3; | 249 | skb->h.raw += (hdr->hdrlen + 1) << 3; |
250 | opt->dst0 = opt->dst1; | 250 | opt->dst0 = opt->dst1; |
251 | opt->dst1 = 0; | 251 | opt->dst1 = 0; |
252 | *nhoffp = (&hdr->nexthdr) - skb->nh.raw; | 252 | opt->nhoff = (&hdr->nexthdr) - skb->nh.raw; |
253 | return 1; | 253 | return 1; |
254 | } | 254 | } |
255 | 255 | ||
@@ -487,9 +487,14 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { | |||
487 | 487 | ||
488 | int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) | 488 | int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) |
489 | { | 489 | { |
490 | IP6CB(skb)->hop = sizeof(struct ipv6hdr); | 490 | struct inet6_skb_parm *opt = IP6CB(skb); |
491 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) | 491 | |
492 | opt->hop = sizeof(struct ipv6hdr); | ||
493 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { | ||
494 | skb->h.raw += (skb->h.raw[1]+1)<<3; | ||
495 | opt->nhoff = sizeof(struct ipv6hdr); | ||
492 | return sizeof(struct ipv6hdr); | 496 | return sizeof(struct ipv6hdr); |
497 | } | ||
493 | return -1; | 498 | return -1; |
494 | } | 499 | } |
495 | 500 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 6ec6a2b549bb..53c81fcd20ba 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -79,7 +79,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; | |||
79 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; | 79 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; |
80 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) | 80 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) |
81 | 81 | ||
82 | static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); | 82 | static int icmpv6_rcv(struct sk_buff **pskb); |
83 | 83 | ||
84 | static struct inet6_protocol icmpv6_protocol = { | 84 | static struct inet6_protocol icmpv6_protocol = { |
85 | .handler = icmpv6_rcv, | 85 | .handler = icmpv6_rcv, |
@@ -581,7 +581,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) | |||
581 | * Handle icmp messages | 581 | * Handle icmp messages |
582 | */ | 582 | */ |
583 | 583 | ||
584 | static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 584 | static int icmpv6_rcv(struct sk_buff **pskb) |
585 | { | 585 | { |
586 | struct sk_buff *skb = *pskb; | 586 | struct sk_buff *skb = *pskb; |
587 | struct net_device *dev = skb->dev; | 587 | struct net_device *dev = skb->dev; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 792f90f0f9ec..f8f3a37a1494 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <net/inet_hashtables.h> | 25 | #include <net/inet_hashtables.h> |
26 | #include <net/ip6_route.h> | 26 | #include <net/ip6_route.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/inet6_connection_sock.h> | ||
28 | 29 | ||
29 | int inet6_csk_bind_conflict(const struct sock *sk, | 30 | int inet6_csk_bind_conflict(const struct sock *sk, |
30 | const struct inet_bind_bucket *tb) | 31 | const struct inet_bind_bucket *tb) |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a6026d2787d2..29f73592e68e 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | 49 | ||
50 | 50 | ||
51 | static inline int ip6_rcv_finish( struct sk_buff *skb) | 51 | inline int ip6_rcv_finish( struct sk_buff *skb) |
52 | { | 52 | { |
53 | if (skb->dst == NULL) | 53 | if (skb->dst == NULL) |
54 | ip6_route_input(skb); | 54 | ip6_route_input(skb); |
@@ -97,6 +97,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
97 | if (hdr->version != 6) | 97 | if (hdr->version != 6) |
98 | goto err; | 98 | goto err; |
99 | 99 | ||
100 | skb->h.raw = (u8 *)(hdr + 1); | ||
101 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); | ||
102 | |||
100 | pkt_len = ntohs(hdr->payload_len); | 103 | pkt_len = ntohs(hdr->payload_len); |
101 | 104 | ||
102 | /* pkt_len may be zero if Jumbo payload option is present */ | 105 | /* pkt_len may be zero if Jumbo payload option is present */ |
@@ -111,8 +114,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
111 | } | 114 | } |
112 | 115 | ||
113 | if (hdr->nexthdr == NEXTHDR_HOP) { | 116 | if (hdr->nexthdr == NEXTHDR_HOP) { |
114 | skb->h.raw = (u8*)(hdr+1); | 117 | if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) { |
115 | if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) { | ||
116 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 118 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); |
117 | return 0; | 119 | return 0; |
118 | } | 120 | } |
@@ -143,26 +145,15 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
143 | int nexthdr; | 145 | int nexthdr; |
144 | u8 hash; | 146 | u8 hash; |
145 | 147 | ||
146 | skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); | ||
147 | |||
148 | /* | 148 | /* |
149 | * Parse extension headers | 149 | * Parse extension headers |
150 | */ | 150 | */ |
151 | 151 | ||
152 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
153 | nhoff = offsetof(struct ipv6hdr, nexthdr); | ||
154 | |||
155 | /* Skip hop-by-hop options, they are already parsed. */ | ||
156 | if (nexthdr == NEXTHDR_HOP) { | ||
157 | nhoff = sizeof(struct ipv6hdr); | ||
158 | nexthdr = skb->h.raw[0]; | ||
159 | skb->h.raw += (skb->h.raw[1]+1)<<3; | ||
160 | } | ||
161 | |||
162 | rcu_read_lock(); | 152 | rcu_read_lock(); |
163 | resubmit: | 153 | resubmit: |
164 | if (!pskb_pull(skb, skb->h.raw - skb->data)) | 154 | if (!pskb_pull(skb, skb->h.raw - skb->data)) |
165 | goto discard; | 155 | goto discard; |
156 | nhoff = IP6CB(skb)->nhoff; | ||
166 | nexthdr = skb->nh.raw[nhoff]; | 157 | nexthdr = skb->nh.raw[nhoff]; |
167 | 158 | ||
168 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); | 159 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); |
@@ -194,7 +185,7 @@ resubmit: | |||
194 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 185 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
195 | goto discard; | 186 | goto discard; |
196 | 187 | ||
197 | ret = ipprot->handler(&skb, &nhoff); | 188 | ret = ipprot->handler(&skb); |
198 | if (ret > 0) | 189 | if (ret > 0) |
199 | goto resubmit; | 190 | goto resubmit; |
200 | else if (ret == 0) | 191 | else if (ret == 0) |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e315d0f80af1..f079621c8b67 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -510,7 +510,7 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, | |||
510 | **/ | 510 | **/ |
511 | 511 | ||
512 | static int | 512 | static int |
513 | ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 513 | ip6ip6_rcv(struct sk_buff **pskb) |
514 | { | 514 | { |
515 | struct sk_buff *skb = *pskb; | 515 | struct sk_buff *skb = *pskb; |
516 | struct ipv6hdr *ipv6h; | 516 | struct ipv6hdr *ipv6h; |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index f8626ebf90fd..b63678328a3b 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <net/dst.h> | 10 | #include <net/dst.h> |
11 | #include <net/ipv6.h> | 11 | #include <net/ipv6.h> |
12 | #include <net/ip6_route.h> | 12 | #include <net/ip6_route.h> |
13 | #include <net/xfrm.h> | ||
13 | 14 | ||
14 | int ip6_route_me_harder(struct sk_buff *skb) | 15 | int ip6_route_me_harder(struct sk_buff *skb) |
15 | { | 16 | { |
@@ -21,11 +22,17 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
21 | { .ip6_u = | 22 | { .ip6_u = |
22 | { .daddr = iph->daddr, | 23 | { .daddr = iph->daddr, |
23 | .saddr = iph->saddr, } }, | 24 | .saddr = iph->saddr, } }, |
24 | .proto = iph->nexthdr, | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | dst = ip6_route_output(skb->sk, &fl); | 27 | dst = ip6_route_output(skb->sk, &fl); |
28 | 28 | ||
29 | #ifdef CONFIG_XFRM | ||
30 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
31 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) | ||
32 | if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0)) | ||
33 | return -1; | ||
34 | #endif | ||
35 | |||
29 | if (dst->error) { | 36 | if (dst->error) { |
30 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 37 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); |
31 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 38 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 04912f9b35c3..105dd69ee9fb 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -179,6 +179,16 @@ config IP6_NF_MATCH_PHYSDEV | |||
179 | 179 | ||
180 | To compile it as a module, choose M here. If unsure, say N. | 180 | To compile it as a module, choose M here. If unsure, say N. |
181 | 181 | ||
182 | config IP6_NF_MATCH_POLICY | ||
183 | tristate "IPsec policy match support" | ||
184 | depends on IP6_NF_IPTABLES && XFRM | ||
185 | help | ||
186 | Policy matching allows you to match packets based on the | ||
187 | IPsec policy that was used during decapsulation/will | ||
188 | be used during encapsulation. | ||
189 | |||
190 | To compile it as a module, choose M here. If unsure, say N. | ||
191 | |||
182 | # The targets | 192 | # The targets |
183 | config IP6_NF_FILTER | 193 | config IP6_NF_FILTER |
184 | tristate "Packet filtering" | 194 | tristate "Packet filtering" |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 9ab5b2ca1f59..c0c809b426e8 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o | |||
13 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 13 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
14 | obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o | 14 | obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o |
15 | obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o | 15 | obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o |
16 | obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o | ||
16 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 17 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
17 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o | 18 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o |
18 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o | 19 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o |
diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c new file mode 100644 index 000000000000..13fedad48c1d --- /dev/null +++ b/net/ipv6/netfilter/ip6t_policy.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* IP tables module for matching IPsec policy | ||
2 | * | ||
3 | * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <net/xfrm.h> | ||
16 | |||
17 | #include <linux/netfilter_ipv6.h> | ||
18 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
19 | #include <linux/netfilter_ipv6/ip6t_policy.h> | ||
20 | |||
21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
22 | MODULE_DESCRIPTION("IPtables IPsec policy matching module"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | |||
26 | static inline int | ||
27 | match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e) | ||
28 | { | ||
29 | #define MATCH_ADDR(x,y,z) (!e->match.x || \ | ||
30 | ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x) | ||
31 | #define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x)) | ||
32 | |||
33 | return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) && | ||
34 | MATCH_ADDR(daddr, dmask, (struct in6_addr *)&x->id.daddr.a6) && | ||
35 | MATCH(proto, x->id.proto) && | ||
36 | MATCH(mode, x->props.mode) && | ||
37 | MATCH(spi, x->id.spi) && | ||
38 | MATCH(reqid, x->props.reqid); | ||
39 | } | ||
40 | |||
41 | static int | ||
42 | match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info) | ||
43 | { | ||
44 | const struct ip6t_policy_elem *e; | ||
45 | struct sec_path *sp = skb->sp; | ||
46 | int strict = info->flags & IP6T_POLICY_MATCH_STRICT; | ||
47 | int i, pos; | ||
48 | |||
49 | if (sp == NULL) | ||
50 | return -1; | ||
51 | if (strict && info->len != sp->len) | ||
52 | return 0; | ||
53 | |||
54 | for (i = sp->len - 1; i >= 0; i--) { | ||
55 | pos = strict ? i - sp->len + 1 : 0; | ||
56 | if (pos >= info->len) | ||
57 | return 0; | ||
58 | e = &info->pol[pos]; | ||
59 | |||
60 | if (match_xfrm_state(sp->x[i].xvec, e)) { | ||
61 | if (!strict) | ||
62 | return 1; | ||
63 | } else if (strict) | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | return strict ? 1 : 0; | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info) | ||
72 | { | ||
73 | const struct ip6t_policy_elem *e; | ||
74 | struct dst_entry *dst = skb->dst; | ||
75 | int strict = info->flags & IP6T_POLICY_MATCH_STRICT; | ||
76 | int i, pos; | ||
77 | |||
78 | if (dst->xfrm == NULL) | ||
79 | return -1; | ||
80 | |||
81 | for (i = 0; dst && dst->xfrm; dst = dst->child, i++) { | ||
82 | pos = strict ? i : 0; | ||
83 | if (pos >= info->len) | ||
84 | return 0; | ||
85 | e = &info->pol[pos]; | ||
86 | |||
87 | if (match_xfrm_state(dst->xfrm, e)) { | ||
88 | if (!strict) | ||
89 | return 1; | ||
90 | } else if (strict) | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | return strict ? 1 : 0; | ||
95 | } | ||
96 | |||
97 | static int match(const struct sk_buff *skb, | ||
98 | const struct net_device *in, | ||
99 | const struct net_device *out, | ||
100 | const void *matchinfo, | ||
101 | int offset, | ||
102 | unsigned int protoff, | ||
103 | int *hotdrop) | ||
104 | { | ||
105 | const struct ip6t_policy_info *info = matchinfo; | ||
106 | int ret; | ||
107 | |||
108 | if (info->flags & IP6T_POLICY_MATCH_IN) | ||
109 | ret = match_policy_in(skb, info); | ||
110 | else | ||
111 | ret = match_policy_out(skb, info); | ||
112 | |||
113 | if (ret < 0) | ||
114 | ret = info->flags & IP6T_POLICY_MATCH_NONE ? 1 : 0; | ||
115 | else if (info->flags & IP6T_POLICY_MATCH_NONE) | ||
116 | ret = 0; | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, | ||
122 | void *matchinfo, unsigned int matchsize, | ||
123 | unsigned int hook_mask) | ||
124 | { | ||
125 | struct ip6t_policy_info *info = matchinfo; | ||
126 | |||
127 | if (matchsize != IP6T_ALIGN(sizeof(*info))) { | ||
128 | printk(KERN_ERR "ip6t_policy: matchsize %u != %zu\n", | ||
129 | matchsize, IP6T_ALIGN(sizeof(*info))); | ||
130 | return 0; | ||
131 | } | ||
132 | if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))) { | ||
133 | printk(KERN_ERR "ip6t_policy: neither incoming nor " | ||
134 | "outgoing policy selected\n"); | ||
135 | return 0; | ||
136 | } | ||
137 | if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN) | ||
138 | && info->flags & IP6T_POLICY_MATCH_OUT) { | ||
139 | printk(KERN_ERR "ip6t_policy: output policy not valid in " | ||
140 | "PRE_ROUTING and INPUT\n"); | ||
141 | return 0; | ||
142 | } | ||
143 | if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT) | ||
144 | && info->flags & IP6T_POLICY_MATCH_IN) { | ||
145 | printk(KERN_ERR "ip6t_policy: input policy not valid in " | ||
146 | "POST_ROUTING and OUTPUT\n"); | ||
147 | return 0; | ||
148 | } | ||
149 | if (info->len > IP6T_POLICY_MAX_ELEM) { | ||
150 | printk(KERN_ERR "ip6t_policy: too many policy elements\n"); | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | return 1; | ||
155 | } | ||
156 | |||
157 | static struct ip6t_match policy_match = { | ||
158 | .name = "policy", | ||
159 | .match = match, | ||
160 | .checkentry = checkentry, | ||
161 | .me = THIS_MODULE, | ||
162 | }; | ||
163 | |||
164 | static int __init init(void) | ||
165 | { | ||
166 | return ip6t_register_match(&policy_match); | ||
167 | } | ||
168 | |||
169 | static void __exit fini(void) | ||
170 | { | ||
171 | ip6t_unregister_match(&policy_match); | ||
172 | } | ||
173 | |||
174 | module_init(init); | ||
175 | module_exit(fini); | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 5d316cb72ec9..15e1456b3f18 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -581,7 +581,6 @@ err: | |||
581 | * the last and the first frames arrived and all the bits are here. | 581 | * the last and the first frames arrived and all the bits are here. |
582 | */ | 582 | */ |
583 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | 583 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, |
584 | unsigned int *nhoffp, | ||
585 | struct net_device *dev) | 584 | struct net_device *dev) |
586 | { | 585 | { |
587 | struct sk_buff *fp, *head = fq->fragments; | 586 | struct sk_buff *fp, *head = fq->fragments; |
@@ -654,6 +653,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
654 | head->dev = dev; | 653 | head->dev = dev; |
655 | skb_set_timestamp(head, &fq->stamp); | 654 | skb_set_timestamp(head, &fq->stamp); |
656 | head->nh.ipv6h->payload_len = htons(payload_len); | 655 | head->nh.ipv6h->payload_len = htons(payload_len); |
656 | IP6CB(head)->nhoff = nhoff; | ||
657 | 657 | ||
658 | *skb_in = head; | 658 | *skb_in = head; |
659 | 659 | ||
@@ -663,7 +663,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
663 | 663 | ||
664 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 664 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); |
665 | fq->fragments = NULL; | 665 | fq->fragments = NULL; |
666 | *nhoffp = nhoff; | ||
667 | return 1; | 666 | return 1; |
668 | 667 | ||
669 | out_oversize: | 668 | out_oversize: |
@@ -678,7 +677,7 @@ out_fail: | |||
678 | return -1; | 677 | return -1; |
679 | } | 678 | } |
680 | 679 | ||
681 | static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | 680 | static int ipv6_frag_rcv(struct sk_buff **skbp) |
682 | { | 681 | { |
683 | struct sk_buff *skb = *skbp; | 682 | struct sk_buff *skb = *skbp; |
684 | struct net_device *dev = skb->dev; | 683 | struct net_device *dev = skb->dev; |
@@ -710,7 +709,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | |||
710 | skb->h.raw += sizeof(struct frag_hdr); | 709 | skb->h.raw += sizeof(struct frag_hdr); |
711 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 710 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); |
712 | 711 | ||
713 | *nhoffp = (u8*)fhdr - skb->nh.raw; | 712 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; |
714 | return 1; | 713 | return 1; |
715 | } | 714 | } |
716 | 715 | ||
@@ -722,11 +721,11 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | |||
722 | 721 | ||
723 | spin_lock(&fq->lock); | 722 | spin_lock(&fq->lock); |
724 | 723 | ||
725 | ip6_frag_queue(fq, skb, fhdr, *nhoffp); | 724 | ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); |
726 | 725 | ||
727 | if (fq->last_in == (FIRST_IN|LAST_IN) && | 726 | if (fq->last_in == (FIRST_IN|LAST_IN) && |
728 | fq->meat == fq->len) | 727 | fq->meat == fq->len) |
729 | ret = ip6_frag_reasm(fq, skbp, nhoffp, dev); | 728 | ret = ip6_frag_reasm(fq, skbp, dev); |
730 | 729 | ||
731 | spin_unlock(&fq->lock); | 730 | spin_unlock(&fq->lock); |
732 | fq_put(fq, NULL); | 731 | fq_put(fq, NULL); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 577d49732b0f..02872ae8a439 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -381,6 +381,7 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
381 | skb->mac.raw = skb->nh.raw; | 381 | skb->mac.raw = skb->nh.raw; |
382 | skb->nh.raw = skb->data; | 382 | skb->nh.raw = skb->data; |
383 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); | 383 | memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); |
384 | IPCB(skb)->flags = 0; | ||
384 | skb->protocol = htons(ETH_P_IPV6); | 385 | skb->protocol = htons(ETH_P_IPV6); |
385 | skb->pkt_type = PACKET_HOST; | 386 | skb->pkt_type = PACKET_HOST; |
386 | tunnel->stat.rx_packets++; | 387 | tunnel->stat.rx_packets++; |
@@ -552,6 +553,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
552 | skb->h.raw = skb->nh.raw; | 553 | skb->h.raw = skb->nh.raw; |
553 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); | 554 | skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); |
554 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 555 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
556 | IPCB(skb)->flags = 0; | ||
555 | dst_release(skb->dst); | 557 | dst_release(skb->dst); |
556 | skb->dst = &rt->u.dst; | 558 | skb->dst = &rt->u.dst; |
557 | 559 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2947bc56d8a0..a25f4e8a8ada 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1153,7 +1153,7 @@ ipv6_pktoptions: | |||
1153 | return 0; | 1153 | return 0; |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 1156 | static int tcp_v6_rcv(struct sk_buff **pskb) |
1157 | { | 1157 | { |
1158 | struct sk_buff *skb = *pskb; | 1158 | struct sk_buff *skb = *pskb; |
1159 | struct tcphdr *th; | 1159 | struct tcphdr *th; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d8538dcea813..c47648892c04 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -435,7 +435,7 @@ out: | |||
435 | read_unlock(&udp_hash_lock); | 435 | read_unlock(&udp_hash_lock); |
436 | } | 436 | } |
437 | 437 | ||
438 | static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 438 | static int udpv6_rcv(struct sk_buff **pskb) |
439 | { | 439 | { |
440 | struct sk_buff *skb = *pskb; | 440 | struct sk_buff *skb = *pskb; |
441 | struct sock *sk; | 441 | struct sock *sk; |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 28c29d78338e..1ca2da68ef69 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6.h> | ||
14 | #include <net/dsfield.h> | 16 | #include <net/dsfield.h> |
15 | #include <net/inet_ecn.h> | 17 | #include <net/inet_ecn.h> |
16 | #include <net/ip.h> | 18 | #include <net/ip.h> |
@@ -26,7 +28,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | |||
26 | IP6_ECN_set_ce(inner_iph); | 28 | IP6_ECN_set_ce(inner_iph); |
27 | } | 29 | } |
28 | 30 | ||
29 | int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi) | 31 | int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi) |
30 | { | 32 | { |
31 | struct sk_buff *skb = *pskb; | 33 | struct sk_buff *skb = *pskb; |
32 | int err; | 34 | int err; |
@@ -38,7 +40,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi) | |||
38 | int nexthdr; | 40 | int nexthdr; |
39 | unsigned int nhoff; | 41 | unsigned int nhoff; |
40 | 42 | ||
41 | nhoff = *nhoffp; | 43 | nhoff = IP6CB(skb)->nhoff; |
42 | nexthdr = skb->nh.raw[nhoff]; | 44 | nexthdr = skb->nh.raw[nhoff]; |
43 | 45 | ||
44 | seq = 0; | 46 | seq = 0; |
@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi) | |||
121 | skb->sp->len += xfrm_nr; | 123 | skb->sp->len += xfrm_nr; |
122 | skb->ip_summed = CHECKSUM_NONE; | 124 | skb->ip_summed = CHECKSUM_NONE; |
123 | 125 | ||
126 | nf_reset(skb); | ||
127 | |||
124 | if (decaps) { | 128 | if (decaps) { |
125 | if (!(skb->dev->flags&IFF_LOOPBACK)) { | 129 | if (!(skb->dev->flags&IFF_LOOPBACK)) { |
126 | dst_release(skb->dst); | 130 | dst_release(skb->dst); |
@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi) | |||
129 | netif_rx(skb); | 133 | netif_rx(skb); |
130 | return -1; | 134 | return -1; |
131 | } else { | 135 | } else { |
136 | #ifdef CONFIG_NETFILTER | ||
137 | skb->nh.ipv6h->payload_len = htons(skb->len); | ||
138 | __skb_push(skb, skb->data - skb->nh.raw); | ||
139 | |||
140 | NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, | ||
141 | ip6_rcv_finish); | ||
142 | return -1; | ||
143 | #else | ||
132 | return 1; | 144 | return 1; |
145 | #endif | ||
133 | } | 146 | } |
134 | 147 | ||
135 | drop_unlock: | 148 | drop_unlock: |
@@ -144,7 +157,7 @@ drop: | |||
144 | 157 | ||
145 | EXPORT_SYMBOL(xfrm6_rcv_spi); | 158 | EXPORT_SYMBOL(xfrm6_rcv_spi); |
146 | 159 | ||
147 | int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 160 | int xfrm6_rcv(struct sk_buff **pskb) |
148 | { | 161 | { |
149 | return xfrm6_rcv_spi(pskb, nhoffp, 0); | 162 | return xfrm6_rcv_spi(pskb, 0); |
150 | } | 163 | } |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 6b9867717d11..80242172a5df 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -9,9 +9,11 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/compiler.h> | ||
12 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
14 | #include <linux/icmpv6.h> | 15 | #include <linux/icmpv6.h> |
16 | #include <linux/netfilter_ipv6.h> | ||
15 | #include <net/dsfield.h> | 17 | #include <net/dsfield.h> |
16 | #include <net/inet_ecn.h> | 18 | #include <net/inet_ecn.h> |
17 | #include <net/ipv6.h> | 19 | #include <net/ipv6.h> |
@@ -92,7 +94,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) | |||
92 | return ret; | 94 | return ret; |
93 | } | 95 | } |
94 | 96 | ||
95 | int xfrm6_output(struct sk_buff *skb) | 97 | static int xfrm6_output_one(struct sk_buff *skb) |
96 | { | 98 | { |
97 | struct dst_entry *dst = skb->dst; | 99 | struct dst_entry *dst = skb->dst; |
98 | struct xfrm_state *x = dst->xfrm; | 100 | struct xfrm_state *x = dst->xfrm; |
@@ -110,29 +112,35 @@ int xfrm6_output(struct sk_buff *skb) | |||
110 | goto error_nolock; | 112 | goto error_nolock; |
111 | } | 113 | } |
112 | 114 | ||
113 | spin_lock_bh(&x->lock); | 115 | do { |
114 | err = xfrm_state_check(x, skb); | 116 | spin_lock_bh(&x->lock); |
115 | if (err) | 117 | err = xfrm_state_check(x, skb); |
116 | goto error; | 118 | if (err) |
119 | goto error; | ||
117 | 120 | ||
118 | xfrm6_encap(skb); | 121 | xfrm6_encap(skb); |
119 | 122 | ||
120 | err = x->type->output(x, skb); | 123 | err = x->type->output(x, skb); |
121 | if (err) | 124 | if (err) |
122 | goto error; | 125 | goto error; |
123 | 126 | ||
124 | x->curlft.bytes += skb->len; | 127 | x->curlft.bytes += skb->len; |
125 | x->curlft.packets++; | 128 | x->curlft.packets++; |
126 | 129 | ||
127 | spin_unlock_bh(&x->lock); | 130 | spin_unlock_bh(&x->lock); |
128 | 131 | ||
129 | skb->nh.raw = skb->data; | 132 | skb->nh.raw = skb->data; |
130 | 133 | ||
131 | if (!(skb->dst = dst_pop(dst))) { | 134 | if (!(skb->dst = dst_pop(dst))) { |
132 | err = -EHOSTUNREACH; | 135 | err = -EHOSTUNREACH; |
133 | goto error_nolock; | 136 | goto error_nolock; |
134 | } | 137 | } |
135 | err = NET_XMIT_BYPASS; | 138 | dst = skb->dst; |
139 | x = dst->xfrm; | ||
140 | } while (x && !x->props.mode); | ||
141 | |||
142 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | ||
143 | err = 0; | ||
136 | 144 | ||
137 | out_exit: | 145 | out_exit: |
138 | return err; | 146 | return err; |
@@ -142,3 +150,33 @@ error_nolock: | |||
142 | kfree_skb(skb); | 150 | kfree_skb(skb); |
143 | goto out_exit; | 151 | goto out_exit; |
144 | } | 152 | } |
153 | |||
154 | static int xfrm6_output_finish(struct sk_buff *skb) | ||
155 | { | ||
156 | int err; | ||
157 | |||
158 | while (likely((err = xfrm6_output_one(skb)) == 0)) { | ||
159 | nf_reset(skb); | ||
160 | |||
161 | err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL, | ||
162 | skb->dst->dev, dst_output); | ||
163 | if (unlikely(err != 1)) | ||
164 | break; | ||
165 | |||
166 | if (!skb->dst->xfrm) | ||
167 | return dst_output(skb); | ||
168 | |||
169 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, | ||
170 | skb->dst->dev, xfrm6_output_finish); | ||
171 | if (unlikely(err != 1)) | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | return err; | ||
176 | } | ||
177 | |||
178 | int xfrm6_output(struct sk_buff *skb) | ||
179 | { | ||
180 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, | ||
181 | xfrm6_output_finish); | ||
182 | } | ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index fbef7826a74f..da09ff258648 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -397,7 +397,7 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) | |||
397 | 397 | ||
398 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); | 398 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); |
399 | 399 | ||
400 | static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 400 | static int xfrm6_tunnel_rcv(struct sk_buff **pskb) |
401 | { | 401 | { |
402 | struct sk_buff *skb = *pskb; | 402 | struct sk_buff *skb = *pskb; |
403 | struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; | 403 | struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; |
@@ -405,11 +405,11 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
405 | u32 spi; | 405 | u32 spi; |
406 | 406 | ||
407 | /* device-like_ip6ip6_handler() */ | 407 | /* device-like_ip6ip6_handler() */ |
408 | if (handler && handler->handler(pskb, nhoffp) == 0) | 408 | if (handler && handler->handler(pskb) == 0) |
409 | return 0; | 409 | return 0; |
410 | 410 | ||
411 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); | 411 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); |
412 | return xfrm6_rcv_spi(pskb, nhoffp, spi); | 412 | return xfrm6_rcv_spi(pskb, spi); |
413 | } | 413 | } |
414 | 414 | ||
415 | static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 415 | static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 238f1bffa684..4aa6fc60357c 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -225,6 +225,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
225 | 225 | ||
226 | if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family)) | 226 | if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family)) |
227 | goto discard_release; | 227 | goto discard_release; |
228 | nf_reset(skb); | ||
228 | 229 | ||
229 | ret = sk_filter(sk, skb, 1); | 230 | ret = sk_filter(sk, skb, 1); |
230 | if (ret) | 231 | if (ret) |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 15c05165c905..04c7fab4edc4 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -905,7 +905,7 @@ static struct inet_protosw sctpv6_stream_protosw = { | |||
905 | .flags = SCTP_PROTOSW_FLAG, | 905 | .flags = SCTP_PROTOSW_FLAG, |
906 | }; | 906 | }; |
907 | 907 | ||
908 | static int sctp6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | 908 | static int sctp6_rcv(struct sk_buff **pskb) |
909 | { | 909 | { |
910 | return sctp_rcv(*pskb) ? -1 : 0; | 910 | return sctp_rcv(*pskb) ? -1 : 0; |
911 | } | 911 | } |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 24cc23af9b95..e14c1cae7460 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -495,7 +495,7 @@ rpc_depopulate(struct dentry *parent) | |||
495 | repeat: | 495 | repeat: |
496 | spin_lock(&dcache_lock); | 496 | spin_lock(&dcache_lock); |
497 | list_for_each_safe(pos, next, &parent->d_subdirs) { | 497 | list_for_each_safe(pos, next, &parent->d_subdirs) { |
498 | dentry = list_entry(pos, struct dentry, d_child); | 498 | dentry = list_entry(pos, struct dentry, d_u.d_child); |
499 | spin_lock(&dentry->d_lock); | 499 | spin_lock(&dentry->d_lock); |
500 | if (!d_unhashed(dentry)) { | 500 | if (!d_unhashed(dentry)) { |
501 | dget_locked(dentry); | 501 | dget_locked(dentry); |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 64a447375fdb..59614a994b4e 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/notifier.h> | 23 | #include <linux/notifier.h> |
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/netfilter.h> | ||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <net/xfrm.h> | 27 | #include <net/xfrm.h> |
27 | #include <net/ip.h> | 28 | #include <net/ip.h> |
@@ -951,8 +952,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, | |||
951 | return start; | 952 | return start; |
952 | } | 953 | } |
953 | 954 | ||
954 | static int | 955 | int |
955 | _decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) | 956 | xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) |
956 | { | 957 | { |
957 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); | 958 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); |
958 | 959 | ||
@@ -963,6 +964,7 @@ _decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) | |||
963 | xfrm_policy_put_afinfo(afinfo); | 964 | xfrm_policy_put_afinfo(afinfo); |
964 | return 0; | 965 | return 0; |
965 | } | 966 | } |
967 | EXPORT_SYMBOL(xfrm_decode_session); | ||
966 | 968 | ||
967 | static inline int secpath_has_tunnel(struct sec_path *sp, int k) | 969 | static inline int secpath_has_tunnel(struct sec_path *sp, int k) |
968 | { | 970 | { |
@@ -982,8 +984,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
982 | u8 fl_dir = policy_to_flow_dir(dir); | 984 | u8 fl_dir = policy_to_flow_dir(dir); |
983 | u32 sk_sid; | 985 | u32 sk_sid; |
984 | 986 | ||
985 | if (_decode_session(skb, &fl, family) < 0) | 987 | if (xfrm_decode_session(skb, &fl, family) < 0) |
986 | return 0; | 988 | return 0; |
989 | nf_nat_decode_session(skb, &fl, family); | ||
987 | 990 | ||
988 | sk_sid = security_sk_sid(sk, &fl, fl_dir); | 991 | sk_sid = security_sk_sid(sk, &fl, fl_dir); |
989 | 992 | ||
@@ -1055,7 +1058,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
1055 | { | 1058 | { |
1056 | struct flowi fl; | 1059 | struct flowi fl; |
1057 | 1060 | ||
1058 | if (_decode_session(skb, &fl, family) < 0) | 1061 | if (xfrm_decode_session(skb, &fl, family) < 0) |
1059 | return 0; | 1062 | return 0; |
1060 | 1063 | ||
1061 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; | 1064 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; |