libipt_REJECT.c revision 7e53bf9c2a697abdb6f1385557338423a86612a3
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	{"tcp-reset", "rst",
30		IPT_TCP_RESET, "for TCP only: faked TCP RST"},
31	{"echo-reply", "echoreply",
32		IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
33};
34
35static void
36print_reject_types()
37{
38	unsigned int i;
39
40	printf("Valid reject types:\n");
41
42	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
43		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
44		printf("    %-25s\talias\n", reject_table[i].alias);
45	}
46	printf("\n");
47}
48
49/* Saves the union ipt_targinfo in parsable form to stdout. */
50
51/* Function which prints out usage message. */
52static void
53help(void)
54{
55	printf(
56"REJECT options:\n"
57"--reject-with type              drop input packet and send back\n"
58"                                a reply packet according to type:\n");
59
60	print_reject_types();
61}
62
63static struct option opts[] = {
64	{ "reject-with", 1, 0, '1' },
65	{ 0 }
66};
67
68/* Allocate and initialize the target. */
69static void
70init(struct ipt_entry_target *t, unsigned int *nfcache)
71{
72	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
73
74	/* default */
75	reject->with = IPT_ICMP_PORT_UNREACHABLE;
76
77	/* Can't cache this */
78	*nfcache |= NFC_UNKNOWN;
79}
80
81/* Function which parses command options; returns true if it
82   ate an option */
83static int
84parse(int c, char **argv, int invert, unsigned int *flags,
85      const struct ipt_entry *entry,
86      struct ipt_entry_target **target)
87{
88	struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
89	unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
90	unsigned int i;
91
92	switch(c) {
93	case '1':
94		if (check_inverse(optarg, &invert))
95			exit_error(PARAMETER_PROBLEM,
96				   "Unexpected `!' after --reject-with");
97		for (i = 0; i < limit; i++) {
98			if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
99			    || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
100				reject->with = reject_table[i].with;
101				return 1;
102			}
103		}
104		exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
105	default:
106		/* Fall through */
107	}
108	return 0;
109}
110
111/* Final check; nothing. */
112static void final_check(unsigned int flags)
113{
114}
115
116/* Prints out ipt_reject_info. */
117static void
118print(const struct ipt_ip *ip,
119      const struct ipt_entry_target *target,
120      int numeric)
121{
122	const struct ipt_reject_info *reject
123		= (const struct ipt_reject_info *)target->data;
124	unsigned int i;
125
126	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
127		if (reject_table[i].with == reject->with)
128			break;
129	}
130	printf("reject-with %s ", reject_table[i].name);
131}
132
133/* Saves ipt_reject in parsable form to stdout. */
134static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
135{
136	const struct ipt_reject_info *reject
137		= (const struct ipt_reject_info *)target->data;
138
139	printf("--reject-with %s ", reject_table[reject->with].name);
140}
141
142struct iptables_target reject
143= { NULL,
144    "REJECT",
145    NETFILTER_VERSION,
146    sizeof(struct ipt_reject_info),
147    &help,
148    &init,
149    &parse,
150    &final_check,
151    &print,
152    &save,
153    opts
154};
155
156void _init(void)
157{
158	register_target(&reject);
159}
160