[netfilter-cvslog] r3475 - in trunk/nfsim/core: . ipv4

rusty at netfilter.org rusty at netfilter.org
Mon Dec 20 14:38:35 CET 2004


Author: rusty at netfilter.org
Date: 2004-12-20 14:38:35 +0100 (Mon, 20 Dec 2004)
New Revision: 3475

Modified:
   trunk/nfsim/core/core.c
   trunk/nfsim/core/ipv4/ipv4.c
Log:
Fragment handling.


Modified: trunk/nfsim/core/core.c
===================================================================
--- trunk/nfsim/core/core.c	2004-12-20 06:46:58 UTC (rev 3474)
+++ trunk/nfsim/core/core.c	2004-12-20 13:38:35 UTC (rev 3475)
@@ -143,9 +143,14 @@
 	talloc_free(hookname);
 
 	ret = ops->hook(hooknum, skb, in, out, okfn);
-	nfsim_log(LOG_HOOK, "hook:%s %s %s%s",
-		   nf_hooknames[PF_INET][hooknum], ops->owner->name,
-		   nf_retval(ret), describe_packet(*skb));
+	if (ret == NF_STOLEN)
+		nfsim_log(LOG_HOOK, "hook:%s %s %s",
+			  nf_hooknames[PF_INET][hooknum], ops->owner->name,
+			  nf_retval(ret));
+	else
+		nfsim_log(LOG_HOOK, "hook:%s %s %s%s",
+			  nf_hooknames[PF_INET][hooknum], ops->owner->name,
+			  nf_retval(ret), describe_packet(*skb));
 	return ret;
 }
 

Modified: trunk/nfsim/core/ipv4/ipv4.c
===================================================================
--- trunk/nfsim/core/ipv4/ipv4.c	2004-12-20 06:46:58 UTC (rev 3474)
+++ trunk/nfsim/core/ipv4/ipv4.c	2004-12-20 13:38:35 UTC (rev 3475)
@@ -467,12 +467,87 @@
 	return 0;
 }
 
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct fraglist
 {
-	log_packet(skb, "ip_defrag");
+	struct list_head list;
+	struct sk_buff *frags[20];
+};
+static LIST_HEAD(fraglist);
+
+static struct sk_buff *gather_frag(struct fraglist *f, struct sk_buff *skb)
+{
+	unsigned int i, len, off, max = 0;
+	bool old, ended = false;
+	char filled[70000] = { 0 };
+	char data[70000];
+
+	for (i = 0; i < ARRAY_SIZE(f->frags); i++) {
+		if (!f->frags[i]) {
+			if (!skb)
+				break;
+			f->frags[i] = skb;
+			talloc_steal(f, skb);
+			skb = NULL;
+		}
+
+		off = (ntohs(f->frags[i]->nh.iph->frag_off) & IP_OFFSET)*8;
+		len = ntohs(f->frags[i]->nh.iph->tot_len) 
+			- f->frags[i]->nh.iph->ihl * 4;
+		if (len + off > max)
+			max = len + off;
+
+		memset(filled + off, 1, len);
+		memcpy(data + off, (void *)f->frags[i]->nh.iph
+		       + f->frags[i]->nh.iph->ihl * 4,
+		       len);
+		if (!(ntohs(f->frags[i]->nh.iph->frag_off) & IP_MF))
+			ended = true;
+	}
+	if (skb)
+		barf("Can't handle %i frags!\n", i);
+
+	/* Not a complete packet? */
+	if (!ended || memchr(filled, 0, max) != NULL)
+		return NULL;
+
+	/* Copy header and data. */
+	old = suppress_failtest;
+	suppress_failtest = true;
+	skb = skb_copy_expand(f->frags[0], 0, max, GFP_KERNEL);
+	suppress_failtest = old;
+
+	skb->nh.iph = (void *)skb->data;
+	memcpy(skb->nh.iph, f->frags[0]->nh.iph, f->frags[0]->nh.iph->ihl*4);
+	memcpy((void *)skb->nh.iph + f->frags[0]->nh.iph->ihl*4, data, len);
+
+	/* Except we're not a fragment, and we're longer. */
+	skb->nh.iph->frag_off = 0;
+	skb->nh.iph->tot_len = max + skb->nh.iph->ihl*4;
+
+	list_del(&f->list);
+	talloc_free(f);
 	return skb;
 }
 
+struct sk_buff *ip_defrag(struct sk_buff *skb)
+{
+	struct fraglist *i;
+
+	list_for_each_entry(i, &fraglist, list) {
+		if (i->frags[0]->nh.iph->saddr != skb->nh.iph->saddr
+		    || i->frags[0]->nh.iph->daddr != skb->nh.iph->daddr
+		    || i->frags[0]->nh.iph->protocol!=skb->nh.iph->protocol)
+			continue;
+		return gather_frag(i, skb);
+	}
+	i = talloc(NULL, struct fraglist);
+	memset(i->frags, 0, sizeof(i->frags));
+	i->frags[0] = skb;
+	list_add(&i->list, &fraglist);
+	talloc_steal(i, skb);
+	return NULL;
+}
+
 void ipfrag_flush(void)
 {
 }




More information about the netfilter-cvslog mailing list