1/* Shared library add-on to iptables to add customized REJECT support. 2 * 3 * (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 */ 5#include <stdio.h> 6#include <string.h> 7#include <stdlib.h> 8#include <getopt.h> 9#include <iptables.h> 10#include <linux/netfilter_ipv4/ip_tables.h> 11#include <linux/netfilter_ipv4/ipt_REJECT.h> 12#include <linux/version.h> 13 14/* If we are compiling against a kernel that does not support 15 * IPT_ICMP_ADMIN_PROHIBITED, we are emulating it. 16 * The result will be a plain DROP of the packet instead of 17 * reject. -- Maciej Soltysiak <solt@dns.toxicfilms.tv> 18 */ 19#ifndef IPT_ICMP_ADMIN_PROHIBITED 20#define IPT_ICMP_ADMIN_PROHIBITED IPT_TCP_RESET + 1 21#endif 22 23struct reject_names { 24 const char *name; 25 const char *alias; 26 enum ipt_reject_with with; 27 const char *desc; 28}; 29 30static const struct reject_names reject_table[] = { 31 {"icmp-net-unreachable", "net-unreach", 32 IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"}, 33 {"icmp-host-unreachable", "host-unreach", 34 IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"}, 35 {"icmp-proto-unreachable", "proto-unreach", 36 IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"}, 37 {"icmp-port-unreachable", "port-unreach", 38 IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"}, 39 {"icmp-net-prohibited", "net-prohib", 40 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"}, 41 {"icmp-host-prohibited", "host-prohib", 42 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"}, 43 {"tcp-reset", "tcp-rst", 44 IPT_TCP_RESET, "TCP RST packet"}, 45 {"icmp-admin-prohibited", "admin-prohib", 46 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"} 47}; 48 49static void 50print_reject_types() 51{ 52 unsigned int i; 53 54 printf("Valid reject types:\n"); 55 56 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) { 57 printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc); 58 printf(" %-25s\talias\n", reject_table[i].alias); 59 } 60 printf("\n"); 61} 62 63/* Saves the union ipt_targinfo in parsable form to stdout. */ 64 65/* Function which prints out usage message. */ 66static void 67help(void) 68{ 69 printf( 70"REJECT options:\n" 71"--reject-with type drop input packet and send back\n" 72" a reply packet according to type:\n"); 73 74 print_reject_types(); 75 76 printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n"); 77} 78 79static struct option opts[] = { 80 { "reject-with", 1, 0, '1' }, 81 { 0 } 82}; 83 84/* Allocate and initialize the target. */ 85static void 86init(struct ipt_entry_target *t, unsigned int *nfcache) 87{ 88 struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data; 89 90 /* default */ 91 reject->with = IPT_ICMP_PORT_UNREACHABLE; 92 93} 94 95/* Function which parses command options; returns true if it 96 ate an option */ 97static int 98parse(int c, char **argv, int invert, unsigned int *flags, 99 const struct ipt_entry *entry, 100 struct ipt_entry_target **target) 101{ 102 struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data; 103 unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names); 104 unsigned int i; 105 106 switch(c) { 107 case '1': 108 if (check_inverse(optarg, &invert, NULL, 0)) 109 exit_error(PARAMETER_PROBLEM, 110 "Unexpected `!' after --reject-with"); 111 for (i = 0; i < limit; i++) { 112 if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0) 113 || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) { 114 reject->with = reject_table[i].with; 115 return 1; 116 } 117 } 118 /* This due to be dropped late in 2.4 pre-release cycle --RR */ 119 if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0 120 || strncasecmp("echoreply", optarg, strlen(optarg)) == 0) 121 fprintf(stderr, "--reject-with echo-reply no longer" 122 " supported\n"); 123 exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg); 124 default: 125 /* Fall through */ 126 break; 127 } 128 return 0; 129} 130 131/* Final check; nothing. */ 132static void final_check(unsigned int flags) 133{ 134} 135 136/* Prints out ipt_reject_info. */ 137static void 138print(const struct ipt_ip *ip, 139 const struct ipt_entry_target *target, 140 int numeric) 141{ 142 const struct ipt_reject_info *reject 143 = (const struct ipt_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/* Saves ipt_reject in parsable form to stdout. */ 154static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 155{ 156 const struct ipt_reject_info *reject 157 = (const struct ipt_reject_info *)target->data; 158 unsigned int i; 159 160 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) 161 if (reject_table[i].with == reject->with) 162 break; 163 164 printf("--reject-with %s ", reject_table[i].name); 165} 166 167static struct iptables_target reject = { 168 .next = NULL, 169 .name = "REJECT", 170 .version = IPTABLES_VERSION, 171 .size = IPT_ALIGN(sizeof(struct ipt_reject_info)), 172 .userspacesize = IPT_ALIGN(sizeof(struct ipt_reject_info)), 173 .help = &help, 174 .init = &init, 175 .parse = &parse, 176 .final_check = &final_check, 177 .print = &print, 178 .save = &save, 179 .extra_opts = opts 180}; 181 182void _init(void) 183{ 184 register_target(&reject); 185} 186