2 Kernel module to match application layer (OSI layer 7) data in connections.
4 http://l7-filter.sf.net
6 (C) 2003-2009 Matthew Strait and Ethan Sommer.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version
11 2 of the License, or (at your option) any later version.
12 http://www.gnu.org/licenses/gpl.txt
14 Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
15 xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
16 Ethan Sommer, Justin Levandoski.
19 #include <linux/spinlock.h>
20 #include <linux/version.h>
23 #include <linux/module.h>
24 #include <linux/skbuff.h>
25 #include <linux/netfilter.h>
26 #include <net/netfilter/nf_conntrack.h>
27 #include <net/netfilter/nf_conntrack_core.h>
28 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
29 #include <net/netfilter/nf_conntrack_extend.h>
30 #include <net/netfilter/nf_conntrack_acct.h>
32 #include <linux/netfilter/x_tables.h>
33 #include <linux/netfilter/xt_layer7.h>
34 #include <linux/ctype.h>
35 #include <linux/proc_fs.h>
37 #include "regexp/regexp.c"
39 MODULE_LICENSE("GPL");
40 MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>, Arne Fitzenreiter <arne_f@ipfire.org>");
41 MODULE_DESCRIPTION("iptables application layer match module");
42 MODULE_ALIAS("ipt_layer7");
43 MODULE_VERSION("2.30");
45 static int maxdatalen
= 2048; // this is the default
46 module_param(maxdatalen
, int, 0444);
47 MODULE_PARM_DESC(maxdatalen
, "maximum bytes of data looked at by l7-filter");
48 #ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
49 #define DPRINTK(format,args...) printk(format,##args)
51 #define DPRINTK(format,args...)
54 /* Number of packets whose data we look at.
55 This can be modified through /proc/net/layer7_numpackets */
56 static int num_packets
= 10;
58 static struct pattern_cache
{
61 struct pattern_cache
* next
;
62 } * first_pattern_cache
= NULL
;
64 static struct proto_cache
{
66 struct proto_cache
* next
;
67 } * first_proto_cache
= NULL
;
69 DEFINE_SPINLOCK(l7_lock
);
71 static int total_acct_packets(struct nf_conn
*ct
)
73 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
75 return (ct
->counters
[IP_CT_DIR_ORIGINAL
].packets
+ ct
->counters
[IP_CT_DIR_REPLY
].packets
);
77 struct nf_conn_counter
*acct
;
80 acct
= nf_conn_acct_find(ct
);
83 return (atomic64_read(&acct
[IP_CT_DIR_ORIGINAL
].packets
) + atomic64_read(&acct
[IP_CT_DIR_REPLY
].packets
));
87 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
88 /* Converts an unfriendly string into a friendly one by
89 replacing unprintables with periods and all whitespace with " ". */
90 static char * friendly_print(unsigned char * s
)
92 char * f
= kmalloc(strlen(s
) + 1, GFP_ATOMIC
);
97 printk(KERN_ERR
"layer7: out of memory in "
98 "friendly_print, bailing.\n");
102 for(i
= 0; i
< strlen(s
); i
++){
103 if(isprint(s
[i
]) && s
[i
] < 128) f
[i
] = s
[i
];
104 else if(isspace(s
[i
])) f
[i
] = ' ';
111 static char dec2hex(int i
)
118 return (i
- 10 + 'a');
122 printk("layer7: Problem in dec2hex\n");
127 static char * hex_print(unsigned char * s
)
129 char * g
= kmalloc(strlen(s
)*3 + 1, GFP_ATOMIC
);
134 printk(KERN_ERR
"layer7: out of memory in hex_print, "
139 for(i
= 0; i
< strlen(s
); i
++) {
140 g
[i
*3 ] = dec2hex(s
[i
]/16);
141 g
[i
*3 + 1] = dec2hex(s
[i
]%16);
150 /* Use instead of regcomp. As we expect to be seeing the same regexps over and
151 over again, it make sense to cache the results. */
152 static regexp
* compile_and_cache(const char * regex_string
,
153 const char * protocol
)
155 struct pattern_cache
* node
= first_pattern_cache
;
156 struct pattern_cache
* last_pattern_cache
= first_pattern_cache
;
157 struct pattern_cache
* tmp
;
160 while (node
!= NULL
) {
161 if (!strcmp(node
->regex_string
, regex_string
))
162 return node
->pattern
;
164 last_pattern_cache
= node
;/* points at the last non-NULL node */
168 /* If we reach the end of the list, then we have not yet cached
169 the pattern for this regex. Let's do that now.
170 Be paranoid about running out of memory to avoid list corruption. */
171 tmp
= kmalloc(sizeof(struct pattern_cache
), GFP_ATOMIC
);
175 printk(KERN_ERR
"layer7: out of memory in "
176 "compile_and_cache, bailing.\n");
180 tmp
->regex_string
= kmalloc(strlen(regex_string
) + 1, GFP_ATOMIC
);
181 tmp
->pattern
= kmalloc(sizeof(struct regexp
), GFP_ATOMIC
);
184 if(!tmp
->regex_string
|| !tmp
->pattern
) {
186 printk(KERN_ERR
"layer7: out of memory in "
187 "compile_and_cache, bailing.\n");
188 kfree(tmp
->regex_string
);
194 /* Ok. The new node is all ready now. */
197 if(first_pattern_cache
== NULL
) /* list is empty */
198 first_pattern_cache
= node
; /* make node the beginning */
200 last_pattern_cache
->next
= node
; /* attach node to the end */
202 /* copy the string and compile the regex */
203 len
= strlen(regex_string
);
204 DPRINTK("About to compile this: \"%s\"\n", regex_string
);
205 node
->pattern
= regcomp((char *)regex_string
, &len
);
206 if ( !node
->pattern
) {
208 printk(KERN_ERR
"layer7: Error compiling regexp "
210 regex_string
, protocol
);
211 /* pattern is now cached as NULL, so we won't try again. */
214 strcpy(node
->regex_string
, regex_string
);
215 return node
->pattern
;
218 static char * get_protostr_ptr(const char * protocol
)
220 struct proto_cache
* node
= first_proto_cache
;
221 struct proto_cache
* last_proto_cache
= first_proto_cache
;
222 struct proto_cache
* tmp
;
224 while (node
!= NULL
) {
225 if (!strcmp(node
->proto_string
, protocol
))
226 return node
->proto_string
;
228 last_proto_cache
= node
;/* points at the last non-NULL node */
232 /* If we reach the end of the list, then we have not yet cached protocol
233 Be paranoid about running out of memory to avoid list corruption. */
234 tmp
= kmalloc(sizeof(struct proto_cache
), GFP_ATOMIC
);
238 printk(KERN_ERR
"layer7: out of memory in "
239 "proto_cache add, bailing.\n");
243 tmp
->proto_string
= kmalloc(strlen(protocol
) + 1 , GFP_ATOMIC
);
246 if(!tmp
->proto_string
) {
248 printk(KERN_ERR
"layer7: out of memory in "
249 "proto_cache add, bailing.\n");
250 kfree(tmp
->proto_string
);
255 /* Ok. The new node is all ready now. */
258 if(first_proto_cache
== NULL
) /* list is empty */
259 first_proto_cache
= node
; /* make node the beginning */
261 last_proto_cache
->next
= node
; /* attach node to the end */
263 strcpy(node
->proto_string
, protocol
);
264 return node
->proto_string
;
267 static int can_handle(const struct sk_buff
*skb
)
269 if(!ip_hdr(skb
)) /* not IP */
271 if(ip_hdr(skb
)->protocol
!= IPPROTO_TCP
&&
272 ip_hdr(skb
)->protocol
!= IPPROTO_UDP
&&
273 ip_hdr(skb
)->protocol
!= IPPROTO_ICMP
)
278 /* Returns offset the into the skb->data that the application data starts */
279 static int app_data_offset(const struct sk_buff
*skb
)
281 /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
282 isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
283 int ip_hl
= 4*ip_hdr(skb
)->ihl
;
285 if( ip_hdr(skb
)->protocol
== IPPROTO_TCP
) {
286 /* 12 == offset into TCP header for the header length field.
287 Can't get this with skb->h.th->doff because the tcphdr
288 struct doesn't get set when routing (this is confirmed to be
289 true in Netfilter as well as QoS.) */
290 int tcp_hl
= 4*(skb
->data
[ip_hl
+ 12] >> 4);
292 return ip_hl
+ tcp_hl
;
293 } else if( ip_hdr(skb
)->protocol
== IPPROTO_UDP
) {
294 return ip_hl
+ 8; /* UDP header is always 8 bytes */
295 } else if( ip_hdr(skb
)->protocol
== IPPROTO_ICMP
) {
296 return ip_hl
+ 8; /* ICMP header is 8 bytes */
299 printk(KERN_ERR
"layer7: tried to handle unknown "
301 return ip_hl
+ 8; /* something reasonable */
305 /* handles whether there's a match when we aren't appending data anymore */
306 static int match_no_append(struct nf_conn
* conntrack
,
307 struct nf_conn
* master_conntrack
,
308 enum ip_conntrack_info ctinfo
,
309 enum ip_conntrack_info master_ctinfo
,
310 const struct xt_layer7_info
* info
)
312 /* If we're in here, throw the app data away */
313 if(master_conntrack
->layer7
.app_data
!= NULL
) {
315 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
316 if(!master_conntrack
->layer7
.app_proto
) {
318 friendly_print(master_conntrack
->layer7
.app_data
);
320 hex_print(master_conntrack
->layer7
.app_data
);
321 DPRINTK("\nl7-filter gave up after %d bytes "
322 "(%d packets):\n%s\n",
323 strlen(f
), total_acct_packets(master_conntrack
), f
);
325 DPRINTK("In hex: %s\n", g
);
330 kfree(master_conntrack
->layer7
.app_data
);
331 master_conntrack
->layer7
.app_data
= NULL
; /* don't free again */
334 if(master_conntrack
->layer7
.app_proto
){
335 /* Here child connections set their .app_proto (for /proc) */
336 if(!conntrack
->layer7
.app_proto
) {
337 conntrack
->layer7
.app_proto
= master_conntrack
->layer7
.app_proto
;
340 return (!strcmp(master_conntrack
->layer7
.app_proto
,
344 /* If not classified, set to "unknown" to distinguish from
345 connections that are still being tested. */
346 master_conntrack
->layer7
.app_proto
= get_protostr_ptr("unknown");
351 /* add the new app data to the conntrack. Return number of bytes added. */
352 static int add_data(struct nf_conn
* master_conntrack
,
353 char * app_data
, int appdatalen
)
356 int oldlength
= master_conntrack
->layer7
.app_data_len
;
358 /* This is a fix for a race condition by Deti Fliegl. However, I'm not
359 clear on whether the race condition exists or whether this really
360 fixes it. I might just be being dense... Anyway, if it's not really
361 a fix, all it does is waste a very small amount of time. */
362 if(!master_conntrack
->layer7
.app_data
) return 0;
364 /* Strip nulls. Make everything lower case (our regex lib doesn't
365 do case insensitivity). Add it to the end of the current data. */
366 for(i
= 0; i
< maxdatalen
-oldlength
-1 &&
367 i
< appdatalen
; i
++) {
368 if(app_data
[i
] != '\0') {
369 /* the kernel version of tolower mungs 'upper ascii' */
370 master_conntrack
->layer7
.app_data
[length
+oldlength
] =
371 isascii(app_data
[i
])?
372 tolower(app_data
[i
]) : app_data
[i
];
377 master_conntrack
->layer7
.app_data
[length
+oldlength
] = '\0';
378 master_conntrack
->layer7
.app_data_len
= length
+ oldlength
;
383 /* taken from drivers/video/modedb.c */
384 static int my_atoi(const char *s
)
391 val
= 10*val
+(*s
-'0');
399 static int layer7_numpackets_proc_show(struct seq_file
*s
, void *p
) {
400 seq_printf(s
, "%d\n", num_packets
);
405 static int layer7_numpackets_proc_open(struct inode
*inode
, struct file
*file
) {
406 return single_open(file
, layer7_numpackets_proc_show
, NULL
);
409 /* Read in num_packets from userland */
410 static ssize_t
layer7_numpackets_write_proc(struct file
* file
, const char __user
*buffer
,
411 size_t count
, loff_t
*data
) {
415 if (copy_from_user(&value
, buffer
, sizeof(value
)))
418 new_num_packets
= my_atoi(value
);
420 if ((new_num_packets
< 1) || (new_num_packets
> 99)) {
421 printk(KERN_WARNING
"layer7: numpackets must be between 1 and 99\n");
425 num_packets
= new_num_packets
;
431 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
432 match(const struct sk_buff
*skbin
, struct xt_action_param
*par
)
433 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
434 match(const struct sk_buff
*skbin
, const struct xt_match_param
*par
)
436 match(const struct sk_buff
*skbin
,
437 const struct net_device
*in
,
438 const struct net_device
*out
,
439 const struct xt_match
*match
,
440 const void *matchinfo
,
442 unsigned int protoff
,
446 /* sidestep const without getting a compiler warning... */
447 struct sk_buff
* skb
= (struct sk_buff
*)skbin
;
449 const struct xt_layer7_info
* info
=
450 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
456 enum ip_conntrack_info master_ctinfo
, ctinfo
;
457 struct nf_conn
*master_conntrack
, *conntrack
;
458 unsigned char * app_data
;
459 unsigned int pattern_result
, appdatalen
;
460 regexp
* comppattern
;
462 /* Be paranoid/incompetent - lock the entire match function. */
463 spin_lock_bh(&l7_lock
);
465 if(!can_handle(skb
)){
466 DPRINTK("layer7: This is some protocol I can't handle.\n");
467 spin_unlock_bh(&l7_lock
);
471 /* Treat parent & all its children together as one connection, except
472 for the purpose of setting conntrack->layer7.app_proto in the actual
473 connection. This makes /proc/net/ip_conntrack more satisfying. */
474 if(!(conntrack
= nf_ct_get(skb
, &ctinfo
)) ||
475 !(master_conntrack
=nf_ct_get(skb
,&master_ctinfo
))){
476 DPRINTK("layer7: couldn't get conntrack.\n");
477 spin_unlock_bh(&l7_lock
);
481 /* Try to get a master conntrack (and its master etc) for FTP, etc. */
482 while (master_ct(master_conntrack
) != NULL
)
483 master_conntrack
= master_ct(master_conntrack
);
485 /* free unused conntrack data if different master conntrack exists */
486 if (master_conntrack
!= conntrack
) {
487 if (conntrack
->layer7
.app_data
) {
488 DPRINTK("layer7: free unused conntrack memory.\n");
489 kfree(conntrack
->layer7
.app_data
);
490 conntrack
->layer7
.app_data
= NULL
; /* don't free again */
494 /* if we've classified it or seen too many packets */
495 if(total_acct_packets(master_conntrack
) > num_packets
||
496 master_conntrack
->layer7
.app_proto
) {
498 pattern_result
= match_no_append(conntrack
, master_conntrack
,
499 ctinfo
, master_ctinfo
, info
);
501 skb
->layer7_flags
[0] = 1; /* marking it seen here's probably irrelevant */
503 spin_unlock_bh(&l7_lock
);
504 return (pattern_result
^ info
->invert
);
507 if(skb_is_nonlinear(skb
)){
508 if(skb_linearize(skb
) != 0){
510 printk(KERN_ERR
"layer7: failed to linearize "
511 "packet, bailing.\n");
512 spin_unlock_bh(&l7_lock
);
517 /* now that the skb is linearized, it's safe to set these. */
518 app_data
= skb
->data
+ app_data_offset(skb
);
519 appdatalen
= skb_tail_pointer(skb
) - app_data
;
521 /* the return value gets checked later, when we're ready to use it */
522 comppattern
= compile_and_cache(info
->pattern
, info
->protocol
);
524 /* On the first packet of a connection, allocate space for app data */
525 if(total_acct_packets(master_conntrack
) == 1 && !skb
->layer7_flags
[0] &&
526 !master_conntrack
->layer7
.app_data
){
527 master_conntrack
->layer7
.app_data
=
528 kmalloc(maxdatalen
, GFP_ATOMIC
);
529 if(!master_conntrack
->layer7
.app_data
){
531 printk(KERN_ERR
"layer7: out of memory in "
532 "match, bailing.\n");
533 spin_unlock_bh(&l7_lock
);
537 master_conntrack
->layer7
.app_data
[0] = '\0';
540 /* Can be here, but unallocated, if numpackets is increased near
541 the beginning of a connection */
542 if(master_conntrack
->layer7
.app_data
== NULL
){
543 spin_unlock_bh(&l7_lock
);
544 return info
->invert
; /* unmatched */
547 if(!skb
->layer7_flags
[0]){
549 newbytes
= add_data(master_conntrack
, app_data
, appdatalen
);
550 if(newbytes
== 0) { /* didn't add any data */
551 skb
->layer7_flags
[0] = 1;
552 /* Didn't match before, not going to match now */
553 spin_unlock_bh(&l7_lock
);
558 /* If looking for "unknown", then never match. "Unknown" means that
559 we've given up; we're still trying with these packets. */
560 if(!strcmp(info
->protocol
, "unknown")) {
562 /* If looking for "unset", then always match. "Unset" means that we
563 haven't yet classified the connection. */
564 } else if(!strcmp(info
->protocol
, "unset")) {
566 DPRINTK("layer7: matched unset: not yet classified "
568 total_acct_packets(master_conntrack
), num_packets
);
569 /* If the regexp failed to compile, don't bother running it */
570 } else if(comppattern
&&
571 regexec(comppattern
, master_conntrack
->layer7
.app_data
)){
572 DPRINTK("layer7: matched %s\n", info
->protocol
);
574 } else pattern_result
= 0;
576 if(pattern_result
== 1) {
577 master_conntrack
->layer7
.app_proto
=get_protostr_ptr(info
->protocol
);
578 } else if(pattern_result
> 1) { /* cleanup from "unset" */
582 /* mark the packet seen */
583 skb
->layer7_flags
[0] = 1;
585 spin_unlock_bh(&l7_lock
);
586 return (pattern_result
^ info
->invert
);
589 // load nf_conntrack_ipv4
590 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
595 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
596 check(const struct xt_mtchk_param
*par
)
598 if (nf_ct_l3proto_try_module_get(par
->match
->family
) < 0) {
599 printk(KERN_WARNING
"can't load conntrack support for "
600 "proto=%d\n", par
->match
->family
);
602 check(const char *tablename
, const void *inf
,
603 const struct xt_match
*match
, void *matchinfo
,
604 unsigned int hook_mask
)
606 if (nf_ct_l3proto_try_module_get(match
->family
) < 0) {
607 printk(KERN_WARNING
"can't load conntrack support for "
608 "proto=%d\n", match
->family
);
610 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
622 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
623 static void destroy(const struct xt_mtdtor_param
*par
)
625 nf_ct_l3proto_module_put(par
->match
->family
);
628 static void destroy(const struct xt_match
*match
, void *matchinfo
)
630 nf_ct_l3proto_module_put(match
->family
);
634 static struct xt_match xt_layer7_match
[] __read_mostly
= {
637 .family
= NFPROTO_IPV4
,
641 .matchsize
= sizeof(struct xt_layer7_info
),
646 static const struct file_operations layer7_numpackets_proc_fops
= {
647 .owner
= THIS_MODULE
,
648 .open
= layer7_numpackets_proc_open
,
651 .release
= single_release
,
652 .write
= layer7_numpackets_write_proc
,
655 static int __init
xt_layer7_init(void)
659 // Register proc interface
660 proc_create_data("layer7_numpackets", 0644,
661 init_net
.proc_net
, &layer7_numpackets_proc_fops
, NULL
);
664 printk(KERN_WARNING
"layer7: maxdatalen can't be < 1, "
668 /* This is not a hard limit. It's just here to prevent people from
669 bringing their slow machines to a grinding halt. */
670 else if(maxdatalen
> 65536) {
671 printk(KERN_WARNING
"layer7: maxdatalen can't be > 65536, "
675 return xt_register_matches(xt_layer7_match
,
676 ARRAY_SIZE(xt_layer7_match
));
679 static void __exit
xt_layer7_fini(void)
681 remove_proc_entry("layer7_numpackets", init_net
.proc_net
);
682 xt_unregister_matches(xt_layer7_match
, ARRAY_SIZE(xt_layer7_match
));
685 module_init(xt_layer7_init
);
686 module_exit(xt_layer7_fini
);