/*
 *  linux/drivers/net/comcerto/fp_netfilter.c
 *
 *  Copyright (C) 2010 Mindspeed Technologies, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack.h>

static unsigned int fp_netfilter_pre_routing(int family, unsigned int hooknum, struct sk_buff *skb)
{
	struct nf_conn *ct;
	u_int8_t protonum;
	enum ip_conntrack_info ctinfo;
	struct comcerto_fp_info *fp_info;
	int dir;

	ct = nf_ct_get(skb, &ctinfo);
	if (!ct)
		goto done;

	protonum = nf_ct_protonum(ct);
	if ((protonum != IPPROTO_TCP) && (protonum != IPPROTO_UDP) && (protonum != IPPROTO_IPIP))
		goto done;

	dir = CTINFO2DIR(ctinfo);

//	if (printk_ratelimit())
//		printk(KERN_INFO "ct: %lx, dir: %x, mark: %x, ifindex: %d iif: %d\n", (unsigned long)ct, dir, skb->mark, skb->dev->ifindex, skb->skb_iif);

	/* We could also check for changes and notify userspace (or print message) */
	if (dir == IP_CT_DIR_ORIGINAL) {
		fp_info = &ct->fp_info[IP_CT_DIR_ORIGINAL];
	} else {
		fp_info = &ct->fp_info[IP_CT_DIR_REPLY];
	}

	if (fp_info->mark && (fp_info->mark != skb->mark))
		if (printk_ratelimit())
			printk(KERN_INFO "ct: mark changed %x, %x\n", fp_info->mark, skb->mark);

	if (fp_info->ifindex && (fp_info->ifindex != skb->dev->ifindex))
		if (printk_ratelimit())
			printk(KERN_INFO "ct: ifindex changed %d, %d\n", fp_info->ifindex, skb->dev->ifindex);

	if (fp_info->iif && (fp_info->iif != skb->skb_iif))
		if (printk_ratelimit())
			printk(KERN_INFO "ct: iif changed %d, %d\n", fp_info->iif, skb->skb_iif);

	fp_info->mark = skb->mark;
	fp_info->ifindex = skb->dev->ifindex;
	fp_info->iif = skb->skb_iif;

done:
	return NF_ACCEPT;
}

static unsigned int fp_ipv4_netfilter_pre_routing(unsigned int hooknum,
                                      struct sk_buff *skb,
                                      const struct net_device *in,
                                      const struct net_device *out,
                                      int (*okfn)(struct sk_buff *))
{

	return fp_netfilter_pre_routing(PF_INET, hooknum, skb);
}

static unsigned int fp_ipv6_netfilter_pre_routing(unsigned int hooknum,
                                      struct sk_buff *skb,
                                      const struct net_device *in,
                                      const struct net_device *out,
                                      int (*okfn)(struct sk_buff *))
{

	return fp_netfilter_pre_routing(PF_INET6, hooknum, skb);
}


static struct nf_hook_ops fp_netfilter_ops[] __read_mostly = {
	{
		.hook		= fp_ipv4_netfilter_pre_routing,
		.owner		= THIS_MODULE,
		.pf		= NFPROTO_IPV4,
		.hooknum	= NF_INET_PRE_ROUTING,
		.priority	= NF_IP_PRI_LAST,
	},
	{
		.hook		= fp_ipv6_netfilter_pre_routing,
		.owner		= THIS_MODULE,
		.pf		= NFPROTO_IPV6,
		.hooknum	= NF_INET_PRE_ROUTING,
		.priority	= NF_IP_PRI_LAST,
	},
};

static int __init fp_netfilter_init(void)
{
	int rc;

	rc = nf_register_hooks(fp_netfilter_ops, ARRAY_SIZE(fp_netfilter_ops));
	if (rc < 0) {
		printk(KERN_ERR "fp_netfilter_ops: can't register hooks.\n");
		goto err0;
	}

	return 0;

err0:
	return rc;
}


static void __exit fp_netfilter_exit(void)
{
	nf_unregister_hooks(fp_netfilter_ops, ARRAY_SIZE(fp_netfilter_ops));
}

module_init(fp_netfilter_init);
module_exit(fp_netfilter_exit);
