1 /* Shared library add-on to iptables to add connection rate tracking 2 * support. 3 * 4 * Copyright (c) 2004 Nuutti Kotivuori <naked (at) iki.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 **/ 10 #include <stdio.h> 11 #include <netdb.h> 12 #include <string.h> 13 #include <stdlib.h> 14 #include <getopt.h> 15 #include <iptables.h> 16 #include <linux/netfilter_ipv4/ip_conntrack.h> 17 #include <linux/netfilter_ipv4/ipt_connrate.h> 18 19 /* Function which prints out usage message. */ 20 static void 21 help(void) 22 { 23 printf( 24 "connrate v%s options:\n" 25 " --connrate [!] [from]:[to]\n" 26 " Match connection transfer rate in bytes\n" 27 " per second. `inf' can be used for maximum\n" 28 " expressible value.\n" 29 "\n", IPTABLES_VERSION); 30 } 31 32 static struct option opts[] = { 33 { "connrate", 1, 0, '1' }, 34 {0} 35 }; 36 37 static u_int32_t 38 parse_value(const char *arg, u_int32_t def) 39 { 40 char *end; 41 size_t len; 42 u_int32_t value; 43 44 len = strlen(arg); 45 if(len == 0) 46 return def; 47 if(strcmp(arg, "inf") == 0) 48 return 0xFFFFFFFF; 49 value = strtoul(arg, &end, 0); 50 if(*end != '\0') 51 exit_error(PARAMETER_PROBLEM, 52 "Bad value in range `%s'", arg); 53 return value; 54 } 55 56 static void 57 parse_range(const char *arg, struct ipt_connrate_info *si) 58 { 59 char *buffer; 60 char *colon; 61 62 buffer = strdup(arg); 63 if ((colon = strchr(buffer, ':')) == NULL) 64 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg); 65 *colon = '\0'; 66 si->from = parse_value(buffer, 0); 67 si->to = parse_value(colon+1, 0xFFFFFFFF); 68 if (si->from > si->to) 69 exit_error(PARAMETER_PROBLEM, "%u should be less than %u", si->from,si->to); 70 free(buffer); 71 } 72 73 #define CONNRATE_OPT 0x01 74 75 /* Function which parses command options; returns true if it 76 ate an option */ 77 static int 78 parse(int c, char **argv, int invert, unsigned int *flags, 79 const struct ipt_entry *entry, 80 unsigned int *nfcache, 81 struct ipt_entry_match **match) 82 { 83 struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)(*match)->data; 84 u_int32_t tmp; 85 86 switch (c) { 87 case '1': 88 if (*flags & CONNRATE_OPT) 89 exit_error(PARAMETER_PROBLEM, 90 "Only one `--connrate' allowed"); 91 check_inverse(optarg, &invert, &optind, 0); 92 parse_range(argv[optind-1], sinfo); 93 if (invert) { 94 tmp = sinfo->from; 95 sinfo->from = sinfo->to; 96 sinfo->to = tmp; 97 } 98 *flags |= CONNRATE_OPT; 99 break; 100 101 default: 102 return 0; 103 } 104 105 return 1; 106 } 107 108 static void final_check(unsigned int flags) 109 { 110 if (!(flags & CONNRATE_OPT)) 111 exit_error(PARAMETER_PROBLEM, 112 "connrate match: You must specify `--connrate'"); 113 } 114 115 static void 116 print_value(u_int32_t value) 117 { 118 if(value == 0xFFFFFFFF) 119 printf("inf"); 120 else 121 printf("%u", value); 122 } 123 124 static void 125 print_range(struct ipt_connrate_info *sinfo) 126 { 127 if (sinfo->from > sinfo->to) { 128 printf("! "); 129 print_value(sinfo->to); 130 printf(":"); 131 print_value(sinfo->from); 132 } else { 133 print_value(sinfo->from); 134 printf(":"); 135 print_value(sinfo->to); 136 } 137 } 138 139 /* Prints out the matchinfo. */ 140 static void 141 print(const struct ipt_ip *ip, 142 const struct ipt_entry_match *match, 143 int numeric) 144 { 145 struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data; 146 147 printf("connrate "); 148 print_range(sinfo); 149 printf(" "); 150 } 151 152 /* Saves the matchinfo in parsable form to stdout. */ 153 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 154 { 155 struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data; 156 157 printf("--connrate "); 158 print_range(sinfo); 159 printf(" "); 160 } 161 162 static struct iptables_match state = { 163 .next = NULL, 164 .name = "connrate", 165 .version = IPTABLES_VERSION, 166 .size = IPT_ALIGN(sizeof(struct ipt_connrate_info)), 167 .userspacesize = IPT_ALIGN(sizeof(struct ipt_connrate_info)), 168 .help = &help, 169 .parse = &parse, 170 .final_check = &final_check, 171 .print = &print, 172 .save = &save, 173 .extra_opts = opts 174 }; 175 176 void ipt_connrate_init(void) 177 { 178 register_match(&state); 179 } 180