libipt_REJECT.c revision bf97128c7262f17a02fec41cdae75b472ba77f88
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Shared library add-on to iptables to add customized REJECT support.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <stdio.h>
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string.h>
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <stdlib.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <getopt.h>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <xtables.h>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <linux/netfilter_ipv4/ipt_REJECT.h>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <linux/version.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* If we are compiling against a kernel that does not support
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * IPT_ICMP_ADMIN_PROHIBITED, we are emulating it.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The result will be a plain DROP of the packet instead of
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * reject. -- Maciej Soltysiak <solt@dns.toxicfilms.tv>
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef IPT_ICMP_ADMIN_PROHIBITED
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define IPT_ICMP_ADMIN_PROHIBITED	IPT_TCP_RESET + 1
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct reject_names {
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	const char *name;
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	const char *alias;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	enum ipt_reject_with with;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const char *desc;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct reject_names reject_table[] = {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"icmp-net-unreachable", "net-unreach",
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"icmp-host-unreachable", "host-unreach",
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"icmp-proto-unreachable", "proto-unreach",
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"icmp-port-unreachable", "port-unreach",
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"echo-reply", "echoreply",
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{"icmp-net-prohibited", "net-prohib",
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{"icmp-host-prohibited", "host-prohib",
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{"tcp-reset", "tcp-rst",
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	 IPT_TCP_RESET, "TCP RST packet"},
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{"icmp-admin-prohibited", "admin-prohib",
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)print_reject_types(void)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	unsigned int i;
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	printf("Valid reject types:\n");
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		printf("    %-25s\talias\n", reject_table[i].alias);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf("\n");
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void REJECT_help(void)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"REJECT target options:\n"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"--reject-with type              drop input packet and send back\n"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"                                a reply packet according to type:\n");
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print_reject_types();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct option REJECT_opts[] = {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ "reject-with", 1, NULL, '1' },
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ .name = NULL }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void REJECT_init(struct xt_entry_target *t)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* default */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	reject->with = IPT_ICMP_PORT_UNREACHABLE;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int REJECT_parse(int c, char **argv, int invert, unsigned int *flags,
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const void *entry, struct xt_entry_target **target)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	static const unsigned int limit = ARRAY_SIZE(reject_table);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int i;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	switch(c) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case '1':
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			xtables_error(PARAMETER_PROBLEM,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   "Unexpected `!' after --reject-with");
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		for (i = 0; i < limit; i++) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				reject->with = reject_table[i].with;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				return 1;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* This due to be dropped late in 2.4 pre-release cycle --RR */
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    || strncasecmp("echoreply", optarg, strlen(optarg)) == 0)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			fprintf(stderr, "--reject-with echo-reply no longer"
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				" supported\n");
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xtables_error(PARAMETER_PROBLEM, "unknown reject type \"%s\"", optarg);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	default:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Fall through */
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void REJECT_print(const void *ip, const struct xt_entry_target *target,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int numeric)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const struct ipt_reject_info *reject
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		= (const struct ipt_reject_info *)target->data;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	unsigned int i;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (reject_table[i].with == reject->with)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf("reject-with %s ", reject_table[i].name);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void REJECT_save(const void *ip, const struct xt_entry_target *target)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const struct ipt_reject_info *reject
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		= (const struct ipt_reject_info *)target->data;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int i;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (reject_table[i].with == reject->with)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf("--reject-with %s ", reject_table[i].name);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct xtables_target reject_tg_reg = {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.name		= "REJECT",
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.version	= XTABLES_VERSION,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.family		= NFPROTO_IPV4,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.size		= XT_ALIGN(sizeof(struct ipt_reject_info)),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.userspacesize	= XT_ALIGN(sizeof(struct ipt_reject_info)),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.help		= REJECT_help,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.init		= REJECT_init,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.parse		= REJECT_parse,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.print		= REJECT_print,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.save		= REJECT_save,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	.extra_opts	= REJECT_opts,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void _init(void)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xtables_register_target(&reject_tg_reg);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)