#include <linux/config.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/tcp.h>
struct in_device;
#include <net/route.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include "ipt_SIGN.h"

#if 1
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif

/* $Id: ipt_STRIPSPS.c,v 1.3 2001/08/28 21:42:49 ahu Exp $ */

static unsigned int stripsps(struct sk_buff **pskb,
			   unsigned int hooknum,
			   const struct net_device *in,
			   const struct net_device *out,
			   const void *targinfo,
			   void *userinfo)
{
/*	const struct ipt_stripsps_info *stripsps = targinfo; */
	struct iphdr *ih=(*pskb)->nh.iph;
	struct spshdr sh;
	int spslen;

	if(ih->protocol!=128) {/* no need to strip */
	  	printk("Got a packet that doesn't need stripping!\n");
	  	return IPT_CONTINUE; 
	}

	/* save SPS header */
	memcpy(&sh,(char*)ih+ih->ihl*4,sizeof(sh));

	spslen=sizeof(sh)+sh.sig_bytes;

	/* shift up payload */
	memmove((char *)ih+ih->ihl*4, (char *)ih+ih->ihl*4+spslen, ntohs(ih->tot_len)-spslen-ih->ihl*4);

	/* fix up packet length in ip header & skb */
	ih->tot_len=htons(ntohs(ih->tot_len)-spslen);
	skb_trim((*pskb),htons(ih->tot_len));

	ih->protocol=sh.orig_proto;

	/* recalculate checksum */
	ih->check=0;
	ih->check=ip_fast_csum((char *)ih, ih->ihl); /* FIXME: this should do incremental */

	(*pskb)->nfcache |= NFC_ALTERED; // tell netfilter we changed
	printk("stripped a packet\n");
	return IPT_CONTINUE;
}

static int check(const char *tablename,
		 const struct ipt_entry *e,
		 void *targinfo,
		 unsigned int targinfosize,
		 unsigned int hook_mask)
{
/* 	const struct ipt_stripsps_info *stripspsinfo = targinfo; */

 	if (targinfosize != 0) {
		DEBUGP("STRIPSPS: targinfosize %u != 0\n", targinfosize);
  		return 0;
  	}
	return 1;

	/* Only allow these for packet filtering. */
/*	if (strcmp(tablename, "filter") != 0) {
		DEBUGP("STRIPSPS: bad table `%s'.\n", tablename);
		return 0;
	} */
	
	if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
			   | (1 << NF_IP_FORWARD)
			   )) != 0) {
		DEBUGP("STRIPSPS: bad hook mask %X\n", hook_mask);
		return 0;
	}

	return 1;
}

static struct ipt_target ipt_stripsps_reg
= { { NULL, NULL }, "STRIPSPS", stripsps, check, NULL, THIS_MODULE };

static int __init init(void)
{
	if (ipt_register_target(&ipt_stripsps_reg))
		return -EINVAL;
	return 0;
}

static void __exit fini(void)
{
	ipt_unregister_target(&ipt_stripsps_reg);
}

module_init(init);
module_exit(fini);

