2 * Implementation of JoikuSpotBouncer module
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
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 */
23 /* Special macro to indicate license (to avoid tainting the kernel) */
25 MODULE_LICENSE( "Dual MIT/GPL" );
26 MODULE_AUTHOR ( "JoikuSoft Oy Ltd <info@joikusoft.com>" );
28 extern struct inet_hashinfo tcp_hashinfo;
29 extern struct proto udp_prot;
30 extern struct rwlock_t udp_hash_lock;
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 ,
38 struct hlist_head udptable[] )
40 struct sock *sk , *result = NULL;
41 struct hlist_node *node;
42 unsigned short int hnum = ntohs( dport );
45 read_lock( &udp_hash_lock );
47 sk_for_each ( sk , node , &udptable[ udp_hashfn ( net , hnum ) ] )
49 struct inet_sock *inet = inet_sk( sk );
51 if ( net_eq ( sock_net( sk ) , net ) && sk->sk_hash == hnum &&
52 !ipv6_only_sock( sk ) )
55 int score = ( sk->sk_family == PF_INET ? 1 : 0 );
57 if ( inet->rcv_saddr )
59 if ( inet->rcv_saddr != daddr )
67 if ( inet->daddr != saddr )
75 if ( inet->dport != sport )
81 if ( sk->sk_bound_dev_if )
83 if ( sk->sk_bound_dev_if != dif )
94 else if ( score > badness )
103 sock_hold ( result );
105 read_unlock ( &udp_hash_lock );
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 * ) )
117 struct iphdr *iph = ipip_hdr ( pskb );
119 if ( iph->protocol == 6 )
121 struct tcphdr *th, tcph;
123 th = skb_header_pointer (
124 pskb , iph->ihl << 2 , sizeof( tcph ) , &tcph );
126 sk = __inet_lookup( dev_net ( pskb->dst->dev ) , &tcp_hashinfo ,
127 iph->saddr , th->source , iph->daddr , th->dest , inet_iif ( pskb ) );
139 if ( iph->protocol == 17 )
141 struct udphdr *uh, udph;
143 uh = skb_header_pointer (
144 pskb , iph->ihl << 2 , sizeof( udph ) , &udph );
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 );
163 static struct nf_hook_ops joikuspot_ops =
165 .hook = joikuspot_nf_hook,
166 .owner = THIS_MODULE,
168 .hooknum = NF_INET_LOCAL_IN,
169 .priority = NF_IP_PRI_FIRST
172 static int joikuspot_init( void )
176 printk( KERN_DEBUG "JoikuSpot Bouncer Kernel Module init\n" );
178 retval = nf_register_hook( &joikuspot_ops );
188 static void joikuspot_exit( void )
190 nf_unregister_hook ( &joikuspot_ops );
191 printk( KERN_DEBUG "JoikuSpot Bouncer Kernel Module exit\n" );
194 module_init( joikuspot_init );
195 module_exit( joikuspot_exit );