[PATCH 2.4] iptables MIRROR target fixes

From: Harald Welte (laforge@netfilter.org)
Date: Fri Jul 25 2003 - 15:50:48 EST


Hi Dave!

This is the first of a set of bugfixes (all tested against 2.4.22-pre7).
You might need to apply them incrementally (didn't test it in a
different order). You will receive 2.6 merges of those patches soon.

Author: Patrick McHardy <kaber@trash.net>

This patch fixes various problems with the experimental
iptables MIRROR target:

- check TTL before rewriting so icmp_send gets clean packet
- skb_copy_expand(skb) for tcpdump and asymmetric routing
- inline some function
- remove unneccessary 'struct in_device' declaration
- remove RTO_CONN

Please apply,

diff -Nru a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c
--- a/net/ipv4/netfilter/ipt_MIRROR.c Mon Apr 21 21:26:42 2003
+++ b/net/ipv4/netfilter/ipt_MIRROR.c Mon Apr 21 21:26:42 2003
@@ -32,7 +32,6 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
 #include <linux/route.h>
-struct in_device;
 #include <net/route.h>
 
 #if 0
@@ -41,31 +40,20 @@
 #define DEBUGP(format, args...)
 #endif
 
-static int route_mirror(struct sk_buff *skb)
+static inline struct rtable *route_mirror(struct sk_buff *skb)
 {
         struct iphdr *iph = skb->nh.iph;
         struct rtable *rt;
 
         /* Backwards */
         if (ip_route_output(&rt, iph->saddr, iph->daddr,
- RT_TOS(iph->tos) | RTO_CONN,
- 0)) {
- return 0;
- }
+ RT_TOS(iph->tos), 0))
+ return NULL;
 
- /* check if the interface we are leaving by is the same as the
- one we arrived on */
- if (skb->dev == rt->u.dst.dev) {
- /* Drop old route. */
- dst_release(skb->dst);
- skb->dst = &rt->u.dst;
- return 1;
- }
- return 0;
+ return rt;
 }
 
-static void
-ip_rewrite(struct sk_buff *skb)
+static inline void ip_rewrite(struct sk_buff *skb)
 {
         struct iphdr *iph = skb->nh.iph;
         u32 odaddr = iph->saddr;
@@ -105,32 +93,48 @@
                                       const void *targinfo,
                                       void *userinfo)
 {
- if (((*pskb)->dst != NULL) &&
- route_mirror(*pskb)) {
-
- ip_rewrite(*pskb);
+ struct rtable *rt;
+ struct sk_buff *nskb;
+ unsigned int hh_len;
 
- /* If we are not at FORWARD hook (INPUT/PREROUTING),
- * the TTL isn't decreased by the IP stack */
- if (hooknum != NF_IP_FORWARD) {
- struct iphdr *iph = (*pskb)->nh.iph;
- if (iph->ttl <= 1) {
- /* this will traverse normal stack, and
- * thus call conntrack on the icmp packet */
- icmp_send(*pskb, ICMP_TIME_EXCEEDED,
- ICMP_EXC_TTL, 0);
- return NF_DROP;
- }
- ip_decrease_ttl(iph);
+ /* If we are not at FORWARD hook (INPUT/PREROUTING),
+ * the TTL isn't decreased by the IP stack */
+ if (hooknum != NF_IP_FORWARD) {
+ struct iphdr *iph = (*pskb)->nh.iph;
+ if (iph->ttl <= 1) {
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(*pskb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ return NF_DROP;
                 }
+ ip_decrease_ttl(iph);
+ }
 
- /* Don't let conntrack code see this packet:
- it will think we are starting a new
- connection! --RR */
- ip_direct_send(*pskb);
+ if ((rt = route_mirror(*pskb)) == NULL)
+ return NF_DROP;
 
- return NF_STOLEN;
+ hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
+
+ /* Copy skb (even if skb is about to be dropped, we can't just
+ * clone it because there may be other things, such as tcpdump,
+ * interested in it). We also need to expand headroom in case
+ * hh_len of incoming interface < hh_len of outgoing interface */
+ nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
+ if (nskb == NULL) {
+ dst_release(&rt->u.dst);
+ return NF_DROP;
         }
+
+ dst_release(nskb->dst);
+ nskb->dst = &rt->u.dst;
+
+ ip_rewrite(nskb);
+ /* Don't let conntrack code see this packet:
+ it will think we are starting a new
+ connection! --RR */
+ ip_direct_send(nskb);
+
         return NF_DROP;
 }
 

-- 
- Harald Welte <laforge@netfilter.org>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie


- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jul 31 2003 - 22:00:27 EST