ipt_REJECT.c 3.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11
/*
 * This is a module which is used for rejecting packets.
 */

/* (C) 1999-2001 Paul `Rusty' Russell
 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
 *
 * 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.
 */
12
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
L
Linus Torvalds 已提交
13 14
#include <linux/module.h>
#include <linux/skbuff.h>
15
#include <linux/slab.h>
L
Linus Torvalds 已提交
16 17 18 19
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/icmp.h>
20
#include <linux/netfilter/x_tables.h>
L
Linus Torvalds 已提交
21 22
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_REJECT.h>
23
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
L
Linus Torvalds 已提交
24 25 26
#include <linux/netfilter_bridge.h>
#endif

27 28
#include <net/netfilter/ipv4/nf_reject.h>

L
Linus Torvalds 已提交
29 30
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
31
MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
L
Linus Torvalds 已提交
32

33
static unsigned int
34
reject_tg(struct sk_buff *skb, const struct xt_action_param *par)
L
Linus Torvalds 已提交
35
{
36
	const struct ipt_reject_info *reject = par->targinfo;
37
	int hook = par->hooknum;
L
Linus Torvalds 已提交
38

39 40
	switch (reject->with) {
	case IPT_ICMP_NET_UNREACHABLE:
41
		nf_send_unreach(skb, ICMP_NET_UNREACH, hook);
42 43
		break;
	case IPT_ICMP_HOST_UNREACHABLE:
44
		nf_send_unreach(skb, ICMP_HOST_UNREACH, hook);
45 46
		break;
	case IPT_ICMP_PROT_UNREACHABLE:
47
		nf_send_unreach(skb, ICMP_PROT_UNREACH, hook);
48 49
		break;
	case IPT_ICMP_PORT_UNREACHABLE:
50
		nf_send_unreach(skb, ICMP_PORT_UNREACH, hook);
51 52
		break;
	case IPT_ICMP_NET_PROHIBITED:
53
		nf_send_unreach(skb, ICMP_NET_ANO, hook);
54
		break;
L
Linus Torvalds 已提交
55
	case IPT_ICMP_HOST_PROHIBITED:
56
		nf_send_unreach(skb, ICMP_HOST_ANO, hook);
57 58
		break;
	case IPT_ICMP_ADMIN_PROHIBITED:
59
		nf_send_unreach(skb, ICMP_PKT_FILTERED, hook);
L
Linus Torvalds 已提交
60 61
		break;
	case IPT_TCP_RESET:
62
		nf_send_reset(par->net, skb, hook);
L
Linus Torvalds 已提交
63 64 65 66 67 68 69 70
	case IPT_ICMP_ECHOREPLY:
		/* Doesn't happen. */
		break;
	}

	return NF_DROP;
}

71
static int reject_tg_check(const struct xt_tgchk_param *par)
L
Linus Torvalds 已提交
72
{
73 74
	const struct ipt_reject_info *rejinfo = par->targinfo;
	const struct ipt_entry *e = par->entryinfo;
L
Linus Torvalds 已提交
75 76

	if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
77
		pr_info("ECHOREPLY no longer supported.\n");
78
		return -EINVAL;
L
Linus Torvalds 已提交
79 80
	} else if (rejinfo->with == IPT_TCP_RESET) {
		/* Must specify that it's a TCP packet */
81 82
		if (e->ip.proto != IPPROTO_TCP ||
		    (e->ip.invflags & XT_INV_PROTO)) {
83
			pr_info("TCP_RESET invalid for non-tcp\n");
84
			return -EINVAL;
L
Linus Torvalds 已提交
85 86
		}
	}
87
	return 0;
L
Linus Torvalds 已提交
88 89
}

90
static struct xt_target reject_tg_reg __read_mostly = {
L
Linus Torvalds 已提交
91
	.name		= "REJECT",
92
	.family		= NFPROTO_IPV4,
93
	.target		= reject_tg,
94 95
	.targetsize	= sizeof(struct ipt_reject_info),
	.table		= "filter",
96 97
	.hooks		= (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
			  (1 << NF_INET_LOCAL_OUT),
98
	.checkentry	= reject_tg_check,
L
Linus Torvalds 已提交
99 100 101
	.me		= THIS_MODULE,
};

102
static int __init reject_tg_init(void)
L
Linus Torvalds 已提交
103
{
104
	return xt_register_target(&reject_tg_reg);
L
Linus Torvalds 已提交
105 106
}

107
static void __exit reject_tg_exit(void)
L
Linus Torvalds 已提交
108
{
109
	xt_unregister_target(&reject_tg_reg);
L
Linus Torvalds 已提交
110 111
}

112 113
module_init(reject_tg_init);
module_exit(reject_tg_exit);