2 * accounting match helper (libipt_account.c)
3 * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
7 * This software is distributed under the terms of GNU GPL
16 #include <linux/netfilter_ipv4/ipt_account.h>
19 #define HIPQUAD(addr) \
20 ((unsigned char *)&addr)[3], \
21 ((unsigned char *)&addr)[2], \
22 ((unsigned char *)&addr)[1], \
23 ((unsigned char *)&addr)[0]
26 static void help(void) {
28 "account v%s options:\n"
29 "--aaddr network/netmask\n"
30 " defines network/netmask for which make statistics.\n"
32 " defines name of list where statistics will be kept. If no is\n"
33 " specified DEFAULT will be used.\n"
35 " table will colect only short statistics (only total counters\n"
36 " without splitting it into protocols.\n"
41 static struct option opts[] = {
42 { .name = "aaddr", .has_arg = 1, .flag = NULL, .val = 201 },
43 { .name = "aname", .has_arg = 1, .flag = NULL, .val = 202 },
44 { .name = "ashort", .has_arg = 0, .flag = NULL, .val = 203 },
45 { .name = 0, .has_arg = 0, .flag = 0, .val = 0 }
48 /* Helper functions for parse_network */
49 int parseip(const char *parameter, u_int32_t *ip) {
51 char buffer[16], *bufferptr, *dot;
52 unsigned int i, shift, part;
54 if (strlen(parameter) > 15)
57 strncpy(buffer, parameter, 15);
62 for (i = 0, shift = 24, *ip = 0; i < 3; i++, shift -= 8) {
64 if ((dot = strchr(bufferptr, '.')) == NULL)
67 if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0)
76 if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0)
85 static void parsenetwork(const char *parameter, u_int32_t *network) {
86 if (!parseip(parameter, network))
87 exit_error(PARAMETER_PROBLEM, "account: wrong ip in network");
90 static void parsenetmaskasbits(const char *parameter, u_int32_t *netmask) {
94 if ((bits = strtol(parameter, (char **)NULL, 10)) < 0 || bits > 32)
95 exit_error(PARAMETER_PROBLEM, "account: wrong netmask");
97 *netmask = 0xffffffff << (32 - bits);
100 static void parsenetmaskasip(const char *parameter, u_int32_t *netmask) {
101 if (!parseip(parameter, netmask))
102 exit_error(PARAMETER_PROBLEM, "account: wrong ip in netmask");
105 static void parsenetmask(const char *parameter, u_int32_t *netmask)
107 if (strchr(parameter, '.') != NULL)
108 parsenetmaskasip(parameter, netmask);
110 parsenetmaskasbits(parameter, netmask);
113 static void parsenetworkandnetmask(const char *parameter, u_int32_t *network, u_int32_t *netmask)
116 char buffer[32], *slash;
118 if (strlen(parameter) > 31)
119 /* text is to long, even for 255.255.255.255/255.255.255.255 */
120 exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
122 strncpy(buffer, parameter, 31);
125 /* check whether netmask is given */
126 if ((slash = strchr(buffer, '/')) != NULL) {
127 parsenetmask(slash + 1, netmask);
130 *netmask = 0xffffffff;
131 parsenetwork(buffer, network);
133 if ((*network & *netmask) != *network)
134 exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
138 /* Function gets network & netmask from argument after --aaddr */
139 static void parse_network(const char *parameter, struct t_ipt_account_info *info) {
141 parsenetworkandnetmask(parameter, &info->network, &info->netmask);
145 /* validate netmask */
146 inline int valid_netmask(u_int32_t netmask) {
147 while (netmask & 0x80000000)
154 /* validate network/netmask pair */
155 inline int valid_network_and_netmask(struct t_ipt_account_info *info) {
156 if (!valid_netmask(info->netmask))
158 if ((info->network & info->netmask) != info->network)
165 /* Function initializes match */
166 static void init(struct ipt_entry_match *match,
167 unsigned int *nfcache) {
169 struct t_ipt_account_info *info = (struct t_ipt_account_info *)(match)->data;
172 /* set default table name to DEFAULT */
173 strncpy(info->name, "DEFAULT", IPT_ACCOUNT_NAME_LEN);
174 info->shortlisting = 0;
178 /* Function parses match's arguments */
179 static int parse(int c, char **argv,
182 const struct ipt_entry *entry,
183 unsigned int *nfcache,
184 struct ipt_entry_match **match) {
186 struct t_ipt_account_info *info = (struct t_ipt_account_info *)(*match)->data;
192 parse_network(optarg, info);
193 if (!valid_network_and_netmask(info))
194 exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
200 if (strlen(optarg) < IPT_ACCOUNT_NAME_LEN)
201 strncpy(info->name, optarg, IPT_ACCOUNT_NAME_LEN);
203 exit_error(PARAMETER_PROBLEM, "account: Too long table name");
207 info->shortlisting = 1;
215 /* Final check whether network/netmask was specified */
216 static void final_check(unsigned int flags) {
218 exit_error(PARAMETER_PROBLEM, "account: You need specify '--aaddr' parameter");
221 /* Function used for printing rule with account match for iptables -L */
222 static void print(const struct ipt_ip *ip,
223 const struct ipt_entry_match *match,
226 struct t_ipt_account_info *info = (struct t_ipt_account_info *)match->data;
229 printf("network/netmask: ");
230 printf("%u.%u.%u.%u/%u.%u.%u.%u ",
231 HIPQUAD(info->network),
232 HIPQUAD(info->netmask)
235 printf("name: %s ", info->name);
236 if (info->shortlisting)
237 printf("short-listing ");
240 /* Function used for saving rule containing account match */
241 static void save(const struct ipt_ip *ip,
242 const struct ipt_entry_match *match) {
244 struct t_ipt_account_info *info = (struct t_ipt_account_info *)match->data;
247 printf("%u.%u.%u.%u/%u.%u.%u.%u ",
248 HIPQUAD(info->network),
249 HIPQUAD(info->netmask)
252 printf("--aname %s ", info->name);
253 if (info->shortlisting)
257 static struct iptables_match account = {
260 .version = IPTABLES_VERSION,
261 .size = IPT_ALIGN(sizeof(struct t_ipt_account_info)),
262 .userspacesize = IPT_ALIGN(sizeof(struct t_ipt_account_info)),
266 .final_check = &final_check,
272 /* Function which registers match */
275 register_match(&account);