1/* Shared library add-on to iptables to add state tracking support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <stddef.h> 7#include <getopt.h> 8#include <iptables.h> 9#include <linux/netfilter_ipv4/ip_conntrack.h> 10#include <linux/netfilter_ipv4/ipt_iplimit.h> 11 12/* Function which prints out usage message. */ 13static void 14help(void) 15{ 16 printf( 17"iplimit v%s options:\n" 18"[!] --iplimit-above n match if the number of existing tcp connections is (not) above n\n" 19" --iplimit-mask n group hosts using mask\n" 20"\n", IPTABLES_VERSION); 21} 22 23static struct option opts[] = { 24 { "iplimit-above", 1, 0, '1' }, 25 { "iplimit-mask", 1, 0, '2' }, 26 {0} 27}; 28 29/* Initialize the match. */ 30static void 31init(struct ipt_entry_match *m, unsigned int *nfcache) 32{ 33 /* Can't cache this */ 34 *nfcache |= NFC_UNKNOWN; 35} 36 37/* Function which parses command options; returns true if it 38 ate an option */ 39static int 40parse(int c, char **argv, int invert, unsigned int *flags, 41 const struct ipt_entry *entry, 42 unsigned int *nfcache, 43 struct ipt_entry_match **match) 44{ 45 struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)(*match)->data; 46 47 if (0 == (*flags & 2)) { 48 /* set default mask unless we've already seen a mask option */ 49 info->mask = htonl(0xFFFFFFFF); 50 } 51 52 switch (c) { 53 case '1': 54 check_inverse(optarg, &invert, &optind, 0); 55 info->limit = atoi(argv[optind-1]); 56 info->inverse = invert; 57 *flags |= 1; 58 break; 59 60 case '2': 61 info->mask = htonl(0xFFFFFFFF << (32 - atoi(argv[optind-1]))); 62 *flags |= 2; 63 break; 64 65 default: 66 return 0; 67 } 68 69 return 1; 70} 71 72/* Final check */ 73static void final_check(unsigned int flags) 74{ 75 if (!flags & 1) 76 exit_error(PARAMETER_PROBLEM, "You must specify `--iplimit-above'"); 77} 78 79static int 80count_bits(u_int32_t mask) 81{ 82 int i, bits; 83 84 for (bits = 0, i = 31; i >= 0; i--) { 85 if (mask & htonl((u_int32_t)1 << i)) { 86 bits++; 87 continue; 88 } 89 break; 90 } 91 return bits; 92} 93 94/* Prints out the matchinfo. */ 95static void 96print(const struct ipt_ip *ip, 97 const struct ipt_entry_match *match, 98 int numeric) 99{ 100 struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data; 101 102 printf("#conn/%d %s %d ", count_bits(info->mask), 103 info->inverse ? "<" : ">", info->limit); 104} 105 106/* Saves the matchinfo in parsable form to stdout. */ 107static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 108{ 109 struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data; 110 111 printf("%s--iplimit-above %d ",info->inverse ? "! " : "",info->limit); 112 printf("--iplimit-mask %d ",count_bits(info->mask)); 113} 114 115static struct iptables_match iplimit = { 116 name: "iplimit", 117 version: IPTABLES_VERSION, 118 size: IPT_ALIGN(sizeof(struct ipt_iplimit_info)), 119 userspacesize: offsetof(struct ipt_iplimit_info,data), 120 help: help, 121 init: init, 122 parse: parse, 123 final_check: final_check, 124 print: print, 125 save: save, 126 extra_opts: opts 127}; 128 129void _init(void) 130{ 131 register_match(&iplimit); 132} 133