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 13struct reject_names { 14 const char *name; 15 const char *alias; 16 enum ipt_reject_with with; 17 const char *desc; 18}; 19 20static const struct reject_names reject_table[] = { 21 {"icmp-net-unreachable", "net-unreach", 22 IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"}, 23 {"icmp-host-unreachable", "host-unreach", 24 IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"}, 25 {"icmp-proto-unreachable", "proto-unreach", 26 IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"}, 27 {"icmp-port-unreachable", "port-unreach", 28 IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"}, 29 {"icmp-net-prohibited", "net-prohib", 30 IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"}, 31 {"icmp-host-prohibited", "host-prohib", 32 IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"}, 33 {"tcp-reset", "tcp-reset", 34 IPT_TCP_RESET, "TCP RST packet"} 35}; 36 37static void 38print_reject_types() 39{ 40 unsigned int i; 41 42 printf("Valid reject types:\n"); 43 44 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) { 45 printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc); 46 printf(" %-25s\talias\n", reject_table[i].alias); 47 } 48 printf("\n"); 49} 50 51/* Saves the union ipt_targinfo in parsable form to stdout. */ 52 53/* Function which prints out usage message. */ 54static void 55help(void) 56{ 57 printf( 58"REJECT options:\n" 59"--reject-with type drop input packet and send back\n" 60" a reply packet according to type:\n"); 61 62 print_reject_types(); 63} 64 65static struct option opts[] = { 66 { "reject-with", 1, 0, '1' }, 67 { 0 } 68}; 69 70/* Allocate and initialize the target. */ 71static void 72init(struct ipt_entry_target *t, unsigned int *nfcache) 73{ 74 struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data; 75 76 /* default */ 77 reject->with = IPT_ICMP_PORT_UNREACHABLE; 78 79 /* Can't cache this */ 80 *nfcache |= NFC_UNKNOWN; 81} 82 83/* Function which parses command options; returns true if it 84 ate an option */ 85static int 86parse(int c, char **argv, int invert, unsigned int *flags, 87 const struct ipt_entry *entry, 88 struct ipt_entry_target **target) 89{ 90 struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data; 91 unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names); 92 unsigned int i; 93 94 switch(c) { 95 case '1': 96 if (check_inverse(optarg, &invert, NULL, 0)) 97 exit_error(PARAMETER_PROBLEM, 98 "Unexpected `!' after --reject-with"); 99 for (i = 0; i < limit; i++) { 100 if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0) 101 || (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) { 102 reject->with = reject_table[i].with; 103 return 1; 104 } 105 } 106 /* This due to be dropped late in 2.4 pre-release cycle --RR */ 107 if (strncasecmp("echo-reply", optarg, strlen(optarg)) == 0 108 || strncasecmp("echoreply", optarg, strlen(optarg)) == 0) 109 fprintf(stderr, "--reject-with echo-reply no longer" 110 " supported\n"); 111 exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg); 112 default: 113 /* Fall through */ 114 break; 115 } 116 return 0; 117} 118 119/* Final check; nothing. */ 120static void final_check(unsigned int flags) 121{ 122} 123 124/* Prints out ipt_reject_info. */ 125static void 126print(const struct ipt_ip *ip, 127 const struct ipt_entry_target *target, 128 int numeric) 129{ 130 const struct ipt_reject_info *reject 131 = (const struct ipt_reject_info *)target->data; 132 unsigned int i; 133 134 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) { 135 if (reject_table[i].with == reject->with) 136 break; 137 } 138 printf("reject-with %s ", reject_table[i].name); 139} 140 141/* Saves ipt_reject in parsable form to stdout. */ 142static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 143{ 144 const struct ipt_reject_info *reject 145 = (const struct ipt_reject_info *)target->data; 146 unsigned int i; 147 148 for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) 149 if (reject_table[i].with == reject->with) 150 break; 151 152 printf("--reject-with %s ", reject_table[i].name); 153} 154 155static 156struct iptables_target reject 157= { NULL, 158 "REJECT", 159 IPTABLES_VERSION, 160 IPT_ALIGN(sizeof(struct ipt_reject_info)), 161 IPT_ALIGN(sizeof(struct ipt_reject_info)), 162 &help, 163 &init, 164 &parse, 165 &final_check, 166 &print, 167 &save, 168 opts 169}; 170 171void _init(void) 172{ 173 register_target(&reject); 174} 175