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