#include "regexp/regexp.c"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>, Arne Fitzenreiter <arne_f@ipfire.org>");
MODULE_DESCRIPTION("iptables application layer match module");
MODULE_ALIAS("ipt_layer7");
-MODULE_VERSION("2.23");
+MODULE_VERSION("2.30");
static int maxdatalen = 2048; // this is the default
module_param(maxdatalen, int, 0444);
struct pattern_cache * next;
} * first_pattern_cache = NULL;
+static struct proto_cache {
+ char * proto_string;
+ struct proto_cache * next;
+} * first_proto_cache = NULL;
+
DEFINE_SPINLOCK(l7_lock);
static int total_acct_packets(struct nf_conn *ct)
return node->pattern;
}
+static char * get_protostr_ptr(const char * protocol)
+{
+ struct proto_cache * node = first_proto_cache;
+ struct proto_cache * last_proto_cache = first_proto_cache;
+ struct proto_cache * tmp;
+
+ while (node != NULL) {
+ if (!strcmp(node->proto_string, protocol))
+ return node->proto_string;
+
+ last_proto_cache = node;/* points at the last non-NULL node */
+ node = node->next;
+ }
+
+ /* If we reach the end of the list, then we have not yet cached protocol
+ Be paranoid about running out of memory to avoid list corruption. */
+ tmp = kmalloc(sizeof(struct proto_cache), GFP_ATOMIC);
+
+ if(!tmp) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in "
+ "proto_cache add, bailing.\n");
+ return NULL;
+ }
+
+ tmp->proto_string = kmalloc(strlen(protocol) + 1 , GFP_ATOMIC);
+ tmp->next = NULL;
+
+ if(!tmp->proto_string) {
+ if (net_ratelimit())
+ printk(KERN_ERR "layer7: out of memory in "
+ "proto_cache add, bailing.\n");
+ kfree(tmp->proto_string);
+ kfree(tmp);
+ return NULL;
+ }
+
+ /* Ok. The new node is all ready now. */
+ node = tmp;
+
+ if(first_proto_cache == NULL) /* list is empty */
+ first_proto_cache = node; /* make node the beginning */
+ else
+ last_proto_cache->next = node; /* attach node to the end */
+
+ strcpy(node->proto_string, protocol);
+ return node->proto_string;
+}
+
static int can_handle(const struct sk_buff *skb)
{
if(!ip_hdr(skb)) /* not IP */
if(master_conntrack->layer7.app_proto){
/* Here child connections set their .app_proto (for /proc) */
if(!conntrack->layer7.app_proto) {
- conntrack->layer7.app_proto =
- kmalloc(strlen(master_conntrack->layer7.app_proto)+1,
- GFP_ATOMIC);
- if(!conntrack->layer7.app_proto){
- if (net_ratelimit())
- printk(KERN_ERR "layer7: out of memory "
- "in match_no_append, "
- "bailing.\n");
- return 1;
- }
- strcpy(conntrack->layer7.app_proto,
- master_conntrack->layer7.app_proto);
+ conntrack->layer7.app_proto = master_conntrack->layer7.app_proto;
}
return (!strcmp(master_conntrack->layer7.app_proto,
else {
/* If not classified, set to "unknown" to distinguish from
connections that are still being tested. */
- master_conntrack->layer7.app_proto =
- kmalloc(strlen("unknown")+1, GFP_ATOMIC);
- if(!master_conntrack->layer7.app_proto){
- if (net_ratelimit())
- printk(KERN_ERR "layer7: out of memory in "
- "match_no_append, bailing.\n");
- return 1;
- }
- strcpy(master_conntrack->layer7.app_proto, "unknown");
+ master_conntrack->layer7.app_proto = get_protostr_ptr("unknown");
return 0;
}
}
if(!skb->cb[0]){
int newbytes;
newbytes = add_data(master_conntrack, app_data, appdatalen);
-
if(newbytes == 0) { /* didn't add any data */
skb->cb[0] = 1;
/* Didn't match before, not going to match now */
} else pattern_result = 0;
if(pattern_result == 1) {
- master_conntrack->layer7.app_proto =
- kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
- if(!master_conntrack->layer7.app_proto){
- if (net_ratelimit())
- printk(KERN_ERR "layer7: out of memory in "
- "match, bailing.\n");
- spin_unlock_bh(&l7_lock);
- return (pattern_result ^ info->invert);
- }
- strcpy(master_conntrack->layer7.app_proto, info->protocol);
+ master_conntrack->layer7.app_proto=get_protostr_ptr(info->protocol);
} else if(pattern_result > 1) { /* cleanup from "unset" */
pattern_result = 1;
}