Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables to add customized REJECT support.
      2  *
      3  * (C) 2000 Jozsef Kadlecsik <kadlec (at) blackhole.kfki.hu>
      4  */
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <xtables.h>
      8 #include <linux/netfilter_ipv4/ipt_REJECT.h>
      9 #include <linux/version.h>
     10 
     11 /* If we are compiling against a kernel that does not support
     12  * IPT_ICMP_ADMIN_PROHIBITED, we are emulating it.
     13  * The result will be a plain DROP of the packet instead of
     14  * reject. -- Maciej Soltysiak <solt (at) dns.toxicfilms.tv>
     15  */
     16 #ifndef IPT_ICMP_ADMIN_PROHIBITED
     17 #define IPT_ICMP_ADMIN_PROHIBITED	IPT_TCP_RESET + 1
     18 #endif
     19 
     20 struct reject_names {
     21 	const char *name;
     22 	const char *alias;
     23 	enum ipt_reject_with with;
     24 	const char *desc;
     25 };
     26 
     27 enum {
     28 	O_REJECT_WITH = 0,
     29 };
     30 
     31 static const struct reject_names reject_table[] = {
     32 	{"icmp-net-unreachable", "net-unreach",
     33 		IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
     34 	{"icmp-host-unreachable", "host-unreach",
     35 		IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
     36 	{"icmp-proto-unreachable", "proto-unreach",
     37 		IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
     38 	{"icmp-port-unreachable", "port-unreach",
     39 		IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
     40 #if 0
     41 	{"echo-reply", "echoreply",
     42 	 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
     43 #endif
     44 	{"icmp-net-prohibited", "net-prohib",
     45 	 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
     46 	{"icmp-host-prohibited", "host-prohib",
     47 	 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
     48 	{"tcp-reset", "tcp-rst",
     49 	 IPT_TCP_RESET, "TCP RST packet"},
     50 	{"icmp-admin-prohibited", "admin-prohib",
     51 	 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
     52 };
     53 
     54 static void
     55 print_reject_types(void)
     56 {
     57 	unsigned int i;
     58 
     59 	printf("Valid reject types:\n");
     60 
     61 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
     62 		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
     63 		printf("    %-25s\talias\n", reject_table[i].alias);
     64 	}
     65 	printf("\n");
     66 }
     67 
     68 static void REJECT_help(void)
     69 {
     70 	printf(
     71 "REJECT target options:\n"
     72 "--reject-with type              drop input packet and send back\n"
     73 "                                a reply packet according to type:\n");
     74 
     75 	print_reject_types();
     76 
     77 	printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
     78 }
     79 
     80 static const struct xt_option_entry REJECT_opts[] = {
     81 	{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
     82 	XTOPT_TABLEEND,
     83 };
     84 
     85 static void REJECT_init(struct xt_entry_target *t)
     86 {
     87 	struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
     88 
     89 	/* default */
     90 	reject->with = IPT_ICMP_PORT_UNREACHABLE;
     91 
     92 }
     93 
     94 static void REJECT_parse(struct xt_option_call *cb)
     95 {
     96 	struct ipt_reject_info *reject = cb->data;
     97 	unsigned int i;
     98 
     99 	xtables_option_parse(cb);
    100 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
    101 		if (strncasecmp(reject_table[i].name,
    102 		      cb->arg, strlen(cb->arg)) == 0 ||
    103 		    strncasecmp(reject_table[i].alias,
    104 		      cb->arg, strlen(cb->arg)) == 0) {
    105 			reject->with = reject_table[i].with;
    106 			return;
    107 		}
    108 	/* This due to be dropped late in 2.4 pre-release cycle --RR */
    109 	if (strncasecmp("echo-reply", cb->arg, strlen(cb->arg)) == 0 ||
    110 	    strncasecmp("echoreply", cb->arg, strlen(cb->arg)) == 0)
    111 		fprintf(stderr, "--reject-with echo-reply no longer"
    112 			" supported\n");
    113 	xtables_error(PARAMETER_PROBLEM,
    114 		"unknown reject type \"%s\"", cb->arg);
    115 }
    116 
    117 static void REJECT_print(const void *ip, const struct xt_entry_target *target,
    118                          int numeric)
    119 {
    120 	const struct ipt_reject_info *reject
    121 		= (const struct ipt_reject_info *)target->data;
    122 	unsigned int i;
    123 
    124 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
    125 		if (reject_table[i].with == reject->with)
    126 			break;
    127 	printf(" reject-with %s", reject_table[i].name);
    128 }
    129 
    130 static void REJECT_save(const void *ip, const struct xt_entry_target *target)
    131 {
    132 	const struct ipt_reject_info *reject
    133 		= (const struct ipt_reject_info *)target->data;
    134 	unsigned int i;
    135 
    136 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
    137 		if (reject_table[i].with == reject->with)
    138 			break;
    139 
    140 	printf(" --reject-with %s", reject_table[i].name);
    141 }
    142 
    143 static struct xtables_target reject_tg_reg = {
    144 	.name		= "REJECT",
    145 	.version	= XTABLES_VERSION,
    146 	.family		= NFPROTO_IPV4,
    147 	.size		= XT_ALIGN(sizeof(struct ipt_reject_info)),
    148 	.userspacesize	= XT_ALIGN(sizeof(struct ipt_reject_info)),
    149 	.help		= REJECT_help,
    150 	.init		= REJECT_init,
    151 	.print		= REJECT_print,
    152 	.save		= REJECT_save,
    153 	.x6_parse	= REJECT_parse,
    154 	.x6_options	= REJECT_opts,
    155 };
    156 
    157 void _init(void)
    158 {
    159 	xtables_register_target(&reject_tg_reg);
    160 }
    161