27
27
#define KFDNS_PROCFS_STAT "kfdns"
28
28
#define DNS_HEADER_SIZE 12
29
29
30
-
31
30
struct ipstat_tree_node {
32
31
struct rb_node node ;
33
32
uint ip ;
@@ -75,58 +74,61 @@ static int hysteresis;
75
74
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
76
75
*/
77
76
78
- static void kfdns_send_tc_packet (struct sk_buff * in_skb , uint dst_ip , uint dst_port , uint src_ip , const unsigned char * data )
77
+ static void kfdns_send_tc_packet (struct sk_buff * in_skb , uint dst_ip ,
78
+ uint dst_port , uint src_ip ,
79
+ const unsigned char * data )
79
80
{
80
81
unsigned char * ndata ;
81
82
struct sk_buff * nskb ;
82
83
struct iphdr * iph ;
83
84
struct udphdr * udph ;
84
85
int udp_len ;
85
86
86
- udp_len = sizeof (struct udphdr ) + DNS_HEADER_SIZE ;
87
+ udp_len = sizeof (struct udphdr ) + DNS_HEADER_SIZE ;
87
88
nskb = alloc_skb (sizeof (struct iphdr ) + udp_len +
88
- LL_MAX_HEADER , GFP_ATOMIC );
89
+ LL_MAX_HEADER , GFP_ATOMIC );
89
90
if (!nskb ) {
90
- printk (KERN_ERR "kfdns: Error, can`t allocate memory to DNS reply\n" );
91
+ printk (KERN_ERR
92
+ "kfdns: Error, can`t allocate memory to DNS reply\n" );
91
93
return ;
92
94
}
93
95
skb_reserve (nskb , LL_MAX_HEADER );
94
96
skb_reset_network_header (nskb );
95
97
96
98
iph = (struct iphdr * )skb_put (nskb , sizeof (struct iphdr ));
97
- iph -> version = 4 ;
98
- iph -> ihl = sizeof (struct iphdr ) / 4 ;
99
- iph -> ttl = 64 ;
100
- iph -> tos = 0 ;
101
- iph -> id = 0 ;
102
- iph -> frag_off = htons (IP_DF );
103
- iph -> protocol = IPPROTO_UDP ;
104
- iph -> saddr = src_ip ;
105
- iph -> daddr = dst_ip ;
106
- iph -> tot_len = htons (sizeof (struct iphdr ) + udp_len );
107
- iph -> check = 0 ;
108
- iph -> check = ip_fast_csum ((unsigned char * )iph , iph -> ihl );
109
-
99
+ iph -> version = 4 ;
100
+ iph -> ihl = sizeof (struct iphdr ) / 4 ;
101
+ iph -> ttl = 64 ;
102
+ iph -> tos = 0 ;
103
+ iph -> id = 0 ;
104
+ iph -> frag_off = htons (IP_DF );
105
+ iph -> protocol = IPPROTO_UDP ;
106
+ iph -> saddr = src_ip ;
107
+ iph -> daddr = dst_ip ;
108
+ iph -> tot_len = htons (sizeof (struct iphdr ) + udp_len );
109
+ iph -> check = 0 ;
110
+ iph -> check = ip_fast_csum ((unsigned char * )iph , iph -> ihl );
111
+
110
112
udph = (struct udphdr * )skb_put (nskb , sizeof (struct udphdr ));
111
113
memset (udph , 0 , sizeof (* udph ));
112
114
udph -> source = htons (53 );
113
115
udph -> dest = dst_port ;
114
116
udph -> len = htons (udp_len );
115
117
skb_dst_set (nskb , dst_clone (skb_dst (in_skb )));
116
- nskb -> protocol = htons (ETH_P_IP );
118
+ nskb -> protocol = htons (ETH_P_IP );
117
119
ndata = (char * )skb_put (nskb , DNS_HEADER_SIZE );
118
- memcpy (ndata , data , DNS_HEADER_SIZE ); //copy header from query
119
- * (ndata + 2 ) |= 0x82 ; //set responce and tc bits
120
- * (u16 * ) (ndata + 4 ) = 0 ; //set questions = 0 to prevent warning on client side
120
+ memcpy (ndata , data , DNS_HEADER_SIZE ); //copy header from query
121
+ * (ndata + 2 ) |= 0x82 ; //set responce and tc bits
122
+ * (u16 * ) (ndata + 4 ) = 0 ; //set questions = 0 to prevent warning on client side
121
123
udph -> check = 0 ;
122
124
udph -> check = csum_tcpudp_magic (src_ip , dst_ip ,
123
- udp_len , IPPROTO_UDP ,
124
- csum_partial (udph , udp_len , 0 ));
125
- if (ip_route_me_harder (nskb , RTN_UNSPEC ))
125
+ udp_len , IPPROTO_UDP ,
126
+ csum_partial (udph , udp_len , 0 ));
127
+ if (ip_route_me_harder (nskb , RTN_UNSPEC ))
126
128
goto free_nskb ;
127
129
ip_local_out (nskb );
128
- return ;
129
-
130
+ return ;
131
+
130
132
free_nskb :
131
133
printk (KERN_ERR "Not good\n" );
132
134
kfree_skb (nskb );
@@ -137,8 +139,8 @@ static int kfdns_check_dns_header(unsigned char *data, uint len)
137
139
if (len < DNS_HEADER_SIZE )
138
140
return -1 ;
139
141
if (* (data + sizeof (u16 )) & 0x80 )
140
- return 0 ; // response
141
- return 1 ; // request
142
+ return 0 ; /* response */
143
+ return 1 ; /* request */
142
144
}
143
145
144
146
static int kfdns_blockedip_tree_insert (uint ip , uint count )
@@ -149,7 +151,7 @@ static int kfdns_blockedip_tree_insert(uint ip, uint count)
149
151
struct blockedip_tree_node * new ;
150
152
int len ;
151
153
unsigned long flags ;
152
- while (* link ) {
154
+ while (* link ) {
153
155
parent = * link ;
154
156
data = rb_entry (parent , struct blockedip_tree_node , node );
155
157
if (ip < data -> ip )
@@ -167,7 +169,6 @@ static int kfdns_blockedip_tree_insert(uint ip, uint count)
167
169
write_lock_irqsave (& rwlock , flags );
168
170
new -> ip = ip ;
169
171
new -> counter = count ;
170
- // printk(KERN_INFO "kfdns: ip: %i blocked for DNS requests via UDP", new->ip);
171
172
rb_link_node (& new -> node , parent , link );
172
173
rb_insert_color (& new -> node , & kfdns_blockedip_tree );
173
174
write_unlock_irqrestore (& rwlock , flags );
@@ -182,7 +183,7 @@ static void kfdns_blockedip_tree_free(void)
182
183
struct blockedip_tree_node * data ;
183
184
unsigned long flags ;
184
185
write_lock_irqsave (& rwlock , flags );
185
- while (n ) {
186
+ while (n ) {
186
187
if (n -> rb_left ) {
187
188
n = n -> rb_left ;
188
189
continue ;
@@ -251,7 +252,7 @@ static struct ipstat_tree_node *rb_ipstat_insert_and_count(uint ip)
251
252
struct ipstat_tree_node * data ;
252
253
struct ipstat_tree_node * new ;
253
254
int len ;
254
- while (* link ) {
255
+ while (* link ) {
255
256
parent = * link ;
256
257
data = rb_entry (parent , struct ipstat_tree_node , node );
257
258
if (ip < data -> ip )
@@ -265,7 +266,7 @@ static struct ipstat_tree_node *rb_ipstat_insert_and_count(uint ip)
265
266
}
266
267
len = sizeof (struct ipstat_tree_node );
267
268
new = kzalloc (len , GFP_KERNEL );
268
- if (!new )
269
+ if (!new )
269
270
return NULL ;
270
271
new -> ip = ip ;
271
272
new -> counter = 1 ;
@@ -292,7 +293,8 @@ static int rb_ipstat_fire(void)
292
293
data = rb_entry (n , struct ipstat_tree_node , node );
293
294
if (data ) {
294
295
if (data -> counter >= threshold ) {
295
- if (kfdns_blockedip_tree_insert (data -> ip , data -> counter ) < 0 )
296
+ if (kfdns_blockedip_tree_insert
297
+ (data -> ip , data -> counter ) < 0 )
296
298
return - ENOMEM ;
297
299
} else if (data -> counter < threshold - hysteresis ) {
298
300
kfdns_blockedip_tree_del_ip (data -> ip );
@@ -341,11 +343,11 @@ static int kfdns_update_stat(void)
341
343
get_online_cpus ();
342
344
for_each_online_cpu (cpu ) {
343
345
p = per_cpu_ptr (raw_counter_pcpu , cpu );
344
- for (;;) {
346
+ for (;;) {
345
347
got = kfifo_get (& p -> fifo , & ip );
346
348
if (!got )
347
349
break ;
348
- if (!rb_ipstat_insert_and_count (ip )) {
350
+ if (!rb_ipstat_insert_and_count (ip )) {
349
351
err = - ENOMEM ;
350
352
break ;
351
353
}
@@ -372,23 +374,25 @@ static void kfdns_add_ip(uint ip)
372
374
static int kfdns_counter_fn (void * data )
373
375
{
374
376
int err ;
375
- for (;;) {
377
+ for (;;) {
376
378
set_current_state (TASK_INTERRUPTIBLE );
377
379
msleep (period );
378
380
if (kthread_should_stop ())
379
381
break ;
380
382
if ((err = kfdns_update_stat ())) {
381
- printk (KERN_ERR "kfdns: error while counting stats, err: %i\n" , err );
383
+ printk (KERN_ERR
384
+ "kfdns: error while counting stats, err: %i\n" ,
385
+ err );
382
386
}
383
387
}
384
388
return 0 ;
385
389
}
386
390
387
391
static uint kfdns_packet_hook (uint hooknum ,
388
- struct sk_buff * skb ,
389
- const struct net_device * in ,
390
- const struct net_device * out ,
391
- int (* okfn )(struct sk_buff * ) )
392
+ struct sk_buff * skb ,
393
+ const struct net_device * in ,
394
+ const struct net_device * out ,
395
+ int (* okfn ) (struct sk_buff * ))
392
396
{
393
397
struct iphdr * ip ;
394
398
struct udphdr * udp ;
@@ -401,15 +405,23 @@ static uint kfdns_packet_hook(uint hooknum,
401
405
skb_set_transport_header (skb , ip -> ihl * 4 );
402
406
udp = (struct udphdr * )skb_transport_header (skb );
403
407
if (udp -> dest == htons (53 )) {
404
- datalen = skb -> len - sizeof (struct iphdr ) - sizeof (struct udphdr );
405
- data = skb -> data + sizeof (struct udphdr ) + sizeof (struct iphdr );
406
- //Drop packet if it hasn`t got valid dns query header
408
+ datalen =
409
+ skb -> len - sizeof (struct iphdr ) -
410
+ sizeof (struct udphdr );
411
+ data =
412
+ skb -> data + sizeof (struct udphdr ) +
413
+ sizeof (struct iphdr );
414
+ /* Drop packet if it hasn`t got
415
+ * valid dns query header */
407
416
query = kfdns_check_dns_header (data , datalen );
408
417
if (query < 0 || (query == 0 && forward == 0 ))
409
418
return NF_DROP ;
410
419
kfdns_add_ip (ip -> saddr );
411
- if (kfdns_blockedip_tree_search (ip -> saddr ) && (noop == 0 )) {
412
- kfdns_send_tc_packet (skb , ip -> saddr , udp -> source , ip -> daddr , data );
420
+ if (kfdns_blockedip_tree_search (ip -> saddr )
421
+ && (noop == 0 )) {
422
+ kfdns_send_tc_packet (skb , ip -> saddr ,
423
+ udp -> source ,
424
+ ip -> daddr , data );
413
425
return NF_DROP ;
414
426
}
415
427
}
@@ -418,7 +430,7 @@ static uint kfdns_packet_hook(uint hooknum,
418
430
return NF_ACCEPT ;
419
431
}
420
432
421
- static void * kfdns_seq_start (struct seq_file * seq , loff_t * pos )
433
+ static void * kfdns_seq_start (struct seq_file * seq , loff_t * pos )
422
434
{
423
435
struct rb_node * node ;
424
436
int n = * pos ;
@@ -433,15 +445,15 @@ static void *kfdns_seq_start(struct seq_file *seq, loff_t *pos)
433
445
return node ;
434
446
}
435
447
436
- static void * kfdns_seq_next (struct seq_file * s , void * v , loff_t * pos )
448
+ static void * kfdns_seq_next (struct seq_file * s , void * v , loff_t * pos )
437
449
{
438
450
struct rb_node * node = v ;
439
451
440
452
(* pos )++ ;
441
453
442
454
if (v == SEQ_START_TOKEN )
443
455
return rb_first (& kfdns_blockedip_tree );
444
-
456
+
445
457
return rb_next (node );
446
458
}
447
459
@@ -452,39 +464,41 @@ static void kfdns_seq_stop(struct seq_file *s, void *v)
452
464
453
465
static int kfdns_seq_show (struct seq_file * seq , void * v )
454
466
{
455
- struct blockedip_tree_node * l = container_of (v , struct blockedip_tree_node , node );
467
+ struct blockedip_tree_node * l =
468
+ container_of (v , struct blockedip_tree_node , node );
456
469
if (v == SEQ_START_TOKEN ) {
457
- seq_puts (seq , "IP counter\n" );
470
+ seq_puts (seq , "IP counter\n" );
458
471
} else {
459
472
seq_printf (seq , "%pI4 %u\n" , & l -> ip , l -> counter );
460
473
}
461
474
return 0 ;
462
475
}
463
476
464
477
static const struct seq_operations kfdns_seq_ops = {
465
- .start = kfdns_seq_start ,
466
- .next = kfdns_seq_next ,
467
- .stop = kfdns_seq_stop ,
468
- .show = kfdns_seq_show ,
478
+ .start = kfdns_seq_start ,
479
+ .next = kfdns_seq_next ,
480
+ .stop = kfdns_seq_stop ,
481
+ .show = kfdns_seq_show ,
469
482
};
470
483
471
484
static int kfdns_seq_open (struct inode * inode , struct file * file )
472
485
{
473
486
return seq_open_net (inode , file , & kfdns_seq_ops ,
474
- sizeof (struct neigh_seq_state ));
487
+ sizeof (struct neigh_seq_state ));
475
488
}
476
489
477
490
static const struct file_operations kfdns_seq_fops = {
478
- .owner = THIS_MODULE ,
479
- .open = kfdns_seq_open ,
480
- .read = seq_read ,
481
- .llseek = seq_lseek ,
482
- .release = seq_release_net ,
491
+ .owner = THIS_MODULE ,
492
+ .open = kfdns_seq_open ,
493
+ .read = seq_read ,
494
+ .llseek = seq_lseek ,
495
+ .release = seq_release_net ,
483
496
};
484
497
485
498
static int kfdns_net_init (struct net * net )
486
499
{
487
- if (!proc_create (KFDNS_PROCFS_STAT , S_IRUGO , net -> proc_net , & kfdns_seq_fops ))
500
+ if (!proc_create
501
+ (KFDNS_PROCFS_STAT , S_IRUGO , net -> proc_net , & kfdns_seq_fops ))
488
502
return - ENOMEM ;
489
503
return 0 ;
490
504
}
@@ -505,12 +519,13 @@ static int kfdns_raw_counter_init(void)
505
519
struct raw_counter * p ;
506
520
raw_counter_pcpu = alloc_percpu (struct raw_counter );
507
521
if (!raw_counter_pcpu ) {
508
- printk (KERN_ERR "kfdns: memory allocation for raw_counter_pcpu failed\n" );
522
+ printk (KERN_ERR
523
+ "kfdns: memory allocation for raw_counter_pcpu failed\n" );
509
524
return - ENOMEM ;
510
525
}
511
526
get_online_cpus ();
512
527
preempt_disable ();
513
- for_each_online_cpu (cpu ) {
528
+ for_each_online_cpu (cpu ) {
514
529
p = per_cpu_ptr (raw_counter_pcpu , cpu );
515
530
INIT_KFIFO (p -> fifo );
516
531
}
@@ -531,17 +546,21 @@ static int kfdns_init(void)
531
546
{
532
547
int err ;
533
548
if (period <= 0 || period > 1000 ) {
534
- printk (KERN_INFO "kfdns: period should be in range 1 ... 1000, forcing default value 100 \n" );
549
+ printk (KERN_INFO
550
+ "kfdns: period should be in range 1 ... 1000, forcing default value 100 \n" );
535
551
period = 100 ;
536
552
}
537
553
if (hysteresis <= 0 || hysteresis > threshold ) {
538
554
hysteresis = threshold / 10 ;
539
555
}
540
- printk (KERN_INFO "Starting kfdns module, threshold = %d, period = %d, hysteresis = %d, HZ = %d \n" , threshold , period , hysteresis , HZ );
556
+ printk (KERN_INFO
557
+ "Starting kfdns module, threshold = %d, period = %d, hysteresis = %d, HZ = %d \n" ,
558
+ threshold , period , hysteresis , HZ );
541
559
if ((err = kfdns_raw_counter_init ()))
542
560
return err ;
543
561
register_pernet_subsys (& kfdns_net_ops );
544
- kfdns_counter_thread = kthread_run (kfdns_counter_fn , NULL , "kfdns_counter_thread" );
562
+ kfdns_counter_thread =
563
+ kthread_run (kfdns_counter_fn , NULL , "kfdns_counter_thread" );
545
564
if (IS_ERR (kfdns_counter_thread )) {
546
565
printk (KERN_ERR "kfdns: creating thread failed\n" );
547
566
err = PTR_ERR (kfdns_counter_thread );
@@ -560,9 +579,10 @@ static int kfdns_init(void)
560
579
nf_register_hook (& bundle );
561
580
return 0 ;
562
581
}
582
+
563
583
static void kfdns_exit (void )
564
584
{
565
- kthread_stop (kfdns_counter_thread );
585
+ kthread_stop (kfdns_counter_thread );
566
586
nf_unregister_hook (& bundle );
567
587
rb_ipstat_free ();
568
588
kfdns_blockedip_tree_free ();
@@ -575,18 +595,18 @@ module_init(kfdns_init);
575
595
module_exit (kfdns_exit );
576
596
577
597
module_param (threshold , int , 0 );
578
- MODULE_PARM_DESC (threshold , "Number of reuests from one IP passed to dns per one period" );
598
+ MODULE_PARM_DESC (threshold ,
599
+ "Number of reuests from one IP passed to dns per one period" );
579
600
module_param (period , int , 0 );
580
601
MODULE_PARM_DESC (period , "Time between counting collected stats, ms" );
581
602
module_param (hysteresis , int , 0 );
582
603
MODULE_PARM_DESC (hysteresis , "Hysteresis" );
583
604
module_param (forward , bool , 0 );
584
- MODULE_PARM_DESC (forward , "Use hook NF_INET_FORWARD instead of NF_INET_LOCAL_IN" );
605
+ MODULE_PARM_DESC (forward ,
606
+ "Use hook NF_INET_FORWARD instead of NF_INET_LOCAL_IN" );
585
607
module_param (noop , bool , 0 );
586
608
MODULE_PARM_DESC (noop , "No Operations mode" );
587
609
588
610
MODULE_AUTHOR (
"Daniil Cherednik <[email protected] >" );
589
611
MODULE_DESCRIPTION ("filter DNS requests" );
590
612
MODULE_LICENSE ("GPL" );
591
-
592
-
0 commit comments