aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-11-06 11:52:20 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-11 00:19:35 -0500
commit6aafeef03b9d9ecf255f3a80ed85ee070260e1ae (patch)
tree48c7f8ff1709c9874342c02c7039d4431a00b333
parent9037c3579a277f3a23ba476664629fda8c35f7c4 (diff)
netfilter: push reasm skb through instead of original frag skbs
Pushing original fragments through causes several problems. For example for matching, frags may not be matched correctly. Take following example: <example> On HOSTA do: ip6tables -I INPUT -p icmpv6 -j DROP ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT and on HOSTB you do: ping6 HOSTA -s2000 (MTU is 1500) Incoming echo requests will be filtered out on HOSTA. This issue does not occur with smaller packets than MTU (where fragmentation does not happen) </example> As was discussed previously, the only correct solution seems to be to use reassembled skb instead of separete frags. Doing this has positive side effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams dances in ipvs and conntrack can be removed. Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c entirely and use code in net/ipv6/reassembly.c instead. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h32
-rw-r--r--include/net/ip_vs.h32
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h4
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c56
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c19
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c7
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c55
-rw-r--r--net/netfilter/ipvs/ip_vs_pe_sip.c8
9 files changed, 13 insertions, 203 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 036ec7d8a83a..215b5ea1cb30 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -337,11 +337,6 @@ typedef unsigned int sk_buff_data_t;
337typedef unsigned char *sk_buff_data_t; 337typedef unsigned char *sk_buff_data_t;
338#endif 338#endif
339 339
340#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
341 defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
342#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
343#endif
344
345/** 340/**
346 * struct sk_buff - socket buffer 341 * struct sk_buff - socket buffer
347 * @next: Next buffer in list 342 * @next: Next buffer in list
@@ -374,7 +369,6 @@ typedef unsigned char *sk_buff_data_t;
374 * @protocol: Packet protocol from driver 369 * @protocol: Packet protocol from driver
375 * @destructor: Destruct function 370 * @destructor: Destruct function
376 * @nfct: Associated connection, if any 371 * @nfct: Associated connection, if any
377 * @nfct_reasm: netfilter conntrack re-assembly pointer
378 * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c 372 * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
379 * @skb_iif: ifindex of device we arrived on 373 * @skb_iif: ifindex of device we arrived on
380 * @tc_index: Traffic control index 374 * @tc_index: Traffic control index
@@ -463,9 +457,6 @@ struct sk_buff {
463#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 457#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
464 struct nf_conntrack *nfct; 458 struct nf_conntrack *nfct;
465#endif 459#endif
466#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
467 struct sk_buff *nfct_reasm;
468#endif
469#ifdef CONFIG_BRIDGE_NETFILTER 460#ifdef CONFIG_BRIDGE_NETFILTER
470 struct nf_bridge_info *nf_bridge; 461 struct nf_bridge_info *nf_bridge;
471#endif 462#endif
@@ -2595,18 +2586,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
2595 atomic_inc(&nfct->use); 2586 atomic_inc(&nfct->use);
2596} 2587}
2597#endif 2588#endif
2598#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
2599static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
2600{
2601 if (skb)
2602 atomic_inc(&skb->users);
2603}
2604static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
2605{
2606 if (skb)
2607 kfree_skb(skb);
2608}
2609#endif
2610#ifdef CONFIG_BRIDGE_NETFILTER 2589#ifdef CONFIG_BRIDGE_NETFILTER
2611static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) 2590static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2612{ 2591{
@@ -2625,10 +2604,6 @@ static inline void nf_reset(struct sk_buff *skb)
2625 nf_conntrack_put(skb->nfct); 2604 nf_conntrack_put(skb->nfct);
2626 skb->nfct = NULL; 2605 skb->nfct = NULL;
2627#endif 2606#endif
2628#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
2629 nf_conntrack_put_reasm(skb->nfct_reasm);
2630 skb->nfct_reasm = NULL;
2631#endif
2632#ifdef CONFIG_BRIDGE_NETFILTER 2607#ifdef CONFIG_BRIDGE_NETFILTER
2633 nf_bridge_put(skb->nf_bridge); 2608 nf_bridge_put(skb->nf_bridge);
2634 skb->nf_bridge = NULL; 2609 skb->nf_bridge = NULL;
@@ -2650,10 +2625,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
2650 nf_conntrack_get(src->nfct); 2625 nf_conntrack_get(src->nfct);
2651 dst->nfctinfo = src->nfctinfo; 2626 dst->nfctinfo = src->nfctinfo;
2652#endif 2627#endif
2653#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
2654 dst->nfct_reasm = src->nfct_reasm;
2655 nf_conntrack_get_reasm(src->nfct_reasm);
2656#endif
2657#ifdef CONFIG_BRIDGE_NETFILTER 2628#ifdef CONFIG_BRIDGE_NETFILTER
2658 dst->nf_bridge = src->nf_bridge; 2629 dst->nf_bridge = src->nf_bridge;
2659 nf_bridge_get(src->nf_bridge); 2630 nf_bridge_get(src->nf_bridge);
@@ -2665,9 +2636,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
2665#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 2636#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
2666 nf_conntrack_put(dst->nfct); 2637 nf_conntrack_put(dst->nfct);
2667#endif 2638#endif
2668#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
2669 nf_conntrack_put_reasm(dst->nfct_reasm);
2670#endif
2671#ifdef CONFIG_BRIDGE_NETFILTER 2639#ifdef CONFIG_BRIDGE_NETFILTER
2672 nf_bridge_put(dst->nf_bridge); 2640 nf_bridge_put(dst->nf_bridge);
2673#endif 2641#endif
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index cd7275f9c463..5679d927562b 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size;
109struct ip_vs_iphdr { 109struct ip_vs_iphdr {
110 __u32 len; /* IPv4 simply where L4 starts 110 __u32 len; /* IPv4 simply where L4 starts
111 IPv6 where L4 Transport Header starts */ 111 IPv6 where L4 Transport Header starts */
112 __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
113 __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ 112 __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
114 __s16 protocol; 113 __s16 protocol;
115 __s32 flags; 114 __s32 flags;
@@ -117,34 +116,12 @@ struct ip_vs_iphdr {
117 union nf_inet_addr daddr; 116 union nf_inet_addr daddr;
118}; 117};
119 118
120/* Dependency to module: nf_defrag_ipv6 */
121#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
122static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
123{
124 return skb->nfct_reasm;
125}
126static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
127 int len, void *buffer,
128 const struct ip_vs_iphdr *ipvsh)
129{
130 if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
131 return skb_header_pointer(skb_nfct_reasm(skb),
132 ipvsh->thoff_reasm, len, buffer);
133
134 return skb_header_pointer(skb, offset, len, buffer);
135}
136#else
137static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
138{
139 return NULL;
140}
141static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, 119static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
142 int len, void *buffer, 120 int len, void *buffer,
143 const struct ip_vs_iphdr *ipvsh) 121 const struct ip_vs_iphdr *ipvsh)
144{ 122{
145 return skb_header_pointer(skb, offset, len, buffer); 123 return skb_header_pointer(skb, offset, len, buffer);
146} 124}
147#endif
148 125
149static inline void 126static inline void
150ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) 127ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
171 (struct ipv6hdr *)skb_network_header(skb); 148 (struct ipv6hdr *)skb_network_header(skb);
172 iphdr->saddr.in6 = iph->saddr; 149 iphdr->saddr.in6 = iph->saddr;
173 iphdr->daddr.in6 = iph->daddr; 150 iphdr->daddr.in6 = iph->daddr;
174 /* ipv6_find_hdr() updates len, flags, thoff_reasm */ 151 /* ipv6_find_hdr() updates len, flags */
175 iphdr->thoff_reasm = 0;
176 iphdr->len = 0; 152 iphdr->len = 0;
177 iphdr->flags = 0; 153 iphdr->flags = 0;
178 iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, 154 iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
179 &iphdr->fragoffs, 155 &iphdr->fragoffs,
180 &iphdr->flags); 156 &iphdr->flags);
181 /* get proto from re-assembled packet and it's offset */
182 if (skb_nfct_reasm(skb))
183 iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
184 &iphdr->thoff_reasm,
185 -1, NULL, NULL);
186
187 } else 157 } else
188#endif 158#endif
189 { 159 {
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index 5613412e7dc2..27666d8a0bd0 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -6,9 +6,7 @@ void nf_defrag_ipv6_enable(void);
6int nf_ct_frag6_init(void); 6int nf_ct_frag6_init(void);
7void nf_ct_frag6_cleanup(void); 7void nf_ct_frag6_cleanup(void);
8struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); 8struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
9void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, 9void nf_ct_frag6_consume_orig(struct sk_buff *skb);
10 struct net_device *in, struct net_device *out,
11 int (*okfn)(struct sk_buff *));
12 10
13struct inet_frags_ctl; 11struct inet_frags_ctl;
14 12
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8c5197fe55a4..8cec1e6b844d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -592,9 +592,6 @@ static void skb_release_head_state(struct sk_buff *skb)
592#if IS_ENABLED(CONFIG_NF_CONNTRACK) 592#if IS_ENABLED(CONFIG_NF_CONNTRACK)
593 nf_conntrack_put(skb->nfct); 593 nf_conntrack_put(skb->nfct);
594#endif 594#endif
595#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
596 nf_conntrack_put_reasm(skb->nfct_reasm);
597#endif
598#ifdef CONFIG_BRIDGE_NETFILTER 595#ifdef CONFIG_BRIDGE_NETFILTER
599 nf_bridge_put(skb->nf_bridge); 596 nf_bridge_put(skb->nf_bridge);
600#endif 597#endif
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 486545eb42ce..4cbc6b290dd5 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -169,64 +169,13 @@ out:
169 return nf_conntrack_confirm(skb); 169 return nf_conntrack_confirm(skb);
170} 170}
171 171
172static unsigned int __ipv6_conntrack_in(struct net *net,
173 unsigned int hooknum,
174 struct sk_buff *skb,
175 const struct net_device *in,
176 const struct net_device *out,
177 int (*okfn)(struct sk_buff *))
178{
179 struct sk_buff *reasm = skb->nfct_reasm;
180 const struct nf_conn_help *help;
181 struct nf_conn *ct;
182 enum ip_conntrack_info ctinfo;
183
184 /* This packet is fragmented and has reassembled packet. */
185 if (reasm) {
186 /* Reassembled packet isn't parsed yet ? */
187 if (!reasm->nfct) {
188 unsigned int ret;
189
190 ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm);
191 if (ret != NF_ACCEPT)
192 return ret;
193 }
194
195 /* Conntrack helpers need the entire reassembled packet in the
196 * POST_ROUTING hook. In case of unconfirmed connections NAT
197 * might reassign a helper, so the entire packet is also
198 * required.
199 */
200 ct = nf_ct_get(reasm, &ctinfo);
201 if (ct != NULL && !nf_ct_is_untracked(ct)) {
202 help = nfct_help(ct);
203 if ((help && help->helper) || !nf_ct_is_confirmed(ct)) {
204 nf_conntrack_get_reasm(reasm);
205 NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
206 (struct net_device *)in,
207 (struct net_device *)out,
208 okfn, NF_IP6_PRI_CONNTRACK + 1);
209 return NF_DROP_ERR(-ECANCELED);
210 }
211 }
212
213 nf_conntrack_get(reasm->nfct);
214 skb->nfct = reasm->nfct;
215 skb->nfctinfo = reasm->nfctinfo;
216 return NF_ACCEPT;
217 }
218
219 return nf_conntrack_in(net, PF_INET6, hooknum, skb);
220}
221
222static unsigned int ipv6_conntrack_in(const struct nf_hook_ops *ops, 172static unsigned int ipv6_conntrack_in(const struct nf_hook_ops *ops,
223 struct sk_buff *skb, 173 struct sk_buff *skb,
224 const struct net_device *in, 174 const struct net_device *in,
225 const struct net_device *out, 175 const struct net_device *out,
226 int (*okfn)(struct sk_buff *)) 176 int (*okfn)(struct sk_buff *))
227{ 177{
228 return __ipv6_conntrack_in(dev_net(in), ops->hooknum, skb, in, out, 178 return nf_conntrack_in(dev_net(in), PF_INET6, ops->hooknum, skb);
229 okfn);
230} 179}
231 180
232static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops, 181static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops,
@@ -240,8 +189,7 @@ static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops,
240 net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); 189 net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
241 return NF_ACCEPT; 190 return NF_ACCEPT;
242 } 191 }
243 return __ipv6_conntrack_in(dev_net(out), ops->hooknum, skb, in, out, 192 return nf_conntrack_in(dev_net(out), PF_INET6, ops->hooknum, skb);
244 okfn);
245} 193}
246 194
247static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { 195static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 4a258263d8ec..767ab8da8218 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -633,31 +633,16 @@ ret_orig:
633 return skb; 633 return skb;
634} 634}
635 635
636void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, 636void nf_ct_frag6_consume_orig(struct sk_buff *skb)
637 struct net_device *in, struct net_device *out,
638 int (*okfn)(struct sk_buff *))
639{ 637{
640 struct sk_buff *s, *s2; 638 struct sk_buff *s, *s2;
641 unsigned int ret = 0;
642 639
643 for (s = NFCT_FRAG6_CB(skb)->orig; s;) { 640 for (s = NFCT_FRAG6_CB(skb)->orig; s;) {
644 nf_conntrack_put_reasm(s->nfct_reasm);
645 nf_conntrack_get_reasm(skb);
646 s->nfct_reasm = skb;
647
648 s2 = s->next; 641 s2 = s->next;
649 s->next = NULL; 642 s->next = NULL;
650 643 consume_skb(s);
651 if (ret != -ECANCELED)
652 ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s,
653 in, out, okfn,
654 NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
655 else
656 kfree_skb(s);
657
658 s = s2; 644 s = s2;
659 } 645 }
660 nf_conntrack_put_reasm(skb);
661} 646}
662 647
663static int nf_ct_net_init(struct net *net) 648static int nf_ct_net_init(struct net *net)
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index ec483aa3f60f..7b9a748c6bac 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
75 if (reasm == skb) 75 if (reasm == skb)
76 return NF_ACCEPT; 76 return NF_ACCEPT;
77 77
78 nf_ct_frag6_output(ops->hooknum, reasm, (struct net_device *)in, 78 nf_ct_frag6_consume_orig(reasm);
79 (struct net_device *)out, okfn); 79
80 NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, reasm,
81 (struct net_device *) in, (struct net_device *) out,
82 okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
80 83
81 return NF_STOLEN; 84 return NF_STOLEN;
82} 85}
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 34fda62f40f6..4f26ee46b51f 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1139,12 +1139,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1139 ip_vs_fill_iph_skb(af, skb, &iph); 1139 ip_vs_fill_iph_skb(af, skb, &iph);
1140#ifdef CONFIG_IP_VS_IPV6 1140#ifdef CONFIG_IP_VS_IPV6
1141 if (af == AF_INET6) { 1141 if (af == AF_INET6) {
1142 if (!iph.fragoffs && skb_nfct_reasm(skb)) {
1143 struct sk_buff *reasm = skb_nfct_reasm(skb);
1144 /* Save fw mark for coming frags */
1145 reasm->ipvs_property = 1;
1146 reasm->mark = skb->mark;
1147 }
1148 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { 1142 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
1149 int related; 1143 int related;
1150 int verdict = ip_vs_out_icmp_v6(skb, &related, 1144 int verdict = ip_vs_out_icmp_v6(skb, &related,
@@ -1614,12 +1608,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1614 1608
1615#ifdef CONFIG_IP_VS_IPV6 1609#ifdef CONFIG_IP_VS_IPV6
1616 if (af == AF_INET6) { 1610 if (af == AF_INET6) {
1617 if (!iph.fragoffs && skb_nfct_reasm(skb)) {
1618 struct sk_buff *reasm = skb_nfct_reasm(skb);
1619 /* Save fw mark for coming frags. */
1620 reasm->ipvs_property = 1;
1621 reasm->mark = skb->mark;
1622 }
1623 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { 1611 if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
1624 int related; 1612 int related;
1625 int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum, 1613 int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum,
@@ -1671,9 +1659,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1671 /* sorry, all this trouble for a no-hit :) */ 1659 /* sorry, all this trouble for a no-hit :) */
1672 IP_VS_DBG_PKT(12, af, pp, skb, 0, 1660 IP_VS_DBG_PKT(12, af, pp, skb, 0,
1673 "ip_vs_in: packet continues traversal as normal"); 1661 "ip_vs_in: packet continues traversal as normal");
1674 if (iph.fragoffs && !skb_nfct_reasm(skb)) { 1662 if (iph.fragoffs) {
1675 /* Fragment that couldn't be mapped to a conn entry 1663 /* Fragment that couldn't be mapped to a conn entry
1676 * and don't have any pointer to a reasm skb
1677 * is missing module nf_defrag_ipv6 1664 * is missing module nf_defrag_ipv6
1678 */ 1665 */
1679 IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n"); 1666 IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
@@ -1756,38 +1743,6 @@ ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
1756#ifdef CONFIG_IP_VS_IPV6 1743#ifdef CONFIG_IP_VS_IPV6
1757 1744
1758/* 1745/*
1759 * AF_INET6 fragment handling
1760 * Copy info from first fragment, to the rest of them.
1761 */
1762static unsigned int
1763ip_vs_preroute_frag6(const struct nf_hook_ops *ops, struct sk_buff *skb,
1764 const struct net_device *in,
1765 const struct net_device *out,
1766 int (*okfn)(struct sk_buff *))
1767{
1768 struct sk_buff *reasm = skb_nfct_reasm(skb);
1769 struct net *net;
1770
1771 /* Skip if not a "replay" from nf_ct_frag6_output or first fragment.
1772 * ipvs_property is set when checking first fragment
1773 * in ip_vs_in() and ip_vs_out().
1774 */
1775 if (reasm)
1776 IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property);
1777 if (!reasm || !reasm->ipvs_property)
1778 return NF_ACCEPT;
1779
1780 net = skb_net(skb);
1781 if (!net_ipvs(net)->enable)
1782 return NF_ACCEPT;
1783
1784 /* Copy stored fw mark, saved in ip_vs_{in,out} */
1785 skb->mark = reasm->mark;
1786
1787 return NF_ACCEPT;
1788}
1789
1790/*
1791 * AF_INET6 handler in NF_INET_LOCAL_IN chain 1746 * AF_INET6 handler in NF_INET_LOCAL_IN chain
1792 * Schedule and forward packets from remote clients 1747 * Schedule and forward packets from remote clients
1793 */ 1748 */
@@ -1924,14 +1879,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
1924 .priority = 100, 1879 .priority = 100,
1925 }, 1880 },
1926#ifdef CONFIG_IP_VS_IPV6 1881#ifdef CONFIG_IP_VS_IPV6
1927 /* After mangle & nat fetch 2:nd fragment and following */
1928 {
1929 .hook = ip_vs_preroute_frag6,
1930 .owner = THIS_MODULE,
1931 .pf = NFPROTO_IPV6,
1932 .hooknum = NF_INET_PRE_ROUTING,
1933 .priority = NF_IP6_PRI_NAT_DST + 1,
1934 },
1935 /* After packet filtering, change source only for VS/NAT */ 1882 /* After packet filtering, change source only for VS/NAT */
1936 { 1883 {
1937 .hook = ip_vs_reply6, 1884 .hook = ip_vs_reply6,
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
index 9ef22bdce9f1..bed5f7042529 100644
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff,
65static int 65static int
66ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) 66ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
67{ 67{
68 struct sk_buff *reasm = skb_nfct_reasm(skb);
69 struct ip_vs_iphdr iph; 68 struct ip_vs_iphdr iph;
70 unsigned int dataoff, datalen, matchoff, matchlen; 69 unsigned int dataoff, datalen, matchoff, matchlen;
71 const char *dptr; 70 const char *dptr;
@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
79 /* todo: IPv6 fragments: 78 /* todo: IPv6 fragments:
80 * I think this only should be done for the first fragment. /HS 79 * I think this only should be done for the first fragment. /HS
81 */ 80 */
82 if (reasm) { 81 dataoff = iph.len + sizeof(struct udphdr);
83 skb = reasm;
84 dataoff = iph.thoff_reasm + sizeof(struct udphdr);
85 } else
86 dataoff = iph.len + sizeof(struct udphdr);
87 82
88 if (dataoff >= skb->len) 83 if (dataoff >= skb->len)
89 return -EINVAL; 84 return -EINVAL;
90 /* todo: Check if this will mess-up the reasm skb !!! /HS */
91 retc = skb_linearize(skb); 85 retc = skb_linearize(skb);
92 if (retc < 0) 86 if (retc < 0)
93 return retc; 87 return retc;