Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / iptables / extensions / libipt_account.c
blob6d9d85a0d2140e39a444a3d12e793b1047edd59b
1 /* Copyright (c) 2004-2006 Piotr 'QuakeR' Gasid³o <quaker@barbara.eu.org>
2 * accounting match helper (libipt_account.c)
4 * Version: 0.1.20
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 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <iptables.h>
14 #include <string.h>
15 #include <getopt.h>
17 #include <linux/netfilter_ipv4/ipt_account.h>
19 #ifndef HIPQUAD
20 #define HIPQUAD(addr) \
21 ((unsigned char *)&addr)[3], \
22 ((unsigned char *)&addr)[2], \
23 ((unsigned char *)&addr)[1], \
24 ((unsigned char *)&addr)[0]
25 #endif
27 static void help(void) {
28 printf(
29 "account v%s options:\n"
30 "--aaddr network/netmask\n"
31 " defines network/netmask for which make statistics.\n"
32 "--aname name\n"
33 " defines name of list where statistics will be kept. If no is\n"
34 " specified DEFAULT will be used.\n"
35 "--ashort\n"
36 " table will colect only short statistics (only total counters\n"
37 " without splitting it into protocols.\n"
39 IPTABLES_VERSION);
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)
56 return 0;
58 strncpy(buffer, parameter, 15);
59 buffer[15] = 0;
61 bufferptr = buffer;
63 for (i = 0, shift = 24, *ip = 0; i < 3; i++, shift -= 8) {
64 /* no dot */
65 if ((dot = strchr(bufferptr, '.')) == NULL)
66 return 0;
67 /* not a number */
68 if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0)
69 return 0;
70 /* to big number */
71 if (part > 255)
72 return 0;
73 *ip |= part << shift;
74 bufferptr = dot + 1;
76 /* not a number */
77 if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0)
78 return 0;
79 /* to big number */
80 if (part > 255)
81 return 0;
82 *ip |= part;
83 return 1;
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) {
93 u_int32_t bits;
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);
110 else
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);
124 buffer[31] = 0;
126 /* check whether netmask is given */
127 if ((slash = strchr(buffer, '/')) != NULL) {
128 parsenetmask(slash + 1, netmask);
129 *slash = 0;
130 } else
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)
149 netmask <<= 1;
150 if (netmask != 0)
151 return 0;
152 return 1;
155 /* validate network/netmask pair */
156 inline int valid_network_and_netmask(struct t_ipt_account_info *info) {
157 if (!valid_netmask(info->netmask))
158 return 0;
159 if ((info->network & info->netmask) != info->network)
160 return 0;
161 return 1;
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;
176 info->table = NULL;
180 /* Function parses match's arguments */
181 static int parse(int c, char **argv,
182 int invert,
183 unsigned int *flags,
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;
190 switch (c) {
192 /* --aaddr */
193 case 201:
194 parse_network(optarg, info);
195 if (!valid_network_and_netmask(info))
196 exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
197 *flags = 1;
198 break;
200 /* --aname */
201 case 202:
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';
205 } else
206 exit_error(PARAMETER_PROBLEM, "account: Too long table name");
207 break;
208 /* --ashort */
209 case 203:
210 info->shortlisting = 1;
211 break;
212 default:
213 return 0;
215 return 1;
218 /* Final check whether network/netmask was specified */
219 static void final_check(unsigned int flags) {
220 if (!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,
227 int numeric) {
229 struct t_ipt_account_info *info = (struct t_ipt_account_info *)match->data;
231 printf("account: ");
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;
249 printf("--aaddr ");
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)
257 printf("--ashort ");
260 static struct iptables_match account = {
261 .next = NULL,
262 .name = "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)),
266 .help = &help,
267 .init = &init,
268 .parse = &parse,
269 .final_check = &final_check,
270 .print = &print,
271 .save = &save,
272 .extra_opts = opts
275 /* Function which registers match */
276 void _init(void)
278 register_match(&account);