1/* Shared library add-on to iptables to add connection rate tracking 2 * support. 3 * 4 * Copyright (c) 2004 Nuutti Kotivuori <naked@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/nf_conntrack_common.h> 17#include <linux/netfilter_ipv4/ipt_connrate.h> 18 19/* Function which prints out usage message. */ 20static void 21help(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 32static struct option opts[] = { 33 { "connrate", 1, 0, '1' }, 34 {0} 35}; 36 37static u_int32_t 38parse_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 56static void 57parse_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 */ 77static int 78parse(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 108static 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 115static void 116print_value(u_int32_t value) 117{ 118 if(value == 0xFFFFFFFF) 119 printf("inf"); 120 else 121 printf("%u", value); 122} 123 124static void 125print_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. */ 140static void 141print(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. */ 153static 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 162static 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 176void _init(void) 177{ 178 register_match(&state); 179} 180