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