]> git.ipfire.org Git - people/arne_f/kernel.git/blob - net/netfilter/xt_layer7.c
netfilter: layer7 change proto to NFPROTO_IPV4
[people/arne_f/kernel.git] / net / netfilter / xt_layer7.c
1 /*
2 Kernel module to match application layer (OSI layer 7) data in connections.
3
4 http://l7-filter.sf.net
5
6 (C) 2003-2009 Matthew Strait and Ethan Sommer.
7
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
13
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.
17 */
18
19 #include <linux/spinlock.h>
20 #include <linux/version.h>
21 #include <net/ip.h>
22 #include <net/tcp.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>
31 #endif
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>
36
37 #include "regexp/regexp.c"
38
39 MODULE_LICENSE("GPL");
40 MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
41 MODULE_DESCRIPTION("iptables application layer match module");
42 MODULE_ALIAS("ipt_layer7");
43 MODULE_VERSION("2.23");
44
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)
50 #else
51 #define DPRINTK(format,args...)
52 #endif
53
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;
57
58 static struct pattern_cache {
59 char * regex_string;
60 regexp * pattern;
61 struct pattern_cache * next;
62 } * first_pattern_cache = NULL;
63
64 DEFINE_SPINLOCK(l7_lock);
65
66 static int total_acct_packets(struct nf_conn *ct)
67 {
68 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
69 BUG_ON(ct == NULL);
70 return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
71 #else
72 struct nf_conn_counter *acct;
73
74 BUG_ON(ct == NULL);
75 acct = nf_conn_acct_find(ct);
76 if (!acct)
77 return 0;
78 return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
79 #endif
80 }
81
82 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
83 /* Converts an unfriendly string into a friendly one by
84 replacing unprintables with periods and all whitespace with " ". */
85 static char * friendly_print(unsigned char * s)
86 {
87 char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
88 int i;
89
90 if(!f) {
91 if (net_ratelimit())
92 printk(KERN_ERR "layer7: out of memory in "
93 "friendly_print, bailing.\n");
94 return NULL;
95 }
96
97 for(i = 0; i < strlen(s); i++){
98 if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
99 else if(isspace(s[i])) f[i] = ' ';
100 else f[i] = '.';
101 }
102 f[i] = '\0';
103 return f;
104 }
105
106 static char dec2hex(int i)
107 {
108 switch (i) {
109 case 0 ... 9:
110 return (i + '0');
111 break;
112 case 10 ... 15:
113 return (i - 10 + 'a');
114 break;
115 default:
116 if (net_ratelimit())
117 printk("layer7: Problem in dec2hex\n");
118 return '\0';
119 }
120 }
121
122 static char * hex_print(unsigned char * s)
123 {
124 char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
125 int i;
126
127 if(!g) {
128 if (net_ratelimit())
129 printk(KERN_ERR "layer7: out of memory in hex_print, "
130 "bailing.\n");
131 return NULL;
132 }
133
134 for(i = 0; i < strlen(s); i++) {
135 g[i*3 ] = dec2hex(s[i]/16);
136 g[i*3 + 1] = dec2hex(s[i]%16);
137 g[i*3 + 2] = ' ';
138 }
139 g[i*3] = '\0';
140
141 return g;
142 }
143 #endif // DEBUG
144
145 /* Use instead of regcomp. As we expect to be seeing the same regexps over and
146 over again, it make sense to cache the results. */
147 static regexp * compile_and_cache(const char * regex_string,
148 const char * protocol)
149 {
150 struct pattern_cache * node = first_pattern_cache;
151 struct pattern_cache * last_pattern_cache = first_pattern_cache;
152 struct pattern_cache * tmp;
153 unsigned int len;
154
155 while (node != NULL) {
156 if (!strcmp(node->regex_string, regex_string))
157 return node->pattern;
158
159 last_pattern_cache = node;/* points at the last non-NULL node */
160 node = node->next;
161 }
162
163 /* If we reach the end of the list, then we have not yet cached
164 the pattern for this regex. Let's do that now.
165 Be paranoid about running out of memory to avoid list corruption. */
166 tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
167
168 if(!tmp) {
169 if (net_ratelimit())
170 printk(KERN_ERR "layer7: out of memory in "
171 "compile_and_cache, bailing.\n");
172 return NULL;
173 }
174
175 tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
176 tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
177 tmp->next = NULL;
178
179 if(!tmp->regex_string || !tmp->pattern) {
180 if (net_ratelimit())
181 printk(KERN_ERR "layer7: out of memory in "
182 "compile_and_cache, bailing.\n");
183 kfree(tmp->regex_string);
184 kfree(tmp->pattern);
185 kfree(tmp);
186 return NULL;
187 }
188
189 /* Ok. The new node is all ready now. */
190 node = tmp;
191
192 if(first_pattern_cache == NULL) /* list is empty */
193 first_pattern_cache = node; /* make node the beginning */
194 else
195 last_pattern_cache->next = node; /* attach node to the end */
196
197 /* copy the string and compile the regex */
198 len = strlen(regex_string);
199 DPRINTK("About to compile this: \"%s\"\n", regex_string);
200 node->pattern = regcomp((char *)regex_string, &len);
201 if ( !node->pattern ) {
202 if (net_ratelimit())
203 printk(KERN_ERR "layer7: Error compiling regexp "
204 "\"%s\" (%s)\n",
205 regex_string, protocol);
206 /* pattern is now cached as NULL, so we won't try again. */
207 }
208
209 strcpy(node->regex_string, regex_string);
210 return node->pattern;
211 }
212
213 static int can_handle(const struct sk_buff *skb)
214 {
215 if(!ip_hdr(skb)) /* not IP */
216 return 0;
217 if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
218 ip_hdr(skb)->protocol != IPPROTO_UDP &&
219 ip_hdr(skb)->protocol != IPPROTO_ICMP)
220 return 0;
221 return 1;
222 }
223
224 /* Returns offset the into the skb->data that the application data starts */
225 static int app_data_offset(const struct sk_buff *skb)
226 {
227 /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
228 isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
229 int ip_hl = 4*ip_hdr(skb)->ihl;
230
231 if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
232 /* 12 == offset into TCP header for the header length field.
233 Can't get this with skb->h.th->doff because the tcphdr
234 struct doesn't get set when routing (this is confirmed to be
235 true in Netfilter as well as QoS.) */
236 int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
237
238 return ip_hl + tcp_hl;
239 } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) {
240 return ip_hl + 8; /* UDP header is always 8 bytes */
241 } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
242 return ip_hl + 8; /* ICMP header is 8 bytes */
243 } else {
244 if (net_ratelimit())
245 printk(KERN_ERR "layer7: tried to handle unknown "
246 "protocol!\n");
247 return ip_hl + 8; /* something reasonable */
248 }
249 }
250
251 /* handles whether there's a match when we aren't appending data anymore */
252 static int match_no_append(struct nf_conn * conntrack,
253 struct nf_conn * master_conntrack,
254 enum ip_conntrack_info ctinfo,
255 enum ip_conntrack_info master_ctinfo,
256 const struct xt_layer7_info * info)
257 {
258 /* If we're in here, throw the app data away */
259 if(master_conntrack->layer7.app_data != NULL) {
260
261 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
262 if(!master_conntrack->layer7.app_proto) {
263 char * f =
264 friendly_print(master_conntrack->layer7.app_data);
265 char * g =
266 hex_print(master_conntrack->layer7.app_data);
267 DPRINTK("\nl7-filter gave up after %d bytes "
268 "(%d packets):\n%s\n",
269 strlen(f), total_acct_packets(master_conntrack), f);
270 kfree(f);
271 DPRINTK("In hex: %s\n", g);
272 kfree(g);
273 }
274 #endif
275
276 kfree(master_conntrack->layer7.app_data);
277 master_conntrack->layer7.app_data = NULL; /* don't free again */
278 }
279
280 if(master_conntrack->layer7.app_proto){
281 /* Here child connections set their .app_proto (for /proc) */
282 if(!conntrack->layer7.app_proto) {
283 conntrack->layer7.app_proto =
284 kmalloc(strlen(master_conntrack->layer7.app_proto)+1,
285 GFP_ATOMIC);
286 if(!conntrack->layer7.app_proto){
287 if (net_ratelimit())
288 printk(KERN_ERR "layer7: out of memory "
289 "in match_no_append, "
290 "bailing.\n");
291 return 1;
292 }
293 strcpy(conntrack->layer7.app_proto,
294 master_conntrack->layer7.app_proto);
295 }
296
297 return (!strcmp(master_conntrack->layer7.app_proto,
298 info->protocol));
299 }
300 else {
301 /* If not classified, set to "unknown" to distinguish from
302 connections that are still being tested. */
303 master_conntrack->layer7.app_proto =
304 kmalloc(strlen("unknown")+1, GFP_ATOMIC);
305 if(!master_conntrack->layer7.app_proto){
306 if (net_ratelimit())
307 printk(KERN_ERR "layer7: out of memory in "
308 "match_no_append, bailing.\n");
309 return 1;
310 }
311 strcpy(master_conntrack->layer7.app_proto, "unknown");
312 return 0;
313 }
314 }
315
316 /* add the new app data to the conntrack. Return number of bytes added. */
317 static int add_data(struct nf_conn * master_conntrack,
318 char * app_data, int appdatalen)
319 {
320 int length = 0, i;
321 int oldlength = master_conntrack->layer7.app_data_len;
322
323 /* This is a fix for a race condition by Deti Fliegl. However, I'm not
324 clear on whether the race condition exists or whether this really
325 fixes it. I might just be being dense... Anyway, if it's not really
326 a fix, all it does is waste a very small amount of time. */
327 if(!master_conntrack->layer7.app_data) return 0;
328
329 /* Strip nulls. Make everything lower case (our regex lib doesn't
330 do case insensitivity). Add it to the end of the current data. */
331 for(i = 0; i < maxdatalen-oldlength-1 &&
332 i < appdatalen; i++) {
333 if(app_data[i] != '\0') {
334 /* the kernel version of tolower mungs 'upper ascii' */
335 master_conntrack->layer7.app_data[length+oldlength] =
336 isascii(app_data[i])?
337 tolower(app_data[i]) : app_data[i];
338 length++;
339 }
340 }
341
342 master_conntrack->layer7.app_data[length+oldlength] = '\0';
343 master_conntrack->layer7.app_data_len = length + oldlength;
344
345 return length;
346 }
347
348 /* taken from drivers/video/modedb.c */
349 static int my_atoi(const char *s)
350 {
351 int val = 0;
352
353 for (;; s++) {
354 switch (*s) {
355 case '0'...'9':
356 val = 10*val+(*s-'0');
357 break;
358 default:
359 return val;
360 }
361 }
362 }
363
364 static int layer7_numpackets_proc_show(struct seq_file *s, void *p) {
365 seq_printf(s, "%d\n", num_packets);
366
367 return 0;
368 }
369
370 static int layer7_numpackets_proc_open(struct inode *inode, struct file *file) {
371 return single_open(file, layer7_numpackets_proc_show, NULL);
372 }
373
374 /* Read in num_packets from userland */
375 static ssize_t layer7_numpackets_write_proc(struct file* file, const char __user *buffer,
376 size_t count, loff_t *data) {
377 char value[1024];
378 int new_num_packets;
379
380 if (copy_from_user(&value, buffer, sizeof(value)))
381 return -EFAULT;
382
383 new_num_packets = my_atoi(value);
384
385 if ((new_num_packets < 1) || (new_num_packets > 99)) {
386 printk(KERN_WARNING "layer7: numpackets must be between 1 and 99\n");
387 return -EFAULT;
388 }
389
390 num_packets = new_num_packets;
391
392 return count;
393 }
394
395 static bool
396 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
397 match(const struct sk_buff *skbin, struct xt_action_param *par)
398 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
399 match(const struct sk_buff *skbin, const struct xt_match_param *par)
400 #else
401 match(const struct sk_buff *skbin,
402 const struct net_device *in,
403 const struct net_device *out,
404 const struct xt_match *match,
405 const void *matchinfo,
406 int offset,
407 unsigned int protoff,
408 bool *hotdrop)
409 #endif
410 {
411 /* sidestep const without getting a compiler warning... */
412 struct sk_buff * skb = (struct sk_buff *)skbin;
413
414 const struct xt_layer7_info * info =
415 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
416 par->matchinfo;
417 #else
418 matchinfo;
419 #endif
420
421 enum ip_conntrack_info master_ctinfo, ctinfo;
422 struct nf_conn *master_conntrack, *conntrack;
423 unsigned char * app_data;
424 unsigned int pattern_result, appdatalen;
425 regexp * comppattern;
426
427 /* Be paranoid/incompetent - lock the entire match function. */
428 spin_lock_bh(&l7_lock);
429
430 if(!can_handle(skb)){
431 DPRINTK("layer7: This is some protocol I can't handle.\n");
432 spin_unlock_bh(&l7_lock);
433 return info->invert;
434 }
435
436 /* Treat parent & all its children together as one connection, except
437 for the purpose of setting conntrack->layer7.app_proto in the actual
438 connection. This makes /proc/net/ip_conntrack more satisfying. */
439 if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
440 !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
441 DPRINTK("layer7: couldn't get conntrack.\n");
442 spin_unlock_bh(&l7_lock);
443 return info->invert;
444 }
445
446 /* Try to get a master conntrack (and its master etc) for FTP, etc. */
447 while (master_ct(master_conntrack) != NULL)
448 master_conntrack = master_ct(master_conntrack);
449
450 /* if we've classified it or seen too many packets */
451 if(total_acct_packets(master_conntrack) > num_packets ||
452 master_conntrack->layer7.app_proto) {
453
454 pattern_result = match_no_append(conntrack, master_conntrack,
455 ctinfo, master_ctinfo, info);
456
457 /* skb->cb[0] == seen. Don't do things twice if there are
458 multiple l7 rules. I'm not sure that using cb for this purpose
459 is correct, even though it says "put your private variables
460 there". But it doesn't look like it is being used for anything
461 else in the skbs that make it here. */
462 skb->cb[0] = 1; /* marking it seen here's probably irrelevant */
463
464 spin_unlock_bh(&l7_lock);
465 return (pattern_result ^ info->invert);
466 }
467
468 if(skb_is_nonlinear(skb)){
469 if(skb_linearize(skb) != 0){
470 if (net_ratelimit())
471 printk(KERN_ERR "layer7: failed to linearize "
472 "packet, bailing.\n");
473 spin_unlock_bh(&l7_lock);
474 return info->invert;
475 }
476 }
477
478 /* now that the skb is linearized, it's safe to set these. */
479 app_data = skb->data + app_data_offset(skb);
480 appdatalen = skb_tail_pointer(skb) - app_data;
481
482 /* the return value gets checked later, when we're ready to use it */
483 comppattern = compile_and_cache(info->pattern, info->protocol);
484
485 /* On the first packet of a connection, allocate space for app data */
486 if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
487 !master_conntrack->layer7.app_data){
488 master_conntrack->layer7.app_data =
489 kmalloc(maxdatalen, GFP_ATOMIC);
490 if(!master_conntrack->layer7.app_data){
491 if (net_ratelimit())
492 printk(KERN_ERR "layer7: out of memory in "
493 "match, bailing.\n");
494 spin_unlock_bh(&l7_lock);
495 return info->invert;
496 }
497
498 master_conntrack->layer7.app_data[0] = '\0';
499 }
500
501 /* Can be here, but unallocated, if numpackets is increased near
502 the beginning of a connection */
503 if(master_conntrack->layer7.app_data == NULL){
504 spin_unlock_bh(&l7_lock);
505 return info->invert; /* unmatched */
506 }
507
508 if(!skb->cb[0]){
509 int newbytes;
510 newbytes = add_data(master_conntrack, app_data, appdatalen);
511
512 if(newbytes == 0) { /* didn't add any data */
513 skb->cb[0] = 1;
514 /* Didn't match before, not going to match now */
515 spin_unlock_bh(&l7_lock);
516 return info->invert;
517 }
518 }
519
520 /* If looking for "unknown", then never match. "Unknown" means that
521 we've given up; we're still trying with these packets. */
522 if(!strcmp(info->protocol, "unknown")) {
523 pattern_result = 0;
524 /* If looking for "unset", then always match. "Unset" means that we
525 haven't yet classified the connection. */
526 } else if(!strcmp(info->protocol, "unset")) {
527 pattern_result = 2;
528 DPRINTK("layer7: matched unset: not yet classified "
529 "(%d/%d packets)\n",
530 total_acct_packets(master_conntrack), num_packets);
531 /* If the regexp failed to compile, don't bother running it */
532 } else if(comppattern &&
533 regexec(comppattern, master_conntrack->layer7.app_data)){
534 DPRINTK("layer7: matched %s\n", info->protocol);
535 pattern_result = 1;
536 } else pattern_result = 0;
537
538 if(pattern_result == 1) {
539 master_conntrack->layer7.app_proto =
540 kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
541 if(!master_conntrack->layer7.app_proto){
542 if (net_ratelimit())
543 printk(KERN_ERR "layer7: out of memory in "
544 "match, bailing.\n");
545 spin_unlock_bh(&l7_lock);
546 return (pattern_result ^ info->invert);
547 }
548 strcpy(master_conntrack->layer7.app_proto, info->protocol);
549 } else if(pattern_result > 1) { /* cleanup from "unset" */
550 pattern_result = 1;
551 }
552
553 /* mark the packet seen */
554 skb->cb[0] = 1;
555
556 spin_unlock_bh(&l7_lock);
557 return (pattern_result ^ info->invert);
558 }
559
560 // load nf_conntrack_ipv4
561 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
562 static int
563 #else
564 static bool
565 #endif
566 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
567 check(const struct xt_mtchk_param *par)
568 {
569 if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
570 printk(KERN_WARNING "can't load conntrack support for "
571 "proto=%d\n", par->match->family);
572 #else
573 check(const char *tablename, const void *inf,
574 const struct xt_match *match, void *matchinfo,
575 unsigned int hook_mask)
576 {
577 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
578 printk(KERN_WARNING "can't load conntrack support for "
579 "proto=%d\n", match->family);
580 #endif
581 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
582 return -EINVAL;
583 }
584 return 0;
585 #else
586 return 0;
587 }
588 return 1;
589 #endif
590 }
591
592
593 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
594 static void destroy(const struct xt_mtdtor_param *par)
595 {
596 nf_ct_l3proto_module_put(par->match->family);
597 }
598 #else
599 static void destroy(const struct xt_match *match, void *matchinfo)
600 {
601 nf_ct_l3proto_module_put(match->family);
602 }
603 #endif
604
605 static struct xt_match xt_layer7_match[] __read_mostly = {
606 {
607 .name = "layer7",
608 .family = NFPROTO_IPV4,
609 .checkentry = check,
610 .match = match,
611 .destroy = destroy,
612 .matchsize = sizeof(struct xt_layer7_info),
613 .me = THIS_MODULE
614 }
615 };
616
617 static const struct file_operations layer7_numpackets_proc_fops = {
618 .owner = THIS_MODULE,
619 .open = layer7_numpackets_proc_open,
620 .read = seq_read,
621 .llseek = seq_lseek,
622 .release = single_release,
623 .write = layer7_numpackets_write_proc,
624 };
625
626 static int __init xt_layer7_init(void)
627 {
628 need_conntrack();
629
630 // Register proc interface
631 proc_create_data("layer7_numpackets", 0644,
632 init_net.proc_net, &layer7_numpackets_proc_fops, NULL);
633
634 if(maxdatalen < 1) {
635 printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
636 "using 1\n");
637 maxdatalen = 1;
638 }
639 /* This is not a hard limit. It's just here to prevent people from
640 bringing their slow machines to a grinding halt. */
641 else if(maxdatalen > 65536) {
642 printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
643 "using 65536\n");
644 maxdatalen = 65536;
645 }
646 return xt_register_matches(xt_layer7_match,
647 ARRAY_SIZE(xt_layer7_match));
648 }
649
650 static void __exit xt_layer7_fini(void)
651 {
652 remove_proc_entry("layer7_numpackets", init_net.proc_net);
653 xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
654 }
655
656 module_init(xt_layer7_init);
657 module_exit(xt_layer7_fini);
658