#define HASH_LOG 9
/* Defaults, these can be overridden on the module command-line. */
-static int ip_list_tot = 100;
-static int ip_pkt_list_tot = 20;
-static int ip_list_hash_size = 0;
-static int ip_list_perms = 0644;
+static unsigned int ip_list_tot = 100;
+static unsigned int ip_pkt_list_tot = 20;
+static unsigned int ip_list_hash_size = 0;
+static unsigned int ip_list_perms = 0644;
#ifdef DEBUG
static int debug = 1;
#endif
MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
MODULE_LICENSE("GPL");
-module_param(ip_list_tot, int, 0400);
-module_param(ip_pkt_list_tot, int, 0400);
-module_param(ip_list_hash_size, int, 0400);
-module_param(ip_list_perms, int, 0400);
+module_param(ip_list_tot, uint, 0400);
+module_param(ip_pkt_list_tot, uint, 0400);
+module_param(ip_list_hash_size, uint, 0400);
+module_param(ip_list_perms, uint, 0400);
#ifdef DEBUG
-module_param(debug, int, 0600);
-MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
+module_param(debug, bool, 0600);
+MODULE_PARM_DESC(debug,"enable debugging output");
#endif
MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
/* We protect r_list with this spinlock so two processors are not modifying
* the list at the same time.
*/
-static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(recent_lock);
#ifdef CONFIG_PROC_FS
/* Our /proc/net/ipt_recent entry */
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
+ const struct xt_match *match,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop);
/* Function to hash a given address into the hash table of table_size size */
-int hash_func(unsigned int addr, int table_size)
+static int hash_func(unsigned int addr, int table_size)
{
int result = 0;
unsigned int value = addr;
curr_table->table[count].last_seen = 0;
curr_table->table[count].addr = 0;
curr_table->table[count].ttl = 0;
- memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
curr_table->table[count].oldest_pkt = 0;
curr_table->table[count].time_pos = 0;
curr_table->time_info[count].position = count;
skb->nh.iph->daddr = 0;
/* Clear ttl since we have no way of knowing it */
skb->nh.iph->ttl = 0;
- match(skb,NULL,NULL,info,0,NULL);
+ match(skb,NULL,NULL,NULL,info,0,0,NULL);
kfree(skb->nh.iph);
out_free_skb:
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
+ const struct xt_match *match,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
int pkt_count, hits_found, ans;
location = time_info[curr_table->time_pos].position;
hash_table[r_list[location].hash_entry] = -1;
hash_table[hash_result] = location;
- memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
r_list[location].time_pos = curr_table->time_pos;
r_list[location].addr = addr;
r_list[location].ttl = ttl;
}
if(info->seconds && info->hit_count) {
for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
+ if(r_list[location].last_pkts[pkt_count] == 0) break;
if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;
}
if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
r_list[location].last_seen = 0;
r_list[location].addr = 0;
r_list[location].ttl = 0;
- memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
r_list[location].oldest_pkt = 0;
ans = !info->invert;
}
*/
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
+ const struct xt_match *match,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
#endif
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
-
/* seconds and hit_count only valid for CHECK/UPDATE */
if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
#endif
curr_table = vmalloc(sizeof(struct recent_ip_tables));
- if(curr_table == NULL) return -ENOMEM;
+ if(curr_table == NULL) return 0;
spin_lock_init(&curr_table->list_lock);
curr_table->next = NULL;
#endif
curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
- if(curr_table->table == NULL) { vfree(curr_table); return -ENOMEM; }
+ if(curr_table->table == NULL) { vfree(curr_table); return 0; }
memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
#ifdef DEBUG
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
- sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+ sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
#endif
- hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+ hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
#ifdef DEBUG
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
#endif
printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for pkt_list.\n");
vfree(curr_table->table);
vfree(curr_table);
- return -ENOMEM;
+ return 0;
}
for(c = 0; c < ip_list_tot; c++) {
curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
vfree(hold);
vfree(curr_table->table);
vfree(curr_table);
- return -ENOMEM;
+ return 0;
}
for(c = 0; c < ip_list_hash_size; c++) {
vfree(hold);
vfree(curr_table->table);
vfree(curr_table);
- return -ENOMEM;
+ return 0;
}
for(c = 0; c < ip_list_tot; c++) {
curr_table->time_info[c].position = c;
/* Create our proc 'status' entry. */
curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
if (!curr_table->status_proc) {
+ vfree(hold);
printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
/* Destroy the created table */
spin_lock_bh(&recent_lock);
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
#endif
spin_unlock_bh(&recent_lock);
- return -ENOMEM;
+ return 0;
}
while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
if(!curr_table) {
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
#endif
spin_unlock_bh(&recent_lock);
- return -ENOMEM;
+ return 0;
}
if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
spin_unlock_bh(&recent_lock);
vfree(curr_table->time_info);
vfree(curr_table->hash_table);
- vfree(hold);
vfree(curr_table->table);
vfree(curr_table);
- return -ENOMEM;
+ return 0;
}
curr_table->status_proc->owner = THIS_MODULE;
* up its memory.
*/
static void
-destroy(void *matchinfo, unsigned int matchsize)
+destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
{
const struct ipt_recent_info *info = matchinfo;
struct recent_ip_tables *curr_table, *last_table;
/* This is the structure we pass to ipt_register to register our
* module with iptables.
*/
-static struct ipt_match recent_match = {
- .name = "recent",
- .match = &match,
- .checkentry = &checkentry,
- .destroy = &destroy,
- .me = THIS_MODULE
+static struct ipt_match recent_match = {
+ .name = "recent",
+ .match = match,
+ .matchsize = sizeof(struct ipt_recent_info),
+ .checkentry = checkentry,
+ .destroy = destroy,
+ .me = THIS_MODULE
};
/* Kernel module initialization. */
-static int __init init(void)
+static int __init ipt_recent_init(void)
{
- int count;
+ int err, count;
printk(version);
#ifdef CONFIG_PROC_FS
if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
#endif
- return ipt_register_match(&recent_match);
+ err = ipt_register_match(&recent_match);
+ if (err)
+ remove_proc_entry("ipt_recent", proc_net);
+ return err;
}
/* Kernel module destruction. */
-static void __exit fini(void)
+static void __exit ipt_recent_fini(void)
{
ipt_unregister_match(&recent_match);
}
/* Register our module with the kernel. */
-module_init(init);
-module_exit(fini);
+module_init(ipt_recent_init);
+module_exit(ipt_recent_fini);