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 ============================================= |