libipt_REJECT.c revision 5d9678ad3eabc34ac40dfe055d7f6a8e44445a5a
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 <xtables.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#if 0 40 {"echo-reply", "echoreply", 41 IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"}, 42#endif 43 {"icmp-net-prohibited", "net-prohib", 44 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"}, 45 {"icmp-host-prohibited", "host-prohib", 46 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"}, 47 {"tcp-reset", "tcp-rst", 48 IPT_TCP_RESET, "TCP RST packet"}, 49 {"icmp-admin-prohibited", "admin-prohib", 50 IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"} 51}; 52 53static void 54print_reject_types(void) 55{ 56 unsigned int i; 57 58 printf("Valid reject types:\n"); 59 60 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) { 61 printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc); 62 printf(" %-25s\talias\n", reject_table[i].alias); 63 } 64 printf("\n"); 65} 66 67static void REJECT_help(void) 68{ 69 printf( 70"REJECT target 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 const struct option REJECT_opts[] = { 80 { "reject-with", 1, NULL, '1' }, 81 { .name = NULL } 82}; 83 84static void REJECT_init(struct xt_entry_target *t) 85{ 86 struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data; 87 88 /* default */ 89 reject->with = IPT_ICMP_PORT_UNREACHABLE; 90 91} 92 93static int REJECT_parse(int c, char **argv, int invert, unsigned int *flags, 94 const void *entry, struct xt_entry_target **target) 95{ 96 struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data; 97 unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names); 98 unsigned int i; 99 100 switch(c) { 101 case '1': 102 if (check_inverse(optarg, &invert, NULL, 0)) 103 exit_error(PARAMETER_PROBLEM, 104 "Unexpected `!' after --reject-with"); 105 for (i = 0; i < limit; i++) { 106 if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0) 107 || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) { 108 reject->with = reject_table[i].with; 109 return 1; 110 } 111 } 112 /* This due to be dropped late in 2.4 pre-release cycle --RR */ 113 if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0 114 || strncasecmp("echoreply", optarg, strlen(optarg)) == 0) 115 fprintf(stderr, "--reject-with echo-reply no longer" 116 " supported\n"); 117 exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg); 118 default: 119 /* Fall through */ 120 break; 121 } 122 return 0; 123} 124 125static void REJECT_print(const void *ip, const struct xt_entry_target *target, 126 int numeric) 127{ 128 const struct ipt_reject_info *reject 129 = (const struct ipt_reject_info *)target->data; 130 unsigned int i; 131 132 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) { 133 if (reject_table[i].with == reject->with) 134 break; 135 } 136 printf("reject-with %s ", reject_table[i].name); 137} 138 139static void REJECT_save(const void *ip, const struct xt_entry_target *target) 140{ 141 const struct ipt_reject_info *reject 142 = (const struct ipt_reject_info *)target->data; 143 unsigned int i; 144 145 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) 146 if (reject_table[i].with == reject->with) 147 break; 148 149 printf("--reject-with %s ", reject_table[i].name); 150} 151 152static struct xtables_target reject_tg_reg = { 153 .name = "REJECT", 154 .version = XTABLES_VERSION, 155 .family = NFPROTO_IPV4, 156 .size = XT_ALIGN(sizeof(struct ipt_reject_info)), 157 .userspacesize = XT_ALIGN(sizeof(struct ipt_reject_info)), 158 .help = REJECT_help, 159 .init = REJECT_init, 160 .parse = REJECT_parse, 161 .print = REJECT_print, 162 .save = REJECT_save, 163 .extra_opts = REJECT_opts, 164}; 165 166void _init(void) 167{ 168 xtables_register_target(&reject_tg_reg); 169} 170