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 struct reject_names_xlate { 28 const char *name; 29 enum ipt_reject_with with; 30 }; 31 32 enum { 33 O_REJECT_WITH = 0, 34 }; 35 36 static const struct reject_names reject_table[] = { 37 {"icmp-net-unreachable", "net-unreach", 38 IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"}, 39 {"icmp-host-unreachable", "host-unreach", 40 IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"}, 41 {"icmp-proto-unreachable", "proto-unreach", 42 IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"}, 43 {"icmp-port-unreachable", "port-unreach", 44 IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"}, 45 #if 0 46 {"echo-reply", "echoreply", 47 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"}, 48 #endif 49 {"icmp-net-prohibited", "net-prohib", 50 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"}, 51 {"icmp-host-prohibited", "host-prohib", 52 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"}, 53 {"tcp-reset", "tcp-rst", 54 IPT_TCP_RESET, "TCP RST packet"}, 55 {"icmp-admin-prohibited", "admin-prohib", 56 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"} 57 }; 58 59 static void 60 print_reject_types(void) 61 { 62 unsigned int i; 63 64 printf("Valid reject types:\n"); 65 66 for (i = 0; i < ARRAY_SIZE(reject_table); ++i) { 67 printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc); 68 printf(" %-25s\talias\n", reject_table[i].alias); 69 } 70 printf("\n"); 71 } 72 73 static void REJECT_help(void) 74 { 75 printf( 76 "REJECT target options:\n" 77 "--reject-with type drop input packet and send back\n" 78 " a reply packet according to type:\n"); 79 80 print_reject_types(); 81 82 printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n"); 83 } 84 85 static const struct xt_option_entry REJECT_opts[] = { 86 {.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING}, 87 XTOPT_TABLEEND, 88 }; 89 90 static void REJECT_init(struct xt_entry_target *t) 91 { 92 struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data; 93 94 /* default */ 95 reject->with = IPT_ICMP_PORT_UNREACHABLE; 96 97 } 98 99 static void REJECT_parse(struct xt_option_call *cb) 100 { 101 struct ipt_reject_info *reject = cb->data; 102 unsigned int i; 103 104 xtables_option_parse(cb); 105 for (i = 0; i < ARRAY_SIZE(reject_table); ++i) 106 if (strncasecmp(reject_table[i].name, 107 cb->arg, strlen(cb->arg)) == 0 || 108 strncasecmp(reject_table[i].alias, 109 cb->arg, strlen(cb->arg)) == 0) { 110 reject->with = reject_table[i].with; 111 return; 112 } 113 /* This due to be dropped late in 2.4 pre-release cycle --RR */ 114 if (strncasecmp("echo-reply", cb->arg, strlen(cb->arg)) == 0 || 115 strncasecmp("echoreply", cb->arg, strlen(cb->arg)) == 0) 116 fprintf(stderr, "--reject-with echo-reply no longer" 117 " supported\n"); 118 xtables_error(PARAMETER_PROBLEM, 119 "unknown reject type \"%s\"", cb->arg); 120 } 121 122 static void REJECT_print(const void *ip, const struct xt_entry_target *target, 123 int numeric) 124 { 125 const struct ipt_reject_info *reject 126 = (const struct ipt_reject_info *)target->data; 127 unsigned int i; 128 129 for (i = 0; i < ARRAY_SIZE(reject_table); ++i) 130 if (reject_table[i].with == reject->with) 131 break; 132 printf(" reject-with %s", reject_table[i].name); 133 } 134 135 static void REJECT_save(const void *ip, const struct xt_entry_target *target) 136 { 137 const struct ipt_reject_info *reject = 138 (const struct ipt_reject_info *)target->data; 139 unsigned int i; 140 141 for (i = 0; i < ARRAY_SIZE(reject_table); ++i) 142 if (reject_table[i].with == reject->with) 143 break; 144 145 printf(" --reject-with %s", reject_table[i].name); 146 } 147 148 static const struct reject_names_xlate reject_table_xlate[] = { 149 {"net-unreachable", IPT_ICMP_NET_UNREACHABLE}, 150 {"host-unreachable", IPT_ICMP_HOST_UNREACHABLE}, 151 {"prot-unreachable", IPT_ICMP_PROT_UNREACHABLE}, 152 {"port-unreachable", IPT_ICMP_PORT_UNREACHABLE}, 153 #if 0 154 {"echo-reply", IPT_ICMP_ECHOREPLY}, 155 #endif 156 {"net-prohibited", IPT_ICMP_NET_PROHIBITED}, 157 {"host-prohibited", IPT_ICMP_HOST_PROHIBITED}, 158 {"tcp reset", IPT_TCP_RESET}, 159 {"admin-prohibited", IPT_ICMP_ADMIN_PROHIBITED} 160 }; 161 162 static int REJECT_xlate(struct xt_xlate *xl, 163 const struct xt_xlate_tg_params *params) 164 { 165 const struct ipt_reject_info *reject = 166 (const struct ipt_reject_info *)params->target->data; 167 unsigned int i; 168 169 for (i = 0; i < ARRAY_SIZE(reject_table_xlate); ++i) { 170 if (reject_table_xlate[i].with == reject->with) 171 break; 172 } 173 174 if (reject->with == IPT_ICMP_PORT_UNREACHABLE) 175 xt_xlate_add(xl, "reject"); 176 else if (reject->with == IPT_TCP_RESET) 177 xt_xlate_add(xl, "reject with %s", 178 reject_table_xlate[i].name); 179 else 180 xt_xlate_add(xl, "reject with icmp type %s", 181 reject_table_xlate[i].name); 182 183 return 1; 184 } 185 186 187 static struct xtables_target reject_tg_reg = { 188 .name = "REJECT", 189 .version = XTABLES_VERSION, 190 .family = NFPROTO_IPV4, 191 .size = XT_ALIGN(sizeof(struct ipt_reject_info)), 192 .userspacesize = XT_ALIGN(sizeof(struct ipt_reject_info)), 193 .help = REJECT_help, 194 .init = REJECT_init, 195 .print = REJECT_print, 196 .save = REJECT_save, 197 .x6_parse = REJECT_parse, 198 .x6_options = REJECT_opts, 199 .xlate = REJECT_xlate, 200 }; 201 202 void _init(void) 203 { 204 xtables_register_target(&reject_tg_reg); 205 } 206