Hi,
I have a problem in writing netfilter
module.
the purpose of this program is to forward packets which is
incoming specified port number to specified destination address(with specified
port).
the problem I met is occured when executing
"skb2->dst->output(skb2)".
whenever I tested this program, linux box was
crashed.
i'll explain the flow of this program.
.- netfilter module receives packet.
.- if this packet is from port 9999, forward it to
210.111.222.111:9999. otherwise, do nothing...
Could you explain your briliant solution?? I
hope..
Thanks.
================= Source
Code ==========================================
#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include
<linux/kernel.h>
#include <linux/skbuff.h>
#include
<linux/netdevice.h>
#include <linux/mm.h>
#include
<asm/uaccess.h>
#include <linux/string.h>
#include <linux/socket.h>
#include
<linux/ip.h>
#include <linux/tcp.h>
#include
<linux/icmp.h>
#include <linux/inet.h>
#include <linux/netfilter.h>
#include
<linux/netfilter_ipv4.h>
#include <linux/interrupt.h>
#include <net/route.h>
#include
<net/sock.h>
struct nf_hook_ops pre_routing_filter;
char *next_node_ip_address = "210.111.222.111";
short
DEST_PORT = 9999;
int change_daddr(struct sk_buff
**pskb)
{
((*pskb)->nh.iph)->daddr =
in_aton(next_node_ip_address);
((*pskb)->h.th)->dest = htons(DEST_PORT);
(*pskb)->nfcache |=
NFC_ALTERED;
return 1;
}
static int route_me_harder(struct sk_buff
*skb)
{
struct iphdr *iph =
skb->nh.iph;
struct rtable
*rt;
struct rt_key key =
{
dst:iph->daddr,
src:iph->saddr,
oif:skb->sk ? skb->sk->bound_dev_if :
0,
tos:RT_TOS(iph->tos)|RTO_CONN,
#ifdef
CONFIG_IP_ROUTE_FWMARK
fwmark:skb->nfmark
#endif
};
if (ip_route_output_key(&rt,
&key) != 0)
{
printk("route_me_harder: No more route.\n");
return -EINVAL;
}
dst_release(skb->dst);
skb->dst =
&rt->u.dst;
return 0;
}
unsigned int pre_routing_handler(unsigned int
hooknum,
struct sk_buff
**skb,
const struct net_device
*in,
const struct net_device *out)
{
struct iphdr *iph;
struct tcphdr
*tcph;
struct sk_buff *skb2 =
NULL;
iph =
(*skb)->nh.iph;
tcph = (struct
tcphdr*)((__u32 *)iph+iph->ihl);
if(ntohs(tcph->dest) ==
DEST_PORT)
{
skb2 = skb_clone(*skb,
GFP_ATOMIC);
if(change_daddr(&skb2)){
if(route_me_harder(skb2) !=
0){
kfree_skb(skb2);
}
skb2->dst->output(skb2);
return
NF_ACCEPT;
}
}
return 0;
}
int init_module(void)
{
int result;
/* pre_routing hook
*/
pre_routing_filter.list.next =
NULL;
pre_routing_filter.list.prev
= NULL;
pre_routing_filter.hook =
(nf_hookfn*)pre_routing_handler;
pre_routing_filter.pf = PF_INET;
/* IPv4 */
pre_routing_filter.hooknum =
NF_IP_PRE_ROUTING;
pre_routing_filter.priority = NF_IP_PRI_FILTER;
/* hooks registration
*/
result =
nf_register_hook(&pre_routing_filter);
if(result){
goto hook_failed;
}
return 0;
hook_failed:
return result;
/* error registering hooks */
}
void
cleanup_module(void)
{
/*
unregister hooks */
nf_unregister_hook(&pre_routing_filter);
printk("cleanup_module\n");
}
============== End of Source Code
=============================================