libip6t_REJECT.c revision c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbe
1c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Shared library add-on to iptables to add customized REJECT support.
2c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte *
3c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte * (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte *
5c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte * ported to IPv6 by Harald Welte <laforge@gnumonks.org>
6c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte *
7c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte */
8c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <stdio.h>
9c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <string.h>
10c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <stdlib.h>
11c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <getopt.h>
12c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <ip6tables.h>
13c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <linux/netfilter_ipv6/ip6_tables.h>
14c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#include <linux/netfilter_ipv6/ip6t_REJECT.h>
15c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
16c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestruct reject_names {
17c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	const char *name;
18c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	const char *alias;
19c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	enum ip6t_reject_with with;
20c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	const char *desc;
21c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte};
22c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
23c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic const struct reject_names reject_table[] = {
24c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"icmp6-no-route", "no-route",
25c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_ICMP6_NO_ROUTE, "ICMPv6 no route"},
26c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"icmp6-adm-prohibited", "adm-prohibited",
27c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_ICMP6_ADM_PROHIBITED, "ICMPv6 administratively prohibited"},
28c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#if 0
29c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"icmp6-not-neighbor", "not-neighbor"},
30c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_ICMP6_NOT_NEIGHBOR, "ICMPv6 not a neighbor"},
31c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte#endif
32c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"icmp6-addr-unreachable", "addr-unreach",
33c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_ICMP6_ADDR_UNREACH, "ICMPv6 address unreachable"},
34c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"icmp6-port-unreachable", "port-unreach",
35c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"},
36c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{"tcp-reset", "tcp-reset",
37c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		IP6T_TCP_RESET, "TCP RST packet"}
38c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte};
39c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
40c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void
41c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welteprint_reject_types()
42c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
43c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	unsigned int i;
44c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
45c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	printf("Valid reject types:\n");
46c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
47c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
48c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
49c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		printf("    %-25s\talias\n", reject_table[i].alias);
50c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	}
51c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	printf("\n");
52c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
53c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
54c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Saves the union ipt_targinfo in parsable form to stdout. */
55c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
56c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Function which prints out usage message. */
57c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void
58c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltehelp(void)
59c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
60c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	printf(
61c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte"REJECT options:\n"
62c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte"--reject-with type              drop input packet and send back\n"
63c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte"                                a reply packet according to type:\n");
64c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
65c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	print_reject_types();
66c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
67c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
68c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic struct option opts[] = {
69c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{ "reject-with", 1, 0, '1' },
70c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	{ 0 }
71c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte};
72c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
73c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Allocate and initialize the target. */
74c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void
75c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welteinit(struct ip6t_entry_target *t, unsigned int *nfcache)
76c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
77c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	struct ip6t_reject_info *reject = (struct ip6t_reject_info *)t->data;
78c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
79c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	/* default */
80c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	reject->with = IP6T_ICMP6_PORT_UNREACH;
81c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
82c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	/* Can't cache this */
83c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	*nfcache |= NFC_UNKNOWN;
84c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
85c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
86c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Function which parses command options; returns true if it
87c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte   ate an option */
88c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic int
89c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welteparse(int c, char **argv, int invert, unsigned int *flags,
90c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte      const struct ip6t_entry *entry,
91c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte      struct ip6t_entry_target **target)
92c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
93c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	struct ip6t_reject_info *reject =
94c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		(struct ip6t_reject_info *)(*target)->data;
95c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
96c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	unsigned int i;
97c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
98c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	switch(c) {
99c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	case '1':
100c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		if (check_inverse(optarg, &invert))
101c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			exit_error(PARAMETER_PROBLEM,
102c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte				   "Unexpected `!' after --reject-with");
103c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		for (i = 0; i < limit; i++) {
104c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
105c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			    || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
106c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte				reject->with = reject_table[i].with;
107c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte				return 1;
108c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			}
109c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		}
110c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
111c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	default:
112c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		/* Fall through */
113c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	}
114c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	return 0;
115c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
116c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
117c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Final check; nothing. */
118c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void final_check(unsigned int flags)
119c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
120c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
121c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
122c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Prints out ipt_reject_info. */
123c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void
124c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welteprint(const struct ip6t_ip6 *ip,
125c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte      const struct ip6t_entry_target *target,
126c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte      int numeric)
127c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
128c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	const struct ip6t_reject_info *reject
129c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		= (const struct ip6t_reject_info *)target->data;
130c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	unsigned int i;
131c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
132c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
133c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		if (reject_table[i].with == reject->with)
134c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			break;
135c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	}
136c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	printf("reject-with %s ", reject_table[i].name);
137c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
138c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
139c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte/* Saves ipt_reject in parsable form to stdout. */
140c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestatic void save(const struct ip6t_ip6 *ip,
141c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		 const struct ip6t_entry_target *target)
142c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
143c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	const struct ip6t_reject_info *reject
144c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		= (const struct ip6t_reject_info *)target->data;
145c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	unsigned int i;
146c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
147c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++)
148c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte		if (reject_table[i].with == reject->with)
149c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte			break;
150c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
151c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	printf("--reject-with %s ", reject_table[i].name);
152c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
153c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
154c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltestruct ip6tables_target reject
155c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte= { NULL,
156c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    "REJECT",
157c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    NETFILTER_VERSION,
158c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    IP6T_ALIGN(sizeof(struct ip6t_reject_info)),
159c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    IP6T_ALIGN(sizeof(struct ip6t_reject_info)),
160c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &help,
161c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &init,
162c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &parse,
163c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &final_check,
164c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &print,
165c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    &save,
166c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte    opts
167c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte};
168c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte
169c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Weltevoid _init(void)
170c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte{
171c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte	register_target6(&reject);
172c8af1fd0a9b8e7e39626c7d66ade0ddc93f25fbeHarald Welte}
173