iptables: (tomj) fixed IPs ending with 255, fixed double count issue
[ipt_ACCOUNT] / linux / net / ipv4 / netfilter / ipt_ACCOUNT.c
CommitLineData
70288420
TJ
1/*
2 * This is a module which is used for counting packets.
3 */
4#include <linux/module.h>
5#include <linux/skbuff.h>
6#include <linux/ip.h>
7#include <linux/spinlock.h>
8#include <net/icmp.h>
9#include <net/udp.h>
10#include <net/tcp.h>
11#include <linux/netfilter_ipv4/ip_tables.h>
12
13struct in_device;
14#include <net/route.h>
15#include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
16
17//#if 0
18#define DEBUGP printk
19//#else
20//#define DEBUGP(format, args...)
21//#endif
22
23struct ipt_account_table *ipt_account_tables = NULL;
24struct ipt_account_handle *ipt_account_handles = NULL;
25
26static spinlock_t ipt_account_lock = SPIN_LOCK_UNLOCKED;
27
70288420 28/* Recursive free of all data structures */
850cece6 29void ipt_account_data_free(void *data, unsigned char depth)
70288420
TJ
30{
31 // Empty data set
32 if (!data)
33 return;
34
850cece6
TJ
35 // Free for 8 bit network
36 if (depth == 0)
70288420 37 {
850cece6 38 free_page((unsigned long)data);
70288420
TJ
39 data = NULL;
40 return;
41 }
42
43 // Free for 16 bit network
850cece6 44 if (depth == 1)
70288420
TJ
45 {
46 struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16 *)data;
4adc8355
TJ
47 unsigned int b;
48 for (b=0; b <= 255; b++)
70288420
TJ
49 {
50 if (mask_16->mask_24[b] != 0)
51 {
850cece6 52 free_page((unsigned long)mask_16->mask_24[b]);
70288420
TJ
53 mask_16->mask_24[b] = NULL;
54 }
55 }
850cece6 56 free_page((unsigned long)data);
70288420
TJ
57 data = NULL;
58 return;
59 }
60
61 // Free for 24 bit network
850cece6 62 if (depth == 3)
70288420 63 {
4adc8355
TJ
64 unsigned int a, b;
65 for (a=0; a <= 255; a++)
70288420
TJ
66 {
67 if (((struct ipt_account_mask_8 *)data)->mask_16[a])
68 {
69 struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16*)((struct ipt_account_mask_8 *)data)->mask_16[a];
4adc8355 70 for (b=0; b <= 255; b++)
70288420
TJ
71 {
72 if (mask_16->mask_24[b]) {
850cece6 73 free_page((unsigned long)mask_16->mask_24[b]);
70288420
TJ
74 mask_16->mask_24[b] = NULL;
75 }
76 }
850cece6 77 free_page((unsigned long)mask_16);
70288420
TJ
78 mask_16 = NULL;
79 }
80 }
850cece6 81 free_page((unsigned long)data);
70288420
TJ
82 data = NULL;
83 return;
84 }
85
850cece6 86 printk("ACCOUNT: ipt_account_data_free called with unknown depth: %d\n", depth);
70288420
TJ
87 return;
88}
89
90/* Look for existing table / insert new one. Return internal ID or -1 on error */
91int ipt_account_table_insert(char *name, unsigned int ip, unsigned int netmask)
92{
93 unsigned int i;
94
850cece6 95 DEBUGP("ACCOUNT: ipt_account_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", name, NIPQUAD(ip), NIPQUAD(netmask));
70288420
TJ
96
97 // Look for existing table
98 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
99 {
bea3921b 100 if (strncmp(ipt_account_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN) == 0)
70288420 101 {
850cece6
TJ
102 DEBUGP("ACCOUNT: Found existing slot: %d - %u.%u.%u.%u/%u.%u.%u.%u\n", i,
103 NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
70288420
TJ
104
105 if (ipt_account_tables[i].ip != ip || ipt_account_tables[i].netmask != netmask)
106 {
850cece6
TJ
107 printk("ACCOUNT: Table %s found, but IP/netmask mismatch. IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
108 name, NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
70288420
TJ
109 return -1;
110 }
111
112 ipt_account_tables[i].refcount++;
113 DEBUGP("ACCOUNT: Refcount: %d\n", ipt_account_tables[i].refcount);
114 return i;
115 }
116 }
117
118 // Insert new table
119 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
120 {
121 // Found free slot
122 if (ipt_account_tables[i].name[0] == 0)
123 {
124 DEBUGP("ACCOUNT: Found free slot: %d\n", i);
125
126 strncpy (ipt_account_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1);
127
128 ipt_account_tables[i].ip = ip;
129 ipt_account_tables[i].netmask = netmask;
130
850cece6
TJ
131 // Calculate netsize
132 unsigned int j, calc_mask, netsize=0;
70288420
TJ
133 calc_mask = htonl(netmask);
134 for (j = 31; j > 0; j--)
135 {
136 if (calc_mask&(1<<j))
850cece6 137 netsize++;
70288420
TJ
138 else
139 break;
140 }
850cece6
TJ
141
142 // Calculate depth from netsize
143 if (netsize >= 24)
144 ipt_account_tables[i].depth = 0;
145 else if (netsize >= 16)
146 ipt_account_tables[i].depth = 1;
147 else if(netsize >= 8)
148 ipt_account_tables[i].depth = 2;
149
150 printk("ACCOUNT: calculated netsize: %u -> ipt_account_table depth %u\n", netsize, ipt_account_tables[i].depth);
70288420
TJ
151
152 ipt_account_tables[i].refcount++;
153 if (!(ipt_account_tables[i].data = (void *)get_zeroed_page(GFP_KERNEL)))
154 {
850cece6 155 printk("ACCOUNT: out of memory for data of table: %s\n", name);
70288420
TJ
156 memset(&ipt_account_tables[i], 0, sizeof(struct ipt_account_table));
157 return -1;
158 }
850cece6 159
70288420
TJ
160 return i;
161 }
162 }
163
164 // No free slot found
165 printk("ACCOUNT: No free table slot found (max: %d). Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES);
166 return -1;
167}
168
169static int ipt_account_checkentry(const char *tablename,
170 const struct ipt_entry *e,
171 void *targinfo,
172 unsigned int targinfosize,
173 unsigned int hook_mask)
174{
175 struct ipt_account_info *info = targinfo;
176
177 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
178 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
179 targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
180 return 0;
181 }
182
850cece6 183 spin_lock_bh(&ipt_account_lock);
70288420
TJ
184 int table_nr = ipt_account_table_insert(info->table_name, info->net_ip, info->net_mask);
185 if (table_nr == -1)
186 {
187 printk("ACCOUNT: Table insert problem. Aborting\n");
850cece6 188 spin_unlock_bh(&ipt_account_lock);
70288420
TJ
189 return 0;
190 }
70288420
TJ
191 // Table nr caching so we don't have to do an extra string compare for every packet
192 info->table_nr = table_nr;
193
850cece6
TJ
194 spin_unlock_bh(&ipt_account_lock);
195
70288420
TJ
196 return 1;
197}
198
850cece6
TJ
199void ipt_account_deleteentry(void *targinfo, unsigned int targinfosize)
200{
201 unsigned int i;
202 struct ipt_account_info *info = targinfo;
203
204 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
205 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
206 targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
207 }
208
209 spin_lock_bh(&ipt_account_lock);
210
211 DEBUGP("ACCOUNT: ipt_account_deleteentry called for table: %s (#%d)\n", info->table_name, info->table_nr);
212
213 info->table_nr = -1; // Set back to original state
214
215 // Look for table
216 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
217 {
bea3921b 218 if (strncmp(ipt_account_tables[i].name, info->table_name, ACCOUNT_TABLE_NAME_LEN) == 0)
850cece6
TJ
219 {
220 DEBUGP("ACCOUNT: Found table at slot: %d\n", i);
221
222 ipt_account_tables[i].refcount--;
223 DEBUGP("ACCOUNT: Refcount left: %d\n", ipt_account_tables[i].refcount);
224
225 // Table not needed anymore?
226 if (ipt_account_tables[i].refcount == 0)
227 {
228 DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i);
229 ipt_account_data_free(ipt_account_tables[i].data, ipt_account_tables[i].depth);
230 memset(&ipt_account_tables[i], 0, sizeof(struct ipt_account_table));
231 }
232
233 spin_unlock_bh(&ipt_account_lock);
234 return;
235 }
236 }
237
238 // Table not found
239 printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
240 spin_unlock_bh(&ipt_account_lock);
241}
242
4068e14d
TJ
243void ipt_account_depth0_insert(struct ipt_account_mask_24 *mask_24, unsigned int net_ip, unsigned int netmask,
244 unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount)
245{
246 unsigned char is_src = 0, is_dst = 0;
247
248 DEBUGP("ACCOUNT: ipt_account_depth0_insert: %u.%u.%u.%u/%u.%u.%u.%u for net %u.%u.%u.%u/%u.%u.%u.%u, size: %u\n",
249 NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask), size);
250
251 // Check if src/dst is inside our network.
252 // Special: net_ip = 0.0.0.0/0 gets stored as src in slot 0
253 if (!netmask)
254 src_ip = 0;
255 if ((net_ip&netmask) == (src_ip&netmask))
256 is_src = 1;
257 if ((net_ip&netmask) == (dst_ip&netmask) && netmask)
258 is_dst = 1;
259
260 if (!is_src && !is_dst)
261 {
262 DEBUGP("ACCOUNT: Skipping packet %u.%u.%u.%u/%u.%u.%u.%u for net %u.%u.%u.%u/%u.%u.%u.%u\n",
263 NIPQUAD(src_ip), NIPQUAD(dst_ip), NIPQUAD(net_ip), NIPQUAD(netmask));
264 return;
265 }
266
267 // Check if this entry is new
fa9124c2 268 char is_src_new_ip = 0, is_dst_new_ip = 0;
ff4ee64d
TJ
269
270 // Calculate array positions
271 unsigned char src_slot = (unsigned char)((src_ip&0xFF000000) >> 24);
272 unsigned char dst_slot = (unsigned char)((dst_ip&0xFF000000) >> 24);
4068e14d
TJ
273
274 // Increase size counters
275 if (is_src)
276 {
277 // Calculate network slot
5dbfa65d 278 DEBUGP("ACCOUNT: Calculated SRC 8 bit network slot: %d\n", src_slot);
ff4ee64d 279 if (!mask_24->ip[src_slot].src_packets && !mask_24->ip[src_slot].dst_packets)
fa9124c2 280 is_src_new_ip = 1;
4068e14d 281
ff4ee64d
TJ
282 mask_24->ip[src_slot].src_packets++;
283 mask_24->ip[src_slot].src_bytes+=size;
4068e14d
TJ
284 }
285 if (is_dst)
286 {
5dbfa65d 287 DEBUGP("ACCOUNT: Calculated DST 8 bit network slot: %d\n", dst_slot);
ff4ee64d 288 if (!mask_24->ip[dst_slot].src_packets && !mask_24->ip[dst_slot].dst_packets)
fa9124c2 289 is_dst_new_ip = 1;
4068e14d 290
ff4ee64d
TJ
291 mask_24->ip[dst_slot].dst_packets++;
292 mask_24->ip[dst_slot].dst_bytes+=size;
4068e14d
TJ
293 }
294
fa9124c2 295 // Increase itemcounter
4adc8355 296 DEBUGP("ACCOUNT: Itemcounter before: %d\n", *itemcount);
ff4ee64d 297 if (src_slot == dst_slot)
fa9124c2 298 {
4adc8355
TJ
299 if (is_src_new_ip || is_dst_new_ip) {
300 DEBUGP("ACCOUNT: src_slot == dst_slot: %d, %d\n", is_src_new_ip, is_dst_new_ip);
fa9124c2 301 (*itemcount)++;
4adc8355 302 }
fa9124c2 303 } else {
4adc8355
TJ
304 if (is_src_new_ip) {
305 DEBUGP("ACCOUNT: New src_ip: %u.%u.%u.%u\n", NIPQUAD(src_ip));
fa9124c2 306 (*itemcount)++;
4adc8355
TJ
307 }
308 if (is_dst_new_ip) {
309 DEBUGP("ACCOUNT: New dst_ip: %u.%u.%u.%u\n", NIPQUAD(dst_ip));
fa9124c2 310 (*itemcount)++;
4adc8355 311 }
fa9124c2 312 }
4adc8355 313 DEBUGP("ACCOUNT: Itemcounter after: %d\n", *itemcount);
4068e14d
TJ
314}
315
316void ipt_account_depth1_insert(struct ipt_account_mask_16 *mask_16, unsigned int net_ip, unsigned int netmask,
317 unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount)
318{
319 // Do we need to process src IP?
320 if ((net_ip&netmask) == (src_ip&netmask))
321 {
322 unsigned char slot = (unsigned char)((src_ip&0x00FF0000) >> 16);
323 DEBUGP("ACCOUNT: Calculated SRC 16 bit network slot: %d\n", slot);
324
325 // Do we need to create a new mask_24 bucket?
326 if (!mask_16->mask_24[slot] && !(mask_16->mask_24[slot] = (void *)get_zeroed_page(GFP_KERNEL)))
327 {
328 printk("ACCOUNT: Can't process packet because out of memory!\n");
329 return;
330 }
331
332 ipt_account_depth0_insert((struct ipt_account_mask_24 *)mask_16->mask_24[slot], net_ip, netmask,
4adc8355 333 src_ip, 0, size, itemcount);
4068e14d
TJ
334 }
335
336 // Do we need to process dst IP?
337 if ((net_ip&netmask) == (dst_ip&netmask))
338 {
339 unsigned char slot = (unsigned char)((dst_ip&0x00FF0000) >> 16);
340 DEBUGP("ACCOUNT: Calculated DST 16 bit network slot: %d\n", slot);
341
342 // Do we need to create a new mask_24 bucket?
343 if (!mask_16->mask_24[slot] && !(mask_16->mask_24[slot] = (void *)get_zeroed_page(GFP_KERNEL)))
344 {
345 printk("ACCOUT: Can't process packet because out of memory!\n");
346 return;
347 }
348
349 ipt_account_depth0_insert((struct ipt_account_mask_24 *)mask_16->mask_24[slot], net_ip, netmask,
4adc8355 350 0, dst_ip, size, itemcount);
4068e14d
TJ
351 }
352}
353
354void ipt_account_depth2_insert(struct ipt_account_mask_8 *mask_8, unsigned int net_ip, unsigned int netmask,
355 unsigned int src_ip, unsigned int dst_ip, unsigned int size, unsigned int *itemcount)
356{
357 // Do we need to process src IP?
358 if ((net_ip&netmask) == (src_ip&netmask))
359 {
360 unsigned char slot = (unsigned char)((src_ip&0x0000FF00) >> 8);
361 DEBUGP("ACCOUNT: Calculated SRC 24 bit network slot: %d\n", slot);
362
363 // Do we need to create a new mask_24 bucket?
364 if (!mask_8->mask_16[slot] && !(mask_8->mask_16[slot] = (void *)get_zeroed_page(GFP_KERNEL)))
365 {
366 printk("ACCOUNT: Can't process packet because out of memory!\n");
367 return;
368 }
369
370 ipt_account_depth1_insert((struct ipt_account_mask_16 *)mask_8->mask_16[slot], net_ip, netmask,
4adc8355 371 src_ip, 0, size, itemcount);
4068e14d
TJ
372 }
373
374 // Do we need to process dst IP?
375 if ((net_ip&netmask) == (dst_ip&netmask))
376 {
377 unsigned char slot = (unsigned char)((dst_ip&0x0000FF00) >> 8);
378 DEBUGP("ACCOUNT: Calculated DST 24 bit network slot: %d\n", slot);
379
380 // Do we need to create a new mask_24 bucket?
381 if (!mask_8->mask_16[slot] && !(mask_8->mask_16[slot] = (void *)get_zeroed_page(GFP_KERNEL)))
382 {
383 printk("ACCOUNT: Can't process packet because out of memory!\n");
384 return;
385 }
386
387 ipt_account_depth1_insert((struct ipt_account_mask_16 *)mask_8->mask_16[slot], net_ip, netmask,
4adc8355 388 0, dst_ip, size, itemcount);
4068e14d
TJ
389 }
390}
391
392static unsigned int ipt_account_target(struct sk_buff **pskb,
393 unsigned int hooknum,
394 const struct net_device *in,
395 const struct net_device *out,
396 const void *targinfo,
397 void *userinfo)
398{
399 const struct ipt_account_info *info = (const struct ipt_account_info *)targinfo;
400 unsigned int src_ip = (*pskb)->nh.iph->saddr;
401 unsigned int dst_ip = (*pskb)->nh.iph->daddr;
402 unsigned int size = ntohs((*pskb)->nh.iph->tot_len);
403
404 spin_lock_bh(&ipt_account_lock);
405
406 if (ipt_account_tables[info->table_nr].name[0] == 0)
407 {
408 printk("ACCOUNT: ipt_account_target: Invalid table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n",
409 info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip));
410 spin_unlock_bh(&ipt_account_lock);
411 return IPT_CONTINUE;
412 }
413
414 // 8 bit network or "any" network
415 if (ipt_account_tables[info->table_nr].depth == 0)
416 {
417 // Count packet and check if the IP is new
418 ipt_account_depth0_insert((struct ipt_account_mask_24 *)ipt_account_tables[info->table_nr].data,
419 ipt_account_tables[info->table_nr].ip, ipt_account_tables[info->table_nr].netmask,
420 src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
421 spin_unlock_bh(&ipt_account_lock);
422 return IPT_CONTINUE;
423 }
424
425 // 16 bit network
426 if (ipt_account_tables[info->table_nr].depth == 1)
427 {
428 ipt_account_depth1_insert((struct ipt_account_mask_16 *)ipt_account_tables[info->table_nr].data,
429 ipt_account_tables[info->table_nr].ip, ipt_account_tables[info->table_nr].netmask,
430 src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
431 spin_unlock_bh(&ipt_account_lock);
432 return IPT_CONTINUE;
433 }
434
435 // 24 bit network
436 if (ipt_account_tables[info->table_nr].depth == 2)
437 {
438 ipt_account_depth2_insert((struct ipt_account_mask_8 *)ipt_account_tables[info->table_nr].data,
439 ipt_account_tables[info->table_nr].ip, ipt_account_tables[info->table_nr].netmask,
440 src_ip, dst_ip, size, &ipt_account_tables[info->table_nr].itemcount);
441 spin_unlock_bh(&ipt_account_lock);
442 return IPT_CONTINUE;
443 }
444
445 printk("ACCOUNT: ipt_account_target: Unable to process packet. Table id %u. IPs %u.%u.%u.%u/%u.%u.%u.%u\n",
446 info->table_nr, NIPQUAD(src_ip), NIPQUAD(dst_ip));
447
448 spin_unlock_bh(&ipt_account_lock);
449 return IPT_CONTINUE;
450}
451
bea3921b
TJ
452/*
453 Functions dealing with "handles":
454 Handles are snapshots of a accounting state.
455
456 read snapshots are only for debugging the code
457 and are very expensive concerning speed/memory
458 compared to read_and_flush.
459
460 The functions aren't protected by spinlocks themselves
461 as this is done in the ioctl part of the code.
462*/
463
464/*
465 Find a free handle slot. Normally only one should be used,
466 but there could be two or more applications accessing the data
467 at the same time.
468*/
469int ipt_account_handle_find_slot(void)
470{
471 unsigned int i;
472 // Insert new table
473 for (i = 0; i < ACCOUNT_MAX_HANDLES; i++)
474 {
475 // Found free slot
476 if (ipt_account_handles[i].data == NULL)
477 {
478 // Don't "mark" data as used as we are protected by a spinlock by the calling function.
479 // handle_find_slot() is only a function to prevent code duplication.
480 return i;
481 }
482 }
483
484 // No free slot found
485 printk("ACCOUNT: No free handle slot found (max: %u). Please increase ACCOUNT_MAX_HANDLES.\n", ACCOUNT_MAX_HANDLES);
486 return -1;
487}
488
489int ipt_account_handle_free(unsigned int handle)
490{
491 if (handle >= ACCOUNT_MAX_HANDLES)
492 {
493 printk("ACCOUNT: Invalid handle for ipt_account_handle_free() specified: %u\n", handle);
494 return -EINVAL;
495 }
496
497 ipt_account_data_free(ipt_account_handles[handle].data, ipt_account_handles[handle].depth);
498 memset (&ipt_account_handles[handle], 0, sizeof (struct ipt_account_handle));
499 return 0;
500}
501
502/* Prepare data for read without flush. Use only for debugging!
503 Real applications should use read&flush as it's way more efficent */
504int ipt_account_handle_prepare_read(char *tablename, unsigned int *count)
505{
506 int handle, i, table_nr=-1;
507
508 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
509 if (strncmp(ipt_account_tables[i].name, tablename, ACCOUNT_TABLE_NAME_LEN) == 0)
510 {
511 table_nr = i;
512 break;
513 }
514
515 if (table_nr == -1)
516 {
517 printk("ACCOUNT: ipt_account_handle_prepare_read(): Table %s not found\n", tablename);
518 return -1;
519 }
520
521 // Can't find a free handle slot?
522 if ((handle = ipt_account_handle_find_slot()) == -1)
523 return -1;
524
525 // Fill up handle structure
526 ipt_account_handles[handle].ip = ipt_account_tables[table_nr].ip;
527 ipt_account_handles[handle].depth = ipt_account_tables[table_nr].depth;
528 ipt_account_handles[handle].itemcount = ipt_account_tables[table_nr].itemcount;
529
530 // allocate "root" table
531 if (!(ipt_account_handles[handle].data = (void*)get_zeroed_page(GFP_KERNEL)))
532 {
533 printk("ACCOUNT: out of memory for root table in ipt_account_handle_prepare_read()\n");
534 memset (&ipt_account_handles[handle], 0, sizeof(struct ipt_account_handle));
535 return -1;
536 }
537
538 // Recursive copy of complete data structure
539 unsigned int depth = ipt_account_handles[handle].depth;
540 if (depth == 0)
541 {
542 memcpy(ipt_account_handles[handle].data, ipt_account_tables[table_nr].data, sizeof(struct ipt_account_mask_24));
543 } else if (depth == 1) {
544 struct ipt_account_mask_16 *src_16 = (struct ipt_account_mask_16 *)ipt_account_tables[table_nr].data;
545 struct ipt_account_mask_16 *network_16 = (struct ipt_account_mask_16 *)ipt_account_handles[handle].data;
4adc8355 546 unsigned int b;
bea3921b 547
4adc8355 548 for (b = 0; b <= 255; b++)
bea3921b
TJ
549 {
550 if (src_16->mask_24[b])
551 {
552 if (!(network_16->mask_24[b] = (void*)get_zeroed_page(GFP_KERNEL)))
553 {
554 printk("ACCOUNT: out of memory during copy of 16 bit network in ipt_account_handle_prepare_read()\n");
555 ipt_account_data_free(ipt_account_handles[handle].data, depth);
556 memset (&ipt_account_handles[handle], 0, sizeof(struct ipt_account_handle));
557 return -1;
558 }
559
560 memcpy(network_16->mask_24[b], src_16->mask_24[b], sizeof(struct ipt_account_mask_24));
561 }
562 }
563 } else if(depth == 2) {
564 struct ipt_account_mask_8 *src_8 = (struct ipt_account_mask_8 *)ipt_account_tables[table_nr].data;
565 struct ipt_account_mask_8 *network_8 = (struct ipt_account_mask_8 *)ipt_account_handles[handle].data;
4adc8355 566 unsigned int a;
bea3921b 567
4adc8355 568 for (a = 0; a <= 255; a++)
bea3921b
TJ
569 {
570 if (src_8->mask_16[a])
571 {
572 if (!(network_8->mask_16[a] = (void*)get_zeroed_page(GFP_KERNEL)))
573 {
574 printk("ACCOUNT: out of memory during copy of 24 bit network in ipt_account_handle_prepare_read()\n");
575 ipt_account_data_free(ipt_account_handles[handle].data, depth);
576 memset (&ipt_account_handles[handle], 0, sizeof(struct ipt_account_handle));
577 return -1;
578 }
579
580 memcpy(network_8->mask_16[a], src_8->mask_16[a], sizeof(struct ipt_account_mask_16));
581
582 struct ipt_account_mask_16 *src_16 = src_8->mask_16[a];
583 struct ipt_account_mask_16 *network_16 = network_8->mask_16[a];
4adc8355 584 unsigned int b;
bea3921b 585
4adc8355 586 for (b = 0; b <= 255; b++)
bea3921b
TJ
587 {
588 if (src_16->mask_24[b])
589 {
590 if (!(network_16->mask_24[b] = (void*)get_zeroed_page(GFP_KERNEL)))
591 {
592 printk("ACCOUNT: out of memory during copy of 16 bit network in ipt_account_handle_prepare_read()\n");
593 ipt_account_data_free(ipt_account_handles[handle].data, depth);
594 memset (&ipt_account_handles[handle], 0, sizeof(struct ipt_account_handle));
595 return -1;
596 }
597
598 memcpy(network_16->mask_24[b], src_16->mask_24[b], sizeof(struct ipt_account_mask_24));
599 }
600 }
601 }
602 }
603 }
604
605 *count = ipt_account_tables[table_nr].itemcount;
606 return handle;
607}
608
609/* Prepare data for read and flush it */
610int ipt_account_handle_prepare_read_flush(char *tablename, unsigned int *count)
611{
612 int handle, i, table_nr=-1;
613
614 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
615 if (strncmp(ipt_account_tables[i].name, tablename, ACCOUNT_TABLE_NAME_LEN) == 0)
616 {
617 table_nr = i;
618 break;
619 }
620
621 if (table_nr == -1)
622 {
623 printk("ACCOUNT: ipt_account_handle_prepare_read_flush(): Table %s not found\n", tablename);
624 return -1;
625 }
626
627 // Can't find a free handle slot?
628 if ((handle = ipt_account_handle_find_slot()) == -1)
629 return -1;
630
631 // Fill up handle structure
632 ipt_account_handles[handle].ip = ipt_account_tables[table_nr].ip;
633 ipt_account_handles[handle].depth = ipt_account_tables[table_nr].depth;
634 ipt_account_handles[handle].itemcount = ipt_account_tables[table_nr].itemcount;
635 ipt_account_handles[handle].data = ipt_account_tables[table_nr].data;
636 *count = ipt_account_tables[table_nr].itemcount;
637
638 // "Flush" table data
639 ipt_account_tables[table_nr].data = (void*)get_zeroed_page(GFP_KERNEL);
640 ipt_account_tables[table_nr].itemcount = 0;
641
642 return handle;
643}
644
645/* Copy the actual that into a prepared buffer.
646 We only copy entries != 0 to increase performance.
647 The memory gets freed again in ipt_account_handle_free().
648*/
649int ipt_account_handle_get_data(unsigned int handle, void *buffer)
650{
651 struct ipt_account_handle_ip handle_ip;
652 unsigned int handle_ip_size = sizeof (struct ipt_account_handle_ip);
4adc8355 653 unsigned int i;
bea3921b
TJ
654
655 if (handle >= ACCOUNT_MAX_HANDLES)
656 {
657 printk("ACCOUNT: invalid handle for ipt_account_handle_get_data() specified: %u\n", handle);
658 return -1;
659 }
660
661 if (ipt_account_handles[handle].data == NULL)
662 {
663 printk("ACCOUNT: handle %u is BROKEN: Contains no data\n", handle);
664 return -1;
665 }
666
667 // Check if at least packet src/dst matches ip/netmask
668 unsigned int net_ip = ipt_account_handles[handle].ip;
669 unsigned int depth = ipt_account_handles[handle].depth;
670
671 // 8 bit network
672 if (depth == 0)
673 {
674 struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)ipt_account_handles[handle].data;
4adc8355 675 for (i = 0; i <= 255; i++)
bea3921b
TJ
676 {
677 if (network->ip[i].src_packets || network->ip[i].dst_packets)
678 {
679 handle_ip.ip = net_ip | (i<<24);
680 handle_ip.src_packets = network->ip[i].src_packets;
681 handle_ip.src_bytes = network->ip[i].src_bytes;
682 handle_ip.dst_packets = network->ip[i].dst_packets;
683 handle_ip.dst_bytes = network->ip[i].dst_bytes;
684
685 copy_to_user(buffer, &handle_ip, handle_ip_size);
686 buffer += handle_ip_size;
687 }
688 }
689
690 return 0;
691 }
692
693 // 16 bit network
694 if (depth == 1)
695 {
696 struct ipt_account_mask_16 *network_16 = (struct ipt_account_mask_16*)ipt_account_handles[handle].data;
4adc8355
TJ
697 unsigned int b;
698 for (b = 0; b <= 255; b++)
bea3921b
TJ
699 {
700 if (network_16->mask_24[b])
701 {
702 struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)network_16->mask_24[b];
4adc8355 703 for (i = 0; i <= 255; i++)
bea3921b
TJ
704 {
705 if (network->ip[i].src_packets || network->ip[i].dst_packets)
706 {
707 handle_ip.ip = net_ip | (b << 16) | (i<<24);
708 handle_ip.src_packets = network->ip[i].src_packets;
709 handle_ip.src_bytes = network->ip[i].src_bytes;
710 handle_ip.dst_packets = network->ip[i].dst_packets;
711 handle_ip.dst_bytes = network->ip[i].dst_bytes;
712
713 copy_to_user(buffer, &handle_ip, handle_ip_size);
714 buffer += handle_ip_size;
715 }
716 }
717 }
718 }
719
720 return 0;
721 }
722
723 // 24 bit network
724 if (depth == 2)
725 {
726 struct ipt_account_mask_8 *network_8 = (struct ipt_account_mask_8*)ipt_account_handles[handle].data;
4adc8355
TJ
727 unsigned int a, b;
728 for (a = 0; a <= 255; a++)
bea3921b
TJ
729 {
730 if (network_8->mask_16[a])
731 {
732 struct ipt_account_mask_16 *network_16 = (struct ipt_account_mask_16*)network_8->mask_16[a];
4adc8355 733 for (b = 0; b <= 255; b++)
bea3921b
TJ
734 {
735 if (network_16->mask_24[b])
736 {
737 struct ipt_account_mask_24 *network = (struct ipt_account_mask_24*)network_16->mask_24[b];
4adc8355 738 for (i = 0; i <= 255; i++)
bea3921b
TJ
739 {
740 if (network->ip[i].src_packets || network->ip[i].dst_packets)
741 {
742 handle_ip.ip = net_ip | (a << 8) | (b << 16) | (i<<24);
743 handle_ip.src_packets = network->ip[i].src_packets;
744 handle_ip.src_bytes = network->ip[i].src_bytes;
745 handle_ip.dst_packets = network->ip[i].dst_packets;
746 handle_ip.dst_bytes = network->ip[i].dst_bytes;
747
748 copy_to_user(buffer, &handle_ip, handle_ip_size);
749 buffer += handle_ip_size;
750 }
751 }
752 }
753 }
754 }
755 }
756
757 return 0;
758 }
759
760 return -1;
761}
762
763static int ipt_account_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len)
764{
765 struct ipt_account_handle_sockopt handle;
766 int ret = -EINVAL;
767
768 if (!capable(CAP_NET_ADMIN))
769 return -EPERM;
770
771 switch (cmd)
772 {
773 case IPT_SO_SET_ACCOUNT_HANDLE_FREE:
774 if (len != sizeof(struct ipt_account_handle_sockopt))
775 {
776 printk("ACCOUNT: ipt_account_set_ctl: wrong data size (%u != %u) for IPT_SO_SET_HANDLE_FREE\n", len, sizeof(struct ipt_account_handle_sockopt));
777 break;
778 }
779
780 if (copy_from_user (&handle, user, len))
781 {
782 printk("ACCOUNT: ipt_account_set_ctl: copy_from_user failed for IPT_SO_SET_HANDLE_FREE\n");
783 break;
784 }
785
786 spin_lock_bh(&ipt_account_lock);
787 ret = ipt_account_handle_free(handle.handle_nr);
788 spin_unlock_bh(&ipt_account_lock);
789 break;
790 default:
791 printk("ACCOUNT: ipt_account_set_ctl: unknown request %i\n", cmd);
792 }
793
794 return ret;
795}
796
797static int ipt_account_get_ctl(struct sock *sk, int cmd, void *user, int *len)
798{
799 struct ipt_account_handle_sockopt handle;
800 int ret = -EINVAL;
801
802 if (!capable(CAP_NET_ADMIN))
803 return -EPERM;
804
805 switch (cmd)
806 {
807 case IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH:
808 case IPT_SO_GET_ACCOUNT_PREPARE_READ:
809 if (*len < sizeof(struct ipt_account_handle_sockopt))
810 {
811 printk("ACCOUNT: ipt_account_get_ctl: wrong data size (%u != %u) for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
812 *len, sizeof(struct ipt_account_handle_sockopt));
813 break;
814 }
815
816 if (copy_from_user (&handle, user, sizeof(struct ipt_account_handle_sockopt)))
817 {
818 printk("ACCOUNT: ipt_account_get_ctl: copy_from_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
819 break;
820 }
821
822 spin_lock_bh(&ipt_account_lock);
823 if (cmd == IPT_SO_GET_ACCOUNT_PREPARE_READ_FLUSH)
824 handle.handle_nr = ipt_account_handle_prepare_read_flush(handle.name, &handle.itemcount);
825 else
826 handle.handle_nr = ipt_account_handle_prepare_read(handle.name, &handle.itemcount);
827 spin_unlock_bh(&ipt_account_lock);
828
829 if (handle.handle_nr == -1)
830 {
831 printk("ACCOUNT: ipt_account_get_ctl: ipt_account_handle_prepare_read failed\n");
832 break;
833 }
834
835 if (copy_to_user(user, &handle, sizeof(struct ipt_account_handle_sockopt)))
836 {
837 printk("ACCOUNT: ipt_account_set_ctl: copy_to_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
838 break;
839 }
840 ret = 0;
841 break;
842 case IPT_SO_GET_ACCOUNT_GET_DATA:
843 if (*len < sizeof(struct ipt_account_handle_sockopt))
844 {
845 printk("ACCOUNT: ipt_account_get_ctl: wrong data size (%u != %u) for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n",
846 *len, sizeof(struct ipt_account_handle_sockopt));
847 break;
848 }
849
850 if (copy_from_user (&handle, user, sizeof(struct ipt_account_handle_sockopt)))
851 {
852 printk("ACCOUNT: ipt_account_get_ctl: copy_from_user failed for IPT_SO_GET_ACCOUNT_PREPARE_READ/READ_FLUSH\n");
853 break;
854 }
855
856 if (handle.handle_nr >= ACCOUNT_MAX_HANDLES)
857 {
858 printk("ACCOUNT: Invalid handle for IPT_SO_GET_ACCOUNT_GET_DATA: %u\n", handle.handle_nr);
859 break;
860 }
861
862 if (*len < ipt_account_handles[handle.handle_nr].itemcount*sizeof(struct ipt_account_handle_ip))
863 {
864 printk("ACCOUNT: ipt_account_get_ctl: not enough space (%u < %u) to store data from IPT_SO_GET_ACCOUNT_GET_DATA\n",
865 *len, ipt_account_handles[handle.handle_nr].itemcount*sizeof(struct ipt_account_handle_ip));
866 break;
867 }
868
869 spin_lock_bh(&ipt_account_lock);
870 ret = ipt_account_handle_get_data(handle.handle_nr, user);
871 spin_unlock_bh(&ipt_account_lock);
872 if (ret)
873 {
874 printk("ACCOUNT: ipt_account_get_ctl: ipt_account_handle_get_data failed for handle %u\n", handle.handle_nr);
875 break;
876 }
877
878 ret = 0;
879 break;
880
881 default:
882 printk("ACCOUNT: ipt_account_get_ctl: unknown request %i\n", cmd);
883 }
884
885 return ret;
886}
887
70288420 888static struct ipt_target ipt_account_reg
850cece6 889= { { NULL, NULL }, "ACCOUNT", ipt_account_target, ipt_account_checkentry, ipt_account_deleteentry,
70288420
TJ
890 THIS_MODULE };
891
bea3921b
TJ
892static struct nf_sockopt_ops ipt_account_sockopts
893= { { NULL, NULL }, PF_INET, IPT_SO_SET_ACCOUNT_HANDLE_FREE, IPT_SO_SET_ACCOUNT_MAX+1, ipt_account_set_ctl,
894 IPT_SO_GET_ACCOUNT_PREPARE_READ, IPT_SO_GET_ACCOUNT_MAX+1, ipt_account_get_ctl, 0, NULL };
895
70288420
TJ
896static int __init init(void)
897{
bea3921b
TJ
898 if (PAGE_SIZE < 4096)
899 {
900 printk("ACCOUNT: Sorry we need at least a PAGE_SIZE of 4096. Found: %lu\n", PAGE_SIZE);
901 return -EINVAL;
902 }
903
850cece6 904 if (!(ipt_account_tables = kmalloc(ACCOUNT_MAX_TABLES*sizeof(struct ipt_account_table), GFP_KERNEL)))
70288420 905 {
bea3921b
TJ
906 printk("ACCOUNT: Out of memory allocating account_tables structure");
907 return -EINVAL;
70288420 908 }
850cece6 909 memset(ipt_account_tables, 0, ACCOUNT_MAX_TABLES*sizeof(struct ipt_account_table));
70288420 910
850cece6 911 if (!(ipt_account_handles = kmalloc(ACCOUNT_MAX_HANDLES*sizeof(struct ipt_account_handle), GFP_KERNEL)))
70288420 912 {
bea3921b
TJ
913 printk("ACCOUNT: Out of memory allocating account_handles structure");
914 kfree (ipt_account_tables);
915 ipt_account_tables = NULL;
916 return -EINVAL;
70288420 917 }
850cece6 918 memset(ipt_account_handles, 0, ACCOUNT_MAX_HANDLES*sizeof(struct ipt_account_handle));
bea3921b
TJ
919
920 /* Register setsockopt */
921 if (nf_register_sockopt(&ipt_account_sockopts) < 0)
922 {
923 printk("ACCOUNT: Can't register sockopts. Aborting\n");
924
925 kfree (ipt_account_tables);
926 ipt_account_tables = NULL;
927 kfree(ipt_account_handles);
928 ipt_account_handles = NULL;
929
930 return -EINVAL;
931 }
70288420
TJ
932
933 if (ipt_register_target(&ipt_account_reg))
934 return -EINVAL;
935
936 return 0;
937}
938
939static void __exit fini(void)
940{
941 ipt_unregister_target(&ipt_account_reg);
942
bea3921b
TJ
943 nf_unregister_sockopt(&ipt_account_sockopts);
944
70288420
TJ
945 kfree(ipt_account_tables);
946 ipt_account_tables = NULL;
947
948 kfree(ipt_account_handles);
949 ipt_account_handles = NULL;
950}
951
952module_init(init);
953module_exit(fini);
954MODULE_LICENSE("GPL");