Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to ip6tables to add customized REJECT support.
      2  *
      3  * (C) 2000 Jozsef Kadlecsik <kadlec (at) blackhole.kfki.hu>
      4  *
      5  * ported to IPv6 by Harald Welte <laforge (at) gnumonks.org>
      6  *
      7  */
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <xtables.h>
     11 #include <linux/netfilter_ipv6/ip6t_REJECT.h>
     12 
     13 struct reject_names {
     14 	const char *name;
     15 	const char *alias;
     16 	enum ip6t_reject_with with;
     17 	const char *desc;
     18 };
     19 
     20 struct reject_names_xlate {
     21 	const char *name;
     22 	enum ip6t_reject_with with;
     23 };
     24 
     25 enum {
     26 	O_REJECT_WITH = 0,
     27 };
     28 
     29 static const struct reject_names reject_table[] = {
     30 	{"icmp6-no-route", "no-route",
     31 		IP6T_ICMP6_NO_ROUTE, "ICMPv6 no route"},
     32 	{"icmp6-adm-prohibited", "adm-prohibited",
     33 		IP6T_ICMP6_ADM_PROHIBITED, "ICMPv6 administratively prohibited"},
     34 #if 0
     35 	{"icmp6-not-neighbor", "not-neighbor"},
     36 		IP6T_ICMP6_NOT_NEIGHBOR, "ICMPv6 not a neighbor"},
     37 #endif
     38 	{"icmp6-addr-unreachable", "addr-unreach",
     39 		IP6T_ICMP6_ADDR_UNREACH, "ICMPv6 address unreachable"},
     40 	{"icmp6-port-unreachable", "port-unreach",
     41 		IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"},
     42 	{"tcp-reset", "tcp-reset",
     43 		IP6T_TCP_RESET, "TCP RST packet"},
     44 	{"icmp6-policy-fail", "policy-fail",
     45 		IP6T_ICMP6_POLICY_FAIL, "ICMPv6 policy fail"},
     46 	{"icmp6-reject-route", "reject-route",
     47 		IP6T_ICMP6_REJECT_ROUTE, "ICMPv6 reject route"}
     48 };
     49 
     50 static void
     51 print_reject_types(void)
     52 {
     53 	unsigned int i;
     54 
     55 	printf("Valid reject types:\n");
     56 
     57 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
     58 		printf("    %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
     59 		printf("    %-25s\talias\n", reject_table[i].alias);
     60 	}
     61 	printf("\n");
     62 }
     63 
     64 static void REJECT_help(void)
     65 {
     66 	printf(
     67 "REJECT target options:\n"
     68 "--reject-with type              drop input packet and send back\n"
     69 "                                a reply packet according to type:\n");
     70 
     71 	print_reject_types();
     72 }
     73 
     74 static const struct xt_option_entry REJECT_opts[] = {
     75 	{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
     76 	XTOPT_TABLEEND,
     77 };
     78 
     79 static void REJECT_init(struct xt_entry_target *t)
     80 {
     81 	struct ip6t_reject_info *reject = (struct ip6t_reject_info *)t->data;
     82 
     83 	/* default */
     84 	reject->with = IP6T_ICMP6_PORT_UNREACH;
     85 
     86 }
     87 
     88 static void REJECT_parse(struct xt_option_call *cb)
     89 {
     90 	struct ip6t_reject_info *reject = cb->data;
     91 	unsigned int i;
     92 
     93 	xtables_option_parse(cb);
     94 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
     95 		if (strncasecmp(reject_table[i].name,
     96 		      cb->arg, strlen(cb->arg)) == 0 ||
     97 		    strncasecmp(reject_table[i].alias,
     98 		      cb->arg, strlen(cb->arg)) == 0) {
     99 			reject->with = reject_table[i].with;
    100 			return;
    101 		}
    102 	xtables_error(PARAMETER_PROBLEM,
    103 		"unknown reject type \"%s\"", cb->arg);
    104 }
    105 
    106 static void REJECT_print(const void *ip, const struct xt_entry_target *target,
    107                          int numeric)
    108 {
    109 	const struct ip6t_reject_info *reject
    110 		= (const struct ip6t_reject_info *)target->data;
    111 	unsigned int i;
    112 
    113 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
    114 		if (reject_table[i].with == reject->with)
    115 			break;
    116 	printf(" reject-with %s", reject_table[i].name);
    117 }
    118 
    119 static void REJECT_save(const void *ip, const struct xt_entry_target *target)
    120 {
    121 	const struct ip6t_reject_info *reject
    122 		= (const struct ip6t_reject_info *)target->data;
    123 	unsigned int i;
    124 
    125 	for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
    126 		if (reject_table[i].with == reject->with)
    127 			break;
    128 
    129 	printf(" --reject-with %s", reject_table[i].name);
    130 }
    131 
    132 static const struct reject_names_xlate reject_table_xlate[] = {
    133 	{"no-route",		IP6T_ICMP6_NO_ROUTE},
    134 	{"admin-prohibited",	IP6T_ICMP6_ADM_PROHIBITED},
    135 	{"addr-unreachable",	IP6T_ICMP6_ADDR_UNREACH},
    136 	{"port-unreachable",	IP6T_ICMP6_PORT_UNREACH},
    137 	{"tcp reset",		IP6T_TCP_RESET},
    138 	{"policy-fail",		IP6T_ICMP6_POLICY_FAIL},
    139 	{"reject-route",	IP6T_ICMP6_REJECT_ROUTE}
    140 };
    141 
    142 static int REJECT_xlate(struct xt_xlate *xl,
    143 			const struct xt_xlate_tg_params *params)
    144 {
    145 	const struct ip6t_reject_info *reject =
    146 		(const struct ip6t_reject_info *)params->target->data;
    147 	unsigned int i;
    148 
    149 	for (i = 0; i < ARRAY_SIZE(reject_table_xlate); ++i)
    150 		if (reject_table_xlate[i].with == reject->with)
    151 			break;
    152 
    153 	if (reject->with == IP6T_ICMP6_PORT_UNREACH)
    154 		xt_xlate_add(xl, "reject");
    155 	else if (reject->with == IP6T_TCP_RESET)
    156 		xt_xlate_add(xl, "reject with %s", reject_table_xlate[i].name);
    157 	else
    158 		xt_xlate_add(xl, "reject with icmpv6 type %s",
    159 			   reject_table_xlate[i].name);
    160 
    161 	return 1;
    162 }
    163 
    164 static struct xtables_target reject_tg6_reg = {
    165 	.name = "REJECT",
    166 	.version	= XTABLES_VERSION,
    167 	.family		= NFPROTO_IPV6,
    168 	.size 		= XT_ALIGN(sizeof(struct ip6t_reject_info)),
    169 	.userspacesize 	= XT_ALIGN(sizeof(struct ip6t_reject_info)),
    170 	.help		= REJECT_help,
    171 	.init		= REJECT_init,
    172 	.print		= REJECT_print,
    173 	.save		= REJECT_save,
    174 	.x6_parse	= REJECT_parse,
    175 	.x6_options	= REJECT_opts,
    176 	.xlate		= REJECT_xlate,
    177 };
    178 
    179 void _init(void)
    180 {
    181 	xtables_register_target(&reject_tg6_reg);
    182 }
    183