• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ipv4/ip_conntrack.h>
17 #include <linux/netfilter_ipv4/ipt_connrate.h>
18 
19 /* Function which prints out usage message. */
20 static void
help(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
parse_value(const char * arg,u_int32_t def)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
parse_range(const char * arg,struct ipt_connrate_info * si)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
parse(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,unsigned int * nfcache,struct ipt_entry_match ** match)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 
final_check(unsigned int flags)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
print_value(u_int32_t value)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
print_range(struct ipt_connrate_info * sinfo)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
print(const struct ipt_ip * ip,const struct ipt_entry_match * match,int numeric)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. */
save(const struct ipt_ip * ip,const struct ipt_entry_match * match)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 
ipt_connrate_init(void)176 void ipt_connrate_init(void)
177 {
178 	register_match(&state);
179 }
180