Home | History | Annotate | Download | only in extensions
      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