ipt_helper.c 3.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* iptables module to match on related connections */
/*
 * (C) 2001 Martin Josefsson <gandalf@wlug.westbo.se>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *   19 Mar 2002 Harald Welte <laforge@gnumonks.org>:
 *   		 - Port to newnat infrastructure
 */

#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
16
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
L
Linus Torvalds 已提交
17 18 19
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
20 21 22 23 24
#else
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h>
#endif
L
Linus Torvalds 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_helper.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
MODULE_DESCRIPTION("iptables helper match module");

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

38
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
L
Linus Torvalds 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static int
match(const struct sk_buff *skb,
      const struct net_device *in,
      const struct net_device *out,
      const void *matchinfo,
      int offset,
      int *hotdrop)
{
	const struct ipt_helper_info *info = matchinfo;
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	int ret = info->invert;
	
	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
	if (!ct) {
		DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
		return ret;
	}

	if (!ct->master) {
		DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
		return ret;
	}

P
Patrick McHardy 已提交
63
	read_lock_bh(&ip_conntrack_lock);
L
Linus Torvalds 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
	if (!ct->master->helper) {
		DEBUGP("ipt_helper: master ct %p has no helper\n", 
			exp->expectant);
		goto out_unlock;
	}

	DEBUGP("master's name = %s , info->name = %s\n", 
		ct->master->helper->name, info->name);

	if (info->name[0] == '\0')
		ret ^= 1;
	else
		ret ^= !strncmp(ct->master->helper->name, info->name, 
		                strlen(ct->master->helper->name));
out_unlock:
P
Patrick McHardy 已提交
79
	read_unlock_bh(&ip_conntrack_lock);
L
Linus Torvalds 已提交
80 81 82
	return ret;
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
#else /* CONFIG_IP_NF_CONNTRACK */

static int
match(const struct sk_buff *skb,
      const struct net_device *in,
      const struct net_device *out,
      const void *matchinfo,
      int offset,
      int *hotdrop)
{
	const struct ipt_helper_info *info = matchinfo;
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	int ret = info->invert;
	
	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
	if (!ct) {
		DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
		return ret;
	}

	if (!ct->master) {
		DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
		return ret;
	}

	read_lock_bh(&nf_conntrack_lock);
	if (!ct->master->helper) {
		DEBUGP("ipt_helper: master ct %p has no helper\n", 
			exp->expectant);
		goto out_unlock;
	}

	DEBUGP("master's name = %s , info->name = %s\n", 
		ct->master->helper->name, info->name);

	if (info->name[0] == '\0')
		ret ^= 1;
	else
		ret ^= !strncmp(ct->master->helper->name, info->name, 
		                strlen(ct->master->helper->name));
out_unlock:
	read_unlock_bh(&nf_conntrack_lock);
	return ret;
}
#endif

L
Linus Torvalds 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static int check(const char *tablename,
		 const struct ipt_ip *ip,
		 void *matchinfo,
		 unsigned int matchsize,
		 unsigned int hook_mask)
{
	struct ipt_helper_info *info = matchinfo;

	info->name[29] = '\0';

	/* verify size */
	if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
		return 0;

	return 1;
}

static struct ipt_match helper_match = {
	.name		= "helper",
	.match		= &match,
	.checkentry	= &check,
	.me		= THIS_MODULE,
};

static int __init init(void)
{
	need_ip_conntrack();
	return ipt_register_match(&helper_match);
}

static void __exit fini(void)
{
	ipt_unregister_match(&helper_match);
}

module_init(init);
module_exit(fini);