libipt_REJECT.c revision 193df8ee3507f0c02762c88a16916c4ea950bd99
121e463b2bf864671a87ebe386cb100ef9349a540Nate Begeman/* Shared library add-on to iptables to add customized REJECT support.
27c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner *
37c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner * (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
47c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner */
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner#include <stdio.h>
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner#include <string.h>
77c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <stdlib.h>
87c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <getopt.h>
97c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <iptables.h>
107c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <linux/netfilter_ipv4/ip_tables.h>
117c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <linux/netfilter_ipv4/ipt_REJECT.h>
127c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner#include <linux/version.h>
137c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
147c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner/* If we are compiling against a kernel that does not support
157c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner * IPT_ICMP_ADMIN_PROHIBITED, we are emulating it.
167c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner * The result will be a plain DROP of the packet instead of
177c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner * reject. -- Maciej Soltysiak <solt@dns.toxicfilms.tv>
182668959b8879097db368aec7d76c455260abc75bChris Lattner */
19331d1bc5dfe1be9090e29f9af9579888a63a9a79Chris Lattner#ifndef IPT_ICMP_ADMIN_PROHIBITED
2079aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#define IPT_ICMP_ADMIN_PROHIBITED	IPT_TCP_RESET + 1
21a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#endif
227c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattner
237c5a3d390a463fb50a6eee7ae3174817925e6d28Chris Lattnerstruct reject_names {
240bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner	const char *name;
250bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner	const char *alias;
263c983c3dc19bb83807f978c04737b4572be90a93Nate Begeman	enum ipt_reject_with with;
270ba2bcfcc3149a25d08aa8aa00fb6c34a4e25bddDan Gohman	const char *desc;
280bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner};
290bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner
300bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattnerstatic const struct reject_names reject_table[] = {
310bbea954331b8f08afa5b094dfb0841829c70eaaChris Lattner	{"icmp-net-unreachable", "net-unreach",
3295771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
33c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman	{"icmp-host-unreachable", "host-unreach",
34c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman		IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
35c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman	{"icmp-proto-unreachable", "proto-unreach",
36c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman		IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
3795771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson	{"icmp-port-unreachable", "port-unreach",
3895771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
39c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman#if 0
40c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman	{"echo-reply", "echoreply",
41c09eeec0ebc378644bafd04916e5efafa7d98152Nate Begeman	 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
4295771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson#endif
435126984b1da4bda0e93961da07e883699f1f2d57Chris Lattner	{"icmp-net-prohibited", "net-prohib",
44c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman	 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
455126984b1da4bda0e93961da07e883699f1f2d57Chris Lattner	{"icmp-host-prohibited", "host-prohib",
4695771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson	 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
47993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman	{"tcp-reset", "tcp-rst",
48993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman	 IPT_TCP_RESET, "TCP RST packet"},
49993aeb2ed93f99faf1438f1b67cd922989306828Nate Begeman	{"icmp-admin-prohibited", "admin-prohib",
5095771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson	 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
51f1d0b2bedaa065972a5ba17259055c1176cd1497Chris Lattner};
52f1d0b2bedaa065972a5ba17259055c1176cd1497Chris Lattner
53f1d0b2bedaa065972a5ba17259055c1176cd1497Chris Lattnerstatic void
5495771afbfd604ad003fa3723cac66c9370fed55dOwen Andersonprint_reject_types()
55860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner{
56860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner	unsigned int i;
57860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner
58860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner	printf("Valid reject types:\n");
59860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner
60860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
6195771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
626b16eff207f99bbde3c0f7340452a5287218772cTilmann Scheller		printf("    %-25s\talias\n", reject_table[i].alias);
636b16eff207f99bbde3c0f7340452a5287218772cTilmann Scheller	}
643a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller	printf("\n");
653a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller}
663a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller
673a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller/* Saves the union ipt_targinfo in parsable form to stdout. */
683a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller
693a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller/* Function which prints out usage message. */
703a84dae654630a89a91a73807201b6067c4774ecTilmann Schellerstatic void
713a84dae654630a89a91a73807201b6067c4774ecTilmann Schellerhelp(void)
723a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller{
733a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller	printf(
743a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller"REJECT options:\n"
753a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller"--reject-with type              drop input packet and send back\n"
763a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller"                                a reply packet according to type:\n");
773a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller
783a84dae654630a89a91a73807201b6067c4774ecTilmann Scheller	print_reject_types();
792f616bff7ef1e2e08d6d23c2a8b42ec2bfebb173Jim Laskey
802f616bff7ef1e2e08d6d23c2a8b42ec2bfebb173Jim Laskey	printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
812f616bff7ef1e2e08d6d23c2a8b42ec2bfebb173Jim Laskey}
822f616bff7ef1e2e08d6d23c2a8b42ec2bfebb173Jim Laskey
8395771afbfd604ad003fa3723cac66c9370fed55dOwen Andersonstatic struct option opts[] = {
84860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner	{ "reject-with", 1, 0, '1' },
85860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner	{ 0 }
86860e8862c1fbd3b261da4a64a8c0096f9f373681Chris Lattner};
8795771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson
884172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner/* Allocate and initialize the target. */
894172b10ca1adfc1026428e5f522aaab98bd939adChris Lattnerstatic void
904172b10ca1adfc1026428e5f522aaab98bd939adChris Lattnerinit(struct xt_entry_target *t, unsigned int *nfcache)
914172b10ca1adfc1026428e5f522aaab98bd939adChris Lattner{
9295771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
93ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner
94ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner	/* default */
95ecfe55e65b6a72fddd543c42f2e2df4c96c647baChris Lattner	reject->with = IPT_ICMP_PORT_UNREACHABLE;
969e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman
97c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner}
985b00ceaeeabff8c25abb09926343c3fcb06053d8Hal Finkel
995b00ceaeeabff8c25abb09926343c3fcb06053d8Hal Finkel/* Function which parses command options; returns true if it
1005b00ceaeeabff8c25abb09926343c3fcb06053d8Hal Finkel   ate an option */
10195771afbfd604ad003fa3723cac66c9370fed55dOwen Andersonstatic int
1026b16eff207f99bbde3c0f7340452a5287218772cTilmann Schellerparse(int c, char **argv, int invert, unsigned int *flags,
1036b16eff207f99bbde3c0f7340452a5287218772cTilmann Scheller      const struct ipt_entry *entry,
1046b16eff207f99bbde3c0f7340452a5287218772cTilmann Scheller      struct xt_entry_target **target)
105c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner{
106c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner	struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
107c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner	unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
10895771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson	unsigned int i;
109c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner
110c703a8fbf8653ac8302ae368391a4954c307ca2cChris Lattner	switch(c) {
1112a9ddfb903ae3baede7282348afae1f750905248Tilmann Scheller	case '1':
11295771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		if (check_inverse(optarg, &invert, NULL, 0))
1139e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman			exit_error(PARAMETER_PROBLEM,
1149e4dd9dfc97f3930f58ca6e47bebbd8eb5cdd8a1Nate Begeman				   "Unexpected `!' after --reject-with");
11595771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		for (i = 0; i < limit; i++) {
1165f07d5224ddc32f405d7e19de8e58e91ab2816bcDale Johannesen			if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
1175f07d5224ddc32f405d7e19de8e58e91ab2816bcDale Johannesen			    || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
1185f07d5224ddc32f405d7e19de8e58e91ab2816bcDale Johannesen				reject->with = reject_table[i].with;
1195f07d5224ddc32f405d7e19de8e58e91ab2816bcDale Johannesen				return 1;
1206d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner			}
121a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner		}
122a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner		/* This due to be dropped late in 2.4 pre-release cycle --RR */
123a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner		if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0
124a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner		    || strncasecmp("echoreply", optarg, strlen(optarg)) == 0)
125a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner			fprintf(stderr, "--reject-with echo-reply no longer"
126a17b1557ad705c56c41624e6841e19093ed31f21Chris Lattner				" supported\n");
12795771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
1286d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner	default:
12995771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson		/* Fall through */
1306d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner		break;
1316d92caddc4aa5fc946b294259e00cc35536e61e8Chris Lattner	}
13290564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner	return 0;
13395771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson}
13490564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner
13590564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner/* Final check; nothing. */
13690564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattnerstatic void final_check(unsigned int flags)
13790564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner{
13890564f26d17701e11effa2f4e0fb9a18d8a91274Chris Lattner}
139d9989384592a3bd9dd374470a723ca8303071a2dChris Lattner
14095771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson/* Prints out ipt_reject_info. */
1416eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesenstatic void
1426eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesenprint(const struct ipt_ip *ip,
1436eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen      const struct xt_entry_target *target,
1446eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen      int numeric)
1456eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen{
1466eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen	const struct ipt_reject_info *reject
1476eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen		= (const struct ipt_reject_info *)target->data;
1486eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen	unsigned int i;
1496eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen
1506eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
1516eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen		if (reject_table[i].with == reject->with)
1526eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen			break;
1536eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen	}
1546eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen	printf("reject-with %s ", reject_table[i].name);
15595771afbfd604ad003fa3723cac66c9370fed55dOwen Anderson}
1566eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen
1576eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen/* Saves ipt_reject in parsable form to stdout. */
1586eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesenstatic void save(const struct ipt_ip *ip, const struct xt_entry_target *target)
1596eaeff29b8a6990107735f7e5f5e49da38f56223Dale Johannesen{
16054fc97dcdc0ab747f49bd09c5a877bfd2a00e364Evan Cheng	const struct ipt_reject_info *reject
16154fc97dcdc0ab747f49bd09c5a877bfd2a00e364Evan Cheng		= (const struct ipt_reject_info *)target->data;
1628608f2eff2dab5345243c40d0bca9138f2dce6f1Evan Cheng	unsigned int i;
16354fc97dcdc0ab747f49bd09c5a877bfd2a00e364Evan Cheng
1648608f2eff2dab5345243c40d0bca9138f2dce6f1Evan Cheng	for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++)
16554fc97dcdc0ab747f49bd09c5a877bfd2a00e364Evan Cheng		if (reject_table[i].with == reject->with)
1668608f2eff2dab5345243c40d0bca9138f2dce6f1Evan Cheng			break;
1678608f2eff2dab5345243c40d0bca9138f2dce6f1Evan Cheng
1688608f2eff2dab5345243c40d0bca9138f2dce6f1Evan Cheng	printf("--reject-with %s ", reject_table[i].name);
16954fc97dcdc0ab747f49bd09c5a877bfd2a00e364Evan Cheng}
17030e62c098b5841259f8026df1c5c45c7c1182a38Arnold Schwaighofer
17130e62c098b5841259f8026df1c5c45c7c1182a38Arnold Schwaighoferstatic struct iptables_target reject = {
17230e62c098b5841259f8026df1c5c45c7c1182a38Arnold Schwaighofer	.next		= NULL,
17330e62c098b5841259f8026df1c5c45c7c1182a38Arnold Schwaighofer	.name		= "REJECT",
17430e62c098b5841259f8026df1c5c45c7c1182a38Arnold Schwaighofer	.version	= IPTABLES_VERSION,
175c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman	.size		= IPT_ALIGN(sizeof(struct ipt_reject_info)),
176c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_reject_info)),
17782b3821208286aeb43f603fdac98832bd662dad9Hal Finkel	.help		= &help,
17882b3821208286aeb43f603fdac98832bd662dad9Hal Finkel	.init		= &init,
17982b3821208286aeb43f603fdac98832bd662dad9Hal Finkel	.parse		= &parse,
18082b3821208286aeb43f603fdac98832bd662dad9Hal Finkel	.final_check	= &final_check,
181d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt	.print		= &print,
182d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt	.save		= &save,
183d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt	.extra_opts	= opts
184d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt};
185d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt
186d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidtvoid _init(void)
187d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt{
188d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt	register_target(&reject);
189d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt}
190d7802bf0ddcac16ee910105922492aee86a53e1bBill Schmidt