netfilter-2.6/patch-o-matic-ng/trunk: net/ipv4/netfilter/ipt_REJECT.c status

pluto cvs at pld-linux.org
Thu Jul 28 13:10:40 CEST 2005


Author: pluto
Date: Thu Jul 28 13:10:37 2005
New Revision: 6254

Modified:
   netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c
   netfilter-2.6/patch-o-matic-ng/trunk/status
Log:
- REJECT (ipv4) updated.


Modified: netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c	(original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/net/ipv4/netfilter/ipt_REJECT.c	Thu Jul 28 13:10:37 2005
@@ -213,16 +213,157 @@
 	nf_ct_attach(nskb, oldskb);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
-		dst_output);
+		ip_finish_output);
 	return;
 
  free_nskb:
 	kfree_skb(nskb);
 }
 
-static inline void send_unreach(struct sk_buff *skb_in, int code)
+static void send_unreach(struct sk_buff *skb_in, int code)
 {
-	icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
+	struct iphdr *iph;
+	struct icmphdr *icmph;
+	struct sk_buff *nskb;
+	u32 saddr;
+	u8 tos;
+	int hh_len, length;
+	struct rtable *rt = (struct rtable*)skb_in->dst;
+	unsigned char *data;
+
+	if (!rt)
+		return;
+
+	/* FIXME: Use sysctl number. --RR */
+	if (!xrlim_allow(&rt->u.dst, 1*HZ))
+		return;
+
+	iph = skb_in->nh.iph;
+
+	/* No replies to physical multicast/broadcast */
+	if (skb_in->pkt_type!=PACKET_HOST)
+		return;
+
+	/* Now check at the protocol level */
+	if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
+		return;
+
+	/* Only reply to fragment 0. */
+	if (iph->frag_off&htons(IP_OFFSET))
+		return;
+
+	/* Ensure we have at least 8 bytes of proto header. */
+	if (skb_in->len < skb_in->nh.iph->ihl*4 + 8)
+		return;
+
+	/* If we send an ICMP error to an ICMP error a mess would result.. */
+	if (iph->protocol == IPPROTO_ICMP) {
+		struct icmphdr ihdr;
+
+		icmph = skb_header_pointer(skb_in, skb_in->nh.iph->ihl*4,
+					   sizeof(ihdr), &ihdr);
+		if (!icmph)
+			return;
+
+		/* Between echo-reply (0) and timestamp (13),
+		   everything except echo-request (8) is an error.
+		   Also, anything greater than NR_ICMP_TYPES is
+		   unknown, and hence should be treated as an error... */
+		if ((icmph->type < ICMP_TIMESTAMP
+		     && icmph->type != ICMP_ECHOREPLY
+		     && icmph->type != ICMP_ECHO)
+		    || icmph->type > NR_ICMP_TYPES)
+			return;
+	}
+
+	saddr = iph->daddr;
+	if (!(rt->rt_flags & RTCF_LOCAL))
+		saddr = 0;
+
+	tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL;
+
+	{
+		struct flowi fl = {
+			.nl_u = {
+				.ip4_u = {
+					.daddr = skb_in->nh.iph->saddr,
+					.saddr = saddr,
+					.tos = RT_TOS(tos)
+				}
+			},
+			.proto = IPPROTO_ICMP,
+			.uli_u = {
+				.icmpt = {
+					.type = ICMP_DEST_UNREACH,
+					.code = code
+				}
+			}
+		};
+
+		if (ip_route_output_key(&rt, &fl))
+			return;
+	}
+	/* RFC says return as much as we can without exceeding 576 bytes. */
+	length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr);
+
+	if (length > dst_mtu(&rt->u.dst))
+		length = dst_mtu(&rt->u.dst);
+	if (length > 576)
+		length = 576;
+
+	hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
+
+	nskb = alloc_skb(hh_len + length, GFP_ATOMIC);
+	if (!nskb) {
+		ip_rt_put(rt);
+		return;
+	}
+
+	nskb->priority = 0;
+	nskb->dst = &rt->u.dst;
+	skb_reserve(nskb, hh_len);
+
+	/* Set up IP header */
+	iph = nskb->nh.iph
+		= (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
+	iph->version=4;
+	iph->ihl=5;
+	iph->tos=tos;
+	iph->tot_len = htons(length);
+
+	/* PMTU discovery never applies to ICMP packets. */
+	iph->frag_off = 0;
+
+	iph->ttl = MAXTTL;
+	ip_select_ident(iph, &rt->u.dst, NULL);
+	iph->protocol=IPPROTO_ICMP;
+	iph->saddr=rt->rt_src;
+	iph->daddr=rt->rt_dst;
+	iph->check=0;
+	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+	/* Set up ICMP header. */
+	icmph = nskb->h.icmph
+		= (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
+	icmph->type = ICMP_DEST_UNREACH;
+	icmph->code = code;	
+	icmph->un.gateway = 0;
+	icmph->checksum = 0;
+	
+	/* Copy as much of original packet as will fit */
+	data = skb_put(nskb,
+		       length - sizeof(struct iphdr) - sizeof(struct icmphdr));
+
+	skb_copy_bits(skb_in, 0, data,
+		      length - sizeof(struct iphdr) - sizeof(struct icmphdr));
+
+	icmph->checksum = ip_compute_csum((unsigned char *)icmph,
+					  length - sizeof(struct iphdr));
+
+	nf_ct_attach(nskb, skb_in);
+
+	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
+		ip_finish_output);
 }	
 
 static unsigned int reject(struct sk_buff **pskb,

Modified: netfilter-2.6/patch-o-matic-ng/trunk/status
==============================================================================
--- netfilter-2.6/patch-o-matic-ng/trunk/status	(original)
+++ netfilter-2.6/patch-o-matic-ng/trunk/status	Thu Jul 28 13:10:37 2005
@@ -32,7 +32,7 @@
 quota			2005/07/27	added
 realm					updated
 recent					updated		(v0.3.2)
-REJECT			2005/07/27	updated		(ipv6 added)
+REJECT			2005/07/27	added+updated	(ipv6 added, ipv4 updated)
 ROUTE			2005/07/27	added		(ipv6 / not working as a module)
 SAME					updated
 sctp					updated



More information about the pld-cvs-commit mailing list