2 * This is a module which is used for counting packets.
4 #include <linux/module.h>
5 #include <linux/skbuff.h>
7 #include <linux/spinlock.h>
11 #include <linux/netfilter_ipv4/ip_tables.h>
14 #include <net/route.h>
15 #include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
20 //#define DEBUGP(format, args...)
23 struct ipt_account_table *ipt_account_tables = NULL;
24 struct ipt_account_handle *ipt_account_handles = NULL;
26 static spinlock_t ipt_account_lock = SPIN_LOCK_UNLOCKED;
29 ipt_account_target(struct sk_buff **pskb,
31 const struct net_device *in,
32 const struct net_device *out,
36 spin_lock_bh(&ipt_account_lock);
37 spin_unlock_bh(&ipt_account_lock);
42 /* Recursive free of all data structures */
43 void ipt_account_data_free(void *data, unsigned char depth)
49 // Free for 8 bit network
52 free_page((unsigned long)data);
57 // Free for 16 bit network
60 struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16 *)data;
62 for (b=0; b < 255; b++)
64 if (mask_16->mask_24[b] != 0)
66 free_page((unsigned long)mask_16->mask_24[b]);
67 mask_16->mask_24[b] = NULL;
70 free_page((unsigned long)data);
75 // Free for 24 bit network
79 for (a=0; a < 255; a++)
81 if (((struct ipt_account_mask_8 *)data)->mask_16[a])
83 struct ipt_account_mask_16 *mask_16 = (struct ipt_account_mask_16*)((struct ipt_account_mask_8 *)data)->mask_16[a];
84 for (b=0; b < 255; b++)
86 if (mask_16->mask_24[b]) {
87 free_page((unsigned long)mask_16->mask_24[b]);
88 mask_16->mask_24[b] = NULL;
91 free_page((unsigned long)mask_16);
95 free_page((unsigned long)data);
100 printk("ACCOUNT: ipt_account_data_free called with unknown depth: %d\n", depth);
104 /* Look for existing table / insert new one. Return internal ID or -1 on error */
105 int ipt_account_table_insert(char *name, unsigned int ip, unsigned int netmask)
109 DEBUGP("ACCOUNT: ipt_account_table_insert: %s, %u.%u.%u.%u/%u.%u.%u.%u\n", name, NIPQUAD(ip), NIPQUAD(netmask));
111 // Look for existing table
112 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
114 if (strcmp(ipt_account_tables[i].name, name) == 0)
116 DEBUGP("ACCOUNT: Found existing slot: %d - %u.%u.%u.%u/%u.%u.%u.%u\n", i,
117 NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
119 if (ipt_account_tables[i].ip != ip || ipt_account_tables[i].netmask != netmask)
121 printk("ACCOUNT: Table %s found, but IP/netmask mismatch. IP/netmask found: %u.%u.%u.%u/%u.%u.%u.%u\n",
122 name, NIPQUAD(ipt_account_tables[i].ip), NIPQUAD(ipt_account_tables[i].netmask));
126 ipt_account_tables[i].refcount++;
127 DEBUGP("ACCOUNT: Refcount: %d\n", ipt_account_tables[i].refcount);
133 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
136 if (ipt_account_tables[i].name[0] == 0)
138 DEBUGP("ACCOUNT: Found free slot: %d\n", i);
140 strncpy (ipt_account_tables[i].name, name, ACCOUNT_TABLE_NAME_LEN-1);
142 ipt_account_tables[i].ip = ip;
143 ipt_account_tables[i].netmask = netmask;
146 unsigned int j, calc_mask, netsize=0;
147 calc_mask = htonl(netmask);
148 for (j = 31; j > 0; j--)
150 if (calc_mask&(1<<j))
156 // Calculate depth from netsize
158 ipt_account_tables[i].depth = 0;
159 else if (netsize >= 16)
160 ipt_account_tables[i].depth = 1;
161 else if(netsize >= 8)
162 ipt_account_tables[i].depth = 2;
164 printk("ACCOUNT: calculated netsize: %u -> ipt_account_table depth %u\n", netsize, ipt_account_tables[i].depth);
166 ipt_account_tables[i].refcount++;
167 if (!(ipt_account_tables[i].data = (void *)get_zeroed_page(GFP_KERNEL)))
169 printk("ACCOUNT: out of memory for data of table: %s\n", name);
170 memset(&ipt_account_tables[i], 0, sizeof(struct ipt_account_table));
178 // No free slot found
179 printk("ACCOUNT: No free table slot found (max: %d). Please increase ACCOUNT_MAX_TABLES.\n", ACCOUNT_MAX_TABLES);
183 static int ipt_account_checkentry(const char *tablename,
184 const struct ipt_entry *e,
186 unsigned int targinfosize,
187 unsigned int hook_mask)
189 struct ipt_account_info *info = targinfo;
191 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
192 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
193 targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
197 spin_lock_bh(&ipt_account_lock);
198 int table_nr = ipt_account_table_insert(info->table_name, info->net_ip, info->net_mask);
201 printk("ACCOUNT: Table insert problem. Aborting\n");
202 spin_unlock_bh(&ipt_account_lock);
205 // Table nr caching so we don't have to do an extra string compare for every packet
206 info->table_nr = table_nr;
208 spin_unlock_bh(&ipt_account_lock);
213 void ipt_account_deleteentry(void *targinfo, unsigned int targinfosize)
216 struct ipt_account_info *info = targinfo;
218 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_account_info))) {
219 DEBUGP("ACCOUNT: targinfosize %u != %u\n",
220 targinfosize, IPT_ALIGN(sizeof(struct ipt_account_info)));
223 spin_lock_bh(&ipt_account_lock);
225 DEBUGP("ACCOUNT: ipt_account_deleteentry called for table: %s (#%d)\n", info->table_name, info->table_nr);
227 info->table_nr = -1; // Set back to original state
230 for (i = 0; i < ACCOUNT_MAX_TABLES; i++)
232 if (strcmp(ipt_account_tables[i].name, info->table_name) == 0)
234 DEBUGP("ACCOUNT: Found table at slot: %d\n", i);
236 ipt_account_tables[i].refcount--;
237 DEBUGP("ACCOUNT: Refcount left: %d\n", ipt_account_tables[i].refcount);
239 // Table not needed anymore?
240 if (ipt_account_tables[i].refcount == 0)
242 DEBUGP("ACCOUNT: Destroying table at slot: %d\n", i);
243 ipt_account_data_free(ipt_account_tables[i].data, ipt_account_tables[i].depth);
244 memset(&ipt_account_tables[i], 0, sizeof(struct ipt_account_table));
247 spin_unlock_bh(&ipt_account_lock);
253 printk("ACCOUNT: Table %s not found for destroy\n", info->table_name);
254 spin_unlock_bh(&ipt_account_lock);
257 static struct ipt_target ipt_account_reg
258 = { { NULL, NULL }, "ACCOUNT", ipt_account_target, ipt_account_checkentry, ipt_account_deleteentry,
261 static int __init init(void)
263 if (!(ipt_account_tables = kmalloc(ACCOUNT_MAX_TABLES*sizeof(struct ipt_account_table), GFP_KERNEL)))
265 printk("ACCOUNT: Out of memory allocating account_tables structure");
268 memset(ipt_account_tables, 0, ACCOUNT_MAX_TABLES*sizeof(struct ipt_account_table));
270 if (!(ipt_account_handles = kmalloc(ACCOUNT_MAX_HANDLES*sizeof(struct ipt_account_handle), GFP_KERNEL)))
272 printk("ACCOUNT: Out of memory allocating account_handles structure");
273 kfree (ipt_account_tables);
274 ipt_account_tables = NULL;
277 memset(ipt_account_handles, 0, ACCOUNT_MAX_HANDLES*sizeof(struct ipt_account_handle));
279 if (ipt_register_target(&ipt_account_reg))
285 static void __exit fini(void)
287 ipt_unregister_target(&ipt_account_reg);
289 kfree(ipt_account_tables);
290 ipt_account_tables = NULL;
292 kfree(ipt_account_handles);
293 ipt_account_handles = NULL;
298 MODULE_LICENSE("GPL");