libipt_REJECT.c revision 97b3fdef41a009e54a0595b78c57f93b63f92469
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 <stdlib.h>
8#include <getopt.h>
9#include <iptables.h>
10#include <linux/netfilter_ipv4/ip_tables.h>
11#include <linux/netfilter_ipv4/ipt_REJECT.h>
12
13struct reject_names {
14	const char *name;
15	const char *alias;
16	enum ipt_reject_with with;
17	const char *desc;
18};
19
20static const struct reject_names reject_table[] = {
21	{"icmp-net-unreachable", "net-unreach",
22		IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
23	{"icmp-host-unreachable", "host-unreach",
24		IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
25	{"icmp-port-unreachable", "port-unreach",
26		IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
27	{"icmp-proto-unreachable", "proto-unreach",
28		IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
29#if 0
30	{"echo-reply", "echoreply",
31	 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
32#endif
33	{"icmp-net-prohibited", "net-prohib",
34	 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
35	{"icmp-host-prohibited", "host-prohib",
36	 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
37	{"tcp-reset", "tcp-reset",
38	 IPT_TCP_RESET, "TCP RST packet"}
39};
40
41static void
42print_reject_types()
43{
44	unsigned int i;
45
46	printf("Valid reject types:\n");
47
48	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
49		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
50		printf("    %-25s\talias\n", reject_table[i].alias);
51	}
52	printf("\n");
53}
54
55/* Saves the union ipt_targinfo in parsable form to stdout. */
56
57/* Function which prints out usage message. */
58static void
59help(void)
60{
61	printf(
62"REJECT options:\n"
63"--reject-with type              drop input packet and send back\n"
64"                                a reply packet according to type:\n");
65
66	print_reject_types();
67}
68
69static struct option opts[] = {
70	{ "reject-with", 1, 0, '1' },
71	{ 0 }
72};
73
74/* Allocate and initialize the target. */
75static void
76init(struct ipt_entry_target *t, unsigned int *nfcache)
77{
78	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
79
80	/* default */
81	reject->with = IPT_ICMP_PORT_UNREACHABLE;
82
83	/* Can't cache this */
84	*nfcache |= NFC_UNKNOWN;
85}
86
87/* Function which parses command options; returns true if it
88   ate an option */
89static int
90parse(int c, char **argv, int invert, unsigned int *flags,
91      const struct ipt_entry *entry,
92      struct ipt_entry_target **target)
93{
94	struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
95	unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
96	unsigned int i;
97
98	switch(c) {
99	case '1':
100		if (check_inverse(optarg, &invert))
101			exit_error(PARAMETER_PROBLEM,
102				   "Unexpected `!' after --reject-with");
103		for (i = 0; i < limit; i++) {
104			if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
105			    || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
106				reject->with = reject_table[i].with;
107				return 1;
108			}
109		}
110		/* This due to be dropped late in 2.4 pre-release cycle --RR */
111		if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0
112		    || strncasecmp("echoreply", optarg, strlen(optarg)) == 0)
113			fprintf(stderr, "--reject-with echo-reply no longer"
114				" supported\n");
115		exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
116	default:
117		/* Fall through */
118	}
119	return 0;
120}
121
122/* Final check; nothing. */
123static void final_check(unsigned int flags)
124{
125}
126
127/* Prints out ipt_reject_info. */
128static void
129print(const struct ipt_ip *ip,
130      const struct ipt_entry_target *target,
131      int numeric)
132{
133	const struct ipt_reject_info *reject
134		= (const struct ipt_reject_info *)target->data;
135	unsigned int i;
136
137	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
138		if (reject_table[i].with == reject->with)
139			break;
140	}
141	printf("reject-with %s ", reject_table[i].name);
142}
143
144/* Saves ipt_reject in parsable form to stdout. */
145static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
146{
147	const struct ipt_reject_info *reject
148		= (const struct ipt_reject_info *)target->data;
149	unsigned int i;
150
151	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++)
152		if (reject_table[i].with == reject->with)
153			break;
154
155	printf("--reject-with %s ", reject_table[i].name);
156}
157
158struct iptables_target reject
159= { NULL,
160    "REJECT",
161    NETFILTER_VERSION,
162    IPT_ALIGN(sizeof(struct ipt_reject_info)),
163    IPT_ALIGN(sizeof(struct ipt_reject_info)),
164    &help,
165    &init,
166    &parse,
167    &final_check,
168    &print,
169    &save,
170    opts
171};
172
173void _init(void)
174{
175	register_target(&reject);
176}
177