libipt_REJECT.c revision b313d8f3f78c62cce930728bc9163ecf942c22e8
1/* Shared library add-on to iptables to add customized REJECT support.
2 *
3 * (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4 */
5#include <stdio.h>
6#include <string.h>
7#include <xtables.h>
8#include <linux/netfilter_ipv4/ipt_REJECT.h>
9#include <linux/version.h>
10
11/* If we are compiling against a kernel that does not support
12 * IPT_ICMP_ADMIN_PROHIBITED, we are emulating it.
13 * The result will be a plain DROP of the packet instead of
14 * reject. -- Maciej Soltysiak <solt@dns.toxicfilms.tv>
15 */
16#ifndef IPT_ICMP_ADMIN_PROHIBITED
17#define IPT_ICMP_ADMIN_PROHIBITED	IPT_TCP_RESET + 1
18#endif
19
20struct reject_names {
21	const char *name;
22	const char *alias;
23	enum ipt_reject_with with;
24	const char *desc;
25};
26
27enum {
28	O_REJECT_WITH = 0,
29};
30
31static const struct reject_names reject_table[] = {
32	{"icmp-net-unreachable", "net-unreach",
33		IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
34	{"icmp-host-unreachable", "host-unreach",
35		IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
36	{"icmp-proto-unreachable", "proto-unreach",
37		IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
38	{"icmp-port-unreachable", "port-unreach",
39		IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
40#if 0
41	{"echo-reply", "echoreply",
42	 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
43#endif
44	{"icmp-net-prohibited", "net-prohib",
45	 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
46	{"icmp-host-prohibited", "host-prohib",
47	 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
48	{"tcp-reset", "tcp-rst",
49	 IPT_TCP_RESET, "TCP RST packet"},
50	{"icmp-admin-prohibited", "admin-prohib",
51	 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
52};
53
54static void
55print_reject_types(void)
56{
57	unsigned int i;
58
59	printf("Valid reject types:\n");
60
61	for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
62		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
63		printf("    %-25s\talias\n", reject_table[i].alias);
64	}
65	printf("\n");
66}
67
68static void REJECT_help(void)
69{
70	printf(
71"REJECT target options:\n"
72"--reject-with type              drop input packet and send back\n"
73"                                a reply packet according to type:\n");
74
75	print_reject_types();
76
77	printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
78}
79
80static const struct xt_option_entry REJECT_opts[] = {
81	{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
82	XTOPT_TABLEEND,
83};
84
85static void REJECT_init(struct xt_entry_target *t)
86{
87	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
88
89	/* default */
90	reject->with = IPT_ICMP_PORT_UNREACHABLE;
91
92}
93
94static void REJECT_parse(struct xt_option_call *cb)
95{
96	struct ipt_reject_info *reject = cb->data;
97	unsigned int i;
98
99	xtables_option_parse(cb);
100	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
101		if (strncasecmp(reject_table[i].name,
102		      cb->arg, strlen(cb->arg)) == 0 ||
103		    strncasecmp(reject_table[i].alias,
104		      cb->arg, strlen(cb->arg)) == 0) {
105			reject->with = reject_table[i].with;
106			return;
107		}
108	/* This due to be dropped late in 2.4 pre-release cycle --RR */
109	if (strncasecmp("echo-reply", cb->arg, strlen(cb->arg)) == 0 ||
110	    strncasecmp("echoreply", cb->arg, strlen(cb->arg)) == 0)
111		fprintf(stderr, "--reject-with echo-reply no longer"
112			" supported\n");
113	xtables_error(PARAMETER_PROBLEM,
114		"unknown reject type \"%s\"", cb->arg);
115}
116
117static void REJECT_print(const void *ip, const struct xt_entry_target *target,
118                         int numeric)
119{
120	const struct ipt_reject_info *reject
121		= (const struct ipt_reject_info *)target->data;
122	unsigned int i;
123
124	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
125		if (reject_table[i].with == reject->with)
126			break;
127	printf(" reject-with %s", reject_table[i].name);
128}
129
130static void REJECT_save(const void *ip, const struct xt_entry_target *target)
131{
132	const struct ipt_reject_info *reject
133		= (const struct ipt_reject_info *)target->data;
134	unsigned int i;
135
136	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
137		if (reject_table[i].with == reject->with)
138			break;
139
140	printf(" --reject-with %s", reject_table[i].name);
141}
142
143static struct xtables_target reject_tg_reg = {
144	.name		= "REJECT",
145	.version	= XTABLES_VERSION,
146	.family		= NFPROTO_IPV4,
147	.size		= XT_ALIGN(sizeof(struct ipt_reject_info)),
148	.userspacesize	= XT_ALIGN(sizeof(struct ipt_reject_info)),
149	.help		= REJECT_help,
150	.init		= REJECT_init,
151	.print		= REJECT_print,
152	.save		= REJECT_save,
153	.x6_parse	= REJECT_parse,
154	.x6_options	= REJECT_opts,
155};
156
157void _init(void)
158{
159	xtables_register_target(&reject_tg_reg);
160}
161