/*
 *  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, 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_orig_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_orig_iif))
		if (printk_ratelimit())
			printk(KERN_INFO "ct: iif changed %d, %d\n", fp_info->iif, skb->skb_orig_iif);

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

done:
	return NF_ACCEPT;
}

static unsigned int fp_ipv4_netfilter_pre_routing(const struct nf_hook_ops *ops,
			       struct sk_buff *skb,
			       const struct nf_hook_state *state)
{

	return fp_netfilter_pre_routing(PF_INET, skb);
}

static unsigned int fp_ipv6_netfilter_pre_routing(const struct nf_hook_ops *ops,
			       struct sk_buff *skb,
			       const struct nf_hook_state *state)
{

	return fp_netfilter_pre_routing(PF_INET6, 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);
