List Info

Thread: Replace reverse_route() with a call to ip_route_me_harder()




Replace reverse_route() with a call to ip_route_me_harder()
user name
2006-09-19 03:56:08
Sorry, the previous invocation of this patch was hopelessly
broken.
This should be a little better.

-- 
Horms
  H: http://www.vergenet.n
et/~horms/
  W: http://www.valinux.co.jp
/en/


*** Please review this patch carefully, I'm not sure that
it is correct ***

ip_route_me_harder() can now be passed the address type,
which means that inet_addr_type() is not called internally,
and thus ip_route_me_harder() is now reasonably cheap.

Make use of this by replacing ipt_REJECT's the reverse
route,
which is largely a duplication of ip_route_me_harder().

Signed-Off-By: Simon Horman <hormsverge.net.au>

Index: net-2.6.19/net/ipv4/netfilter/ipt_REJECT.c
============================================================
=======
---
net-2.6.19.orig/net/ipv4/netfilter/ipt_REJECT.c	2006-09-19
12:50:43.000000000 +0900
+++ net-2.6.19/net/ipv4/netfilter/ipt_REJECT.c	2006-09-19
12:53:42.000000000 +0900
 -38,13
+38,9 
 #define DEBUGP(format, args...)
 #endif
 
-static inline struct rtable *route_reverse(struct sk_buff
*skb, 
-					   struct tcphdr *tcph, int hook)
+static inline int send_reset_route(struct sk_buff **pskb,
int hook)
 {
-	struct iphdr *iph = skb->nh.iph;
-	struct dst_entry *odst;
-	struct flowi fl = {};
-	struct rtable *rt;
+	int addr_type;
 
 	/* We don't require ip forwarding to be enabled to be
able to
 	 * send a RST reply for bridged traffic. */
 -52,62
+48,23 
 #ifdef CONFIG_BRIDGE_NETFILTER
 	    || (skb->nf_bridge &&
skb->nf_bridge->mask & BRNF_BRIDGED)
 #endif
-	   ) {
-		fl.nl_u.ip4_u.daddr = iph->saddr;
-		if (hook == NF_IP_LOCAL_IN)
-			fl.nl_u.ip4_u.saddr = iph->daddr;
-		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+	   )
+		addr_type = 1;
+	else
+		addr_type = 2;
 
-		if (ip_route_output_key(&rt, &fl) != 0)
-			return NULL;
-	} else {
-		/* non-local src, find valid iif to satisfy
-		 * rp-filter when calling ip_route_input. */
-		fl.nl_u.ip4_u.daddr = iph->daddr;
-		if (ip_route_output_key(&rt, &fl) != 0)
-			return NULL;
-
-		odst = skb->dst;
-		if (ip_route_input(skb, iph->saddr, iph->daddr,
-		                   RT_TOS(iph->tos), rt->u.dst.dev)
!= 0) {
-			dst_release(&rt->u.dst);
-			return NULL;
-		}
-		dst_release(&rt->u.dst);
-		rt = (struct rtable *)skb->dst;
-		skb->dst = odst;
-
-		fl.nl_u.ip4_u.daddr = iph->saddr;
-		fl.nl_u.ip4_u.saddr = iph->daddr;
-		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
-	}
-
-	if (rt->u.dst.error) {
-		dst_release(&rt->u.dst);
-		return NULL;
-	}
-
-	fl.proto = IPPROTO_TCP;
-	fl.fl_ip_sport = tcph->dest;
-	fl.fl_ip_dport = tcph->source;
-	security_skb_classify_flow(skb, &fl);
-
-	xfrm_lookup((struct dst_entry **)&rt, &fl, NULL,
0);
-
-	return rt;
+	return ip_route_me_harder(pskb, addr_type);
 }
 
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
-	struct sk_buff *nskb;
+	struct sk_buff *nskb, **pnskb;
 	struct iphdr *iph = oldskb->nh.iph;
 	struct tcphdr _otcph, *oth, *tcph;
-	struct rtable *rt;
 	u_int16_t tmp_port;
 	u_int32_t tmp_addr;
 	int needs_ack;
-	int hh_len;
 
 	/* IP header checks: fragment. */
 	if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
 -126,23
+83,15 
 	if (nf_ip_checksum(oldskb, hook, iph->ihl * 4,
IPPROTO_TCP))
 		return;
 
-	if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
-		return;
-
-	hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
-
 	/* We need a linear, writeable skb.  We also need to
expand
 	   headroom in case hh_len of incoming interface <
hh_len of
-	   outgoing interface */
-	nskb = skb_copy_expand(oldskb, hh_len,
skb_tailroom(oldskb),
+	   outgoing interface. As routing happens later, using
+	   ip_route_me_harder(), LL_MAX_HEADER is used as hh_len,
+	   to ensure there will always be enough space. */
+	nskb = skb_copy_expand(oldskb, LL_MAX_HEADER,
skb_tailroom(oldskb),
 			       GFP_ATOMIC);
-	if (!nskb) {
-		dst_release(&rt->u.dst);
+	if (!nskb)
 		return;
-	}
-
-	dst_release(nskb->dst);
-	nskb->dst = &rt->u.dst;
 
 	/* This packet will not be the same as the other: clear nf
fields */
 	nf_reset(nskb);
 -204,6
+153,12 
 	nskb->nh.iph->check = ip_fast_csum((unsigned char
*)nskb->nh.iph, 
 					   nskb->nh.iph->ihl);
 
+	/* Route - this may not need to be so late */
+	pnskb = &nskb;
+	if (send_reset_route(pnskb, hook) < 0)
+		goto free_nskb;
+	nskb = *pnskb;
+
 	/* "Never happens" */
 	if (nskb->len > dst_mtu(nskb->dst))
 		goto free_nskb;

[1]

about | contact  Other archives ( Real Estate discussion Medical topics )