1 /* Copyright (c) 2004-2006 Piotr 'QuakeR' Gasid³o <quaker@barbara.eu.org>
2 * accounting match helper (libipt_account.c)
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.
17 #include <linux/netfilter_ipv4/ipt_account.h>
20 #define HIPQUAD(addr) \
21 ((unsigned char *)&addr)[3], \
22 ((unsigned char *)&addr)[2], \
23 ((unsigned char *)&addr)[1], \
24 ((unsigned char *)&addr)[0]
27 static void help(void) {
29 "account v%s options:\n"
30 "--aaddr network/netmask\n"
31 " defines network/netmask for which make statistics.\n"
33 " defines name of list where statistics will be kept. If no is\n"
34 " specified DEFAULT will be used.\n"
36 " table will colect only short statistics (only total counters\n"
37 " without splitting it into protocols.\n"
42 static struct option opts
[] = {
43 { .name
= "aaddr", .has_arg
= 1, .flag
= NULL
, .val
= 201 },
44 { .name
= "aname", .has_arg
= 1, .flag
= NULL
, .val
= 202 },
45 { .name
= "ashort", .has_arg
= 0, .flag
= NULL
, .val
= 203 },
46 { .name
= 0, .has_arg
= 0, .flag
= 0, .val
= 0 }
49 /* Helper functions for parse_network */
50 int parseip(const char *parameter
, u_int32_t
*ip
) {
52 char buffer
[16], *bufferptr
, *dot
;
53 unsigned int i
, shift
, part
;
55 if (strlen(parameter
) > 15)
58 strncpy(buffer
, parameter
, 15);
63 for (i
= 0, shift
= 24, *ip
= 0; i
< 3; i
++, shift
-= 8) {
65 if ((dot
= strchr(bufferptr
, '.')) == NULL
)
68 if ((part
= strtol(bufferptr
, (char**)NULL
, 10)) < 0)
77 if ((part
= strtol(bufferptr
, (char**)NULL
, 10)) < 0)
86 static void parsenetwork(const char *parameter
, u_int32_t
*network
) {
87 if (!parseip(parameter
, network
))
88 exit_error(PARAMETER_PROBLEM
, "account: wrong ip in network");
91 static void parsenetmaskasbits(const char *parameter
, u_int32_t
*netmask
) {
95 if ((bits
= strtol(parameter
, (char **)NULL
, 10)) < 0 || bits
> 32)
96 exit_error(PARAMETER_PROBLEM
, "account: wrong netmask");
98 *netmask
= 0xffffffff << (32 - bits
);
101 static void parsenetmaskasip(const char *parameter
, u_int32_t
*netmask
) {
102 if (!parseip(parameter
, netmask
))
103 exit_error(PARAMETER_PROBLEM
, "account: wrong ip in netmask");
106 static void parsenetmask(const char *parameter
, u_int32_t
*netmask
)
108 if (strchr(parameter
, '.') != NULL
)
109 parsenetmaskasip(parameter
, netmask
);
111 parsenetmaskasbits(parameter
, netmask
);
114 static void parsenetworkandnetmask(const char *parameter
, u_int32_t
*network
, u_int32_t
*netmask
)
117 char buffer
[32], *slash
;
119 if (strlen(parameter
) > 31)
120 /* text is to long, even for 255.255.255.255/255.255.255.255 */
121 exit_error(PARAMETER_PROBLEM
, "account: wrong network/netmask");
123 strncpy(buffer
, parameter
, 31);
126 /* check whether netmask is given */
127 if ((slash
= strchr(buffer
, '/')) != NULL
) {
128 parsenetmask(slash
+ 1, netmask
);
131 *netmask
= 0xffffffff;
132 parsenetwork(buffer
, network
);
134 if ((*network
& *netmask
) != *network
)
135 exit_error(PARAMETER_PROBLEM
, "account: wrong network/netmask");
139 /* Function gets network & netmask from argument after --aaddr */
140 static void parse_network(const char *parameter
, struct t_ipt_account_info
*info
) {
142 parsenetworkandnetmask(parameter
, &info
->network
, &info
->netmask
);
146 /* validate netmask */
147 inline int valid_netmask(u_int32_t netmask
) {
148 while (netmask
& 0x80000000)
155 /* validate network/netmask pair */
156 inline int valid_network_and_netmask(struct t_ipt_account_info
*info
) {
157 if (!valid_netmask(info
->netmask
))
159 if ((info
->network
& info
->netmask
) != info
->network
)
166 /* Function initializes match */
167 static void init(struct ipt_entry_match
*match
,
168 unsigned int *nfcache
) {
170 struct t_ipt_account_info
*info
= (struct t_ipt_account_info
*)(match
)->data
;
173 /* set default table name to DEFAULT */
174 strncpy(info
->name
, "DEFAULT", IPT_ACCOUNT_NAME_LEN
);
175 info
->shortlisting
= 0;
180 /* Function parses match's arguments */
181 static int parse(int c
, char **argv
,
184 const struct ipt_entry
*entry
,
185 unsigned int *nfcache
,
186 struct ipt_entry_match
**match
) {
188 struct t_ipt_account_info
*info
= (struct t_ipt_account_info
*)(*match
)->data
;
194 parse_network(optarg
, info
);
195 if (!valid_network_and_netmask(info
))
196 exit_error(PARAMETER_PROBLEM
, "account: wrong network/netmask");
202 if (strlen(optarg
) < IPT_ACCOUNT_NAME_LEN
) {
203 strncpy(info
->name
, optarg
, IPT_ACCOUNT_NAME_LEN
);
204 info
->name
[IPT_ACCOUNT_NAME_LEN
] = '\0';
206 exit_error(PARAMETER_PROBLEM
, "account: Too long table name");
210 info
->shortlisting
= 1;
218 /* Final check whether network/netmask was specified */
219 static void final_check(unsigned int flags
) {
221 exit_error(PARAMETER_PROBLEM
, "account: You need specify '--aaddr' parameter");
224 /* Function used for printing rule with account match for iptables -L */
225 static void print(const struct ipt_ip
*ip
,
226 const struct ipt_entry_match
*match
,
229 struct t_ipt_account_info
*info
= (struct t_ipt_account_info
*)match
->data
;
232 printf("network/netmask: ");
233 printf("%u.%u.%u.%u/%u.%u.%u.%u ",
234 HIPQUAD(info
->network
),
235 HIPQUAD(info
->netmask
)
238 printf("name: %s ", info
->name
);
239 if (info
->shortlisting
)
240 printf("short-listing ");
243 /* Function used for saving rule containing account match */
244 static void save(const struct ipt_ip
*ip
,
245 const struct ipt_entry_match
*match
) {
247 struct t_ipt_account_info
*info
= (struct t_ipt_account_info
*)match
->data
;
250 printf("%u.%u.%u.%u/%u.%u.%u.%u ",
251 HIPQUAD(info
->network
),
252 HIPQUAD(info
->netmask
)
255 printf("--aname %s ", info
->name
);
256 if (info
->shortlisting
)
260 static struct iptables_match account
= {
263 .version
= IPTABLES_VERSION
,
264 .size
= IPT_ALIGN(sizeof(struct t_ipt_account_info
)),
265 .userspacesize
= IPT_ALIGN(sizeof(struct t_ipt_account_info
)),
269 .final_check
= &final_check
,
275 /* Function which registers match */
278 register_match(&account
);