X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fipt_recent.c;h=b847ee409efbb7146987f526998ccb8ea51422fe;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=15472b3e9e563b9c569fc6d5e52f448323266190;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 15472b3e9..b847ee409 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -24,10 +24,10 @@ #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 @@ -38,13 +38,13 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost . htt MODULE_AUTHOR("Stephen Frost "); 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"); @@ -90,7 +90,7 @@ static struct recent_ip_tables *r_tables = NULL; /* 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 */ @@ -102,12 +102,14 @@ static int 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; @@ -223,7 +225,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned 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; @@ -317,7 +319,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned 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: @@ -355,8 +357,10 @@ static int 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; @@ -502,7 +506,7 @@ match(const struct sk_buff *skb, 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; @@ -532,6 +536,7 @@ match(const struct sk_buff *skb, } 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; @@ -631,7 +636,7 @@ match(const struct sk_buff *skb, 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; } @@ -653,7 +658,8 @@ match(const struct sk_buff *skb, */ 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) @@ -667,8 +673,6 @@ checkentry(const char *tablename, 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; } @@ -713,9 +717,9 @@ checkentry(const char *tablename, #endif curr_table = vmalloc(sizeof(struct recent_ip_tables)); - if(curr_table == NULL) return -ENOMEM; + if(curr_table == NULL) return 0; - curr_table->list_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&curr_table->list_lock); curr_table->next = NULL; curr_table->count = 1; curr_table->time_pos = 0; @@ -730,14 +734,14 @@ checkentry(const char *tablename, #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 @@ -745,7 +749,7 @@ checkentry(const char *tablename, 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; @@ -763,7 +767,7 @@ checkentry(const char *tablename, vfree(hold); vfree(curr_table->table); vfree(curr_table); - return -ENOMEM; + return 0; } for(c = 0; c < ip_list_hash_size; c++) { @@ -783,7 +787,7 @@ checkentry(const char *tablename, 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; @@ -817,6 +821,7 @@ checkentry(const char *tablename, /* 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); @@ -827,7 +832,7 @@ checkentry(const char *tablename, 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) { @@ -835,16 +840,15 @@ checkentry(const char *tablename, 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; @@ -868,7 +872,7 @@ checkentry(const char *tablename, * 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; @@ -948,18 +952,19 @@ destroy(void *matchinfo, unsigned int matchsize) /* 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 @@ -983,11 +988,14 @@ static int __init init(void) 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); @@ -995,5 +1003,5 @@ static void __exit fini(void) } /* Register our module with the kernel. */ -module_init(init); -module_exit(fini); +module_init(ipt_recent_init); +module_exit(ipt_recent_fini);