8ff74a8d87a1d9499f3d2940472debc9fb9e1dfa
[kernel-bfs] / kernel-bfs-2.6.28 / debian / joikuspot / JoikuSpot_Bouncer.c
1 /* 
2  * Implementation of JoikuSpotBouncer module
3  * JoikuSpot_Bouncer.c
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version
8  * 2 of the license, or ( at your option ) any later version
9  */
10
11 #include <linux/module.h>         /* needed by all kernel modules          */
12 #include <linux/init.h>           /* needed for custom init/exit functions */
13 #include <linux/kernel.h>         /* needed for KERN_ALERT macro           */
14 #include <linux/netfilter.h>      /* Hook register/unregister              */
15 #include <linux/netfilter_ipv4.h> /* nf_hook_priorities                    */
16 #include <linux/ip.h>             /* Ip header                             */
17 #include <linux/tcp.h>            /* Tcp Header                            */
18 #include <linux/udp.h>            /* Udp Header                            */
19 #include <net/inet_hashtables.h>  /* __inet_lookup()                       */
20 #include <net/inet_sock.h>        /* struct inet_sock                      */
21
22
23 /* Special macro to indicate license (to avoid tainting the kernel) */
24
25 MODULE_LICENSE( "Dual MIT/GPL" );
26 MODULE_AUTHOR ( "JoikuSoft Oy Ltd <info@joikusoft.com>" );
27
28 extern struct inet_hashinfo tcp_hashinfo;
29 extern struct proto udp_prot;
30 extern struct rwlock_t udp_hash_lock;
31
32 static struct sock *__udp4_lib_lookup( struct net *net ,
33     unsigned long int saddr ,
34     unsigned short int sport ,
35     unsigned long int daddr ,
36     unsigned short int dport ,
37     int dif ,
38     struct hlist_head udptable[] )
39     {
40     struct sock *sk , *result = NULL;
41     struct hlist_node *node;
42     unsigned short int hnum = ntohs( dport );
43     int badness = -1;
44
45     read_lock( &udp_hash_lock );
46
47     sk_for_each ( sk , node , &udptable[ udp_hashfn ( net , hnum ) ] )
48         {
49         struct inet_sock *inet = inet_sk( sk );
50
51         if ( net_eq ( sock_net( sk ) , net ) && sk->sk_hash == hnum &&
52             !ipv6_only_sock( sk ) )
53             {
54
55             int score = ( sk->sk_family == PF_INET ? 1 : 0 );
56
57             if ( inet->rcv_saddr )
58                 {
59                 if ( inet->rcv_saddr != daddr )
60                     {
61                     continue;
62                     }
63                 score += 2;
64                 }
65             if ( inet->daddr )
66                 {
67                 if ( inet->daddr != saddr )
68                     {
69                     continue;
70                     }
71                 score += 2;
72                 }
73             if ( inet->dport )
74                 {
75                 if ( inet->dport != sport )
76                     {
77                     continue;
78                     }
79                 score += 2;
80                 }
81             if ( sk->sk_bound_dev_if )
82                 {
83                 if ( sk->sk_bound_dev_if != dif )
84                     {
85                     continue;
86                     }
87                 score += 2;
88                 }
89             if ( score == 9 )
90                 {
91                 result = sk;
92                 break;
93                 }
94                 else if ( score > badness )
95                 {
96                 result  = sk;
97                 badness = score;
98                 }
99             }
100         }
101     if ( result )
102         {
103         sock_hold ( result );
104         }
105     read_unlock ( &udp_hash_lock );
106     return result;
107     }
108
109
110 static unsigned int joikuspot_nf_hook ( unsigned int hook ,
111     struct sk_buff *pskb ,
112     const struct net_device *in ,
113     const struct net_device *out ,
114     int ( *okfn ) ( struct sk_buff * ) )
115     {
116     struct sock *sk;
117     struct iphdr *iph = ipip_hdr ( pskb );
118
119     if ( iph->protocol == 6 )
120         {
121         struct tcphdr *th, tcph;
122
123         th = skb_header_pointer (
124             pskb , iph->ihl << 2 , sizeof( tcph ) , &tcph );
125
126         sk = __inet_lookup( dev_net ( pskb->dst->dev ) , &tcp_hashinfo , 
127             iph->saddr , th->source , iph->daddr , th->dest , inet_iif ( pskb ) );
128
129         if( !sk )
130             {
131             return NF_DROP;
132             }
133         else
134             {
135             return NF_ACCEPT;
136             }
137         }
138
139     if ( iph->protocol == 17 )
140         {
141         struct udphdr *uh, udph;
142
143         uh = skb_header_pointer (
144             pskb , iph->ihl << 2 , sizeof( udph ) , &udph );
145
146         sk = __udp4_lib_lookup( dev_net ( pskb->dst->dev ) , iph->saddr , uh->source ,
147             iph->daddr , uh->dest , inet_iif ( pskb ) , udp_prot.h.udp_hash );
148
149         if ( sk != NULL )
150             {
151             return NF_ACCEPT;
152             }
153         else
154             {
155             return NF_DROP;
156             }
157         }
158
159     return NF_ACCEPT;
160     }
161
162
163 static struct nf_hook_ops joikuspot_ops =
164     {
165     .hook     = joikuspot_nf_hook,
166     .owner    = THIS_MODULE,
167     .pf       = PF_INET,
168     .hooknum  = NF_INET_LOCAL_IN,
169     .priority = NF_IP_PRI_FIRST
170     };
171
172 static int joikuspot_init( void )
173     {
174     int retval = 0;
175
176     printk( KERN_DEBUG "JoikuSpot Bouncer Kernel Module init\n" );
177
178     retval = nf_register_hook( &joikuspot_ops );
179
180     if ( retval < 0 )
181         {
182         return retval;
183         }
184
185     return retval;
186     }
187
188 static void joikuspot_exit( void ) 
189     {
190     nf_unregister_hook ( &joikuspot_ops );
191     printk( KERN_DEBUG "JoikuSpot Bouncer Kernel Module exit\n" );
192     }
193
194 module_init( joikuspot_init ); 
195 module_exit( joikuspot_exit );
196