求大神帮帮忙 发表于 2014-05-14 14:17

linux内核中怎样根据端口号获得与之对应sock

刚刚接触linux内核编程,在练习写一个netfilter的模块:通过local_in和local_out两个点来截取数据包,之后从数据包里面获取struct sock的指针。
在local_out里面可以在sk_buff直接获取。但是,local_in就有麻烦了,sk_buff里面的sk成员因为还在ip层,没有填写(为NULL)。
试过:分协议,利用IP层以上的函数来查找。以TCP为例用inet_lookup函数获取,但是得到的还是null。
求解:有什么办法可以解决?

求大神帮帮忙 发表于 2014-05-14 14:20

二楼附上代码:#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <net/tcp.h>
#include <net/inet_hashtables.h>
#include <linux/ip.h>
#include <linux/net.h>
#include <net/sock.h>

static struct nf_hook_ops nfno;
static struct nf_hook_ops nfno2;

static unsigned int my_hook_fun(unsigned int hooknum,
                                        struct sk_buff **skb,
                                        const struct net_device *in,
                                        const struct net_device *out,
                                        int (*okfn)(struct sk_buff *))
{
        struct iphdr * iph = (*skb)->nh.iph;
        struct tcphdr * tcph = (struct tcphdr *)((__u32*)iph+iph->ihl);
        struct udphdr * udph = (struct udphdr *)((__u32*)iph+iph->ihl);
        struct sock *sk;
        if(hooknum == NF_IP_LOCAL_OUT)
        {
                printk("send a pack\n");
        }
        else
        {
                printk("recv a pack\n");
        }
        sk = (*skb)->sk;
        if(iph->protocol == 6 )
        {
                printk("tcp,source port %d , dst port %d\n",ntohs(tcph->source),ntohs(tcph->dest));
                if(sk==NULL)
                {
                        sk = inet_lookup(&tcp_hashinfo,iph->saddr,tcph->source,iph->daddr,ntohs(tcph->dest),inet_iif(*skb));
                       
                }
       
        }
        else if(iph->protocol == 17)
        {
                printk("udp,source prot %d, dst prot %d\n",ntohs(udph->source),ntohs(udph->dest));
        }
       
        if(sk!=NULL && sk->sk_socket!=NULL)
        printk("socket:%x \n",(unsigned int)(sk->sk_socket) );
        else
        {
                if(sk==NULL)
                {
                        printk("sk\n");
                }
                else
                {
                        printk("socket\n");
                }
        }
        return NF_ACCEPT;
}

static int __init drop_pack_ini(void)
{
        nfno.hook = my_hook_fun;
        nfno.hooknum = NF_IP_LOCAL_OUT;
        nfno.pf = PF_INET;
        nfno.priority = NF_IP_PRI_LAST;
        nf_register_hook(&nfno);
        nfno2.hook = my_hook_fun;
        nfno2.hooknum = NF_IP_LOCAL_IN;
        nfno2.pf = PF_INET;
        nfno2.priority = NF_IP_PRI_LAST;
        nf_register_hook(&nfno2);
        return 0;
}

static voiddrop_pack_exe(void)
{
        nf_unregister_hook(&nfno);
        nf_unregister_hook(&nfno2);
}

module_init(drop_pack_ini);
module_exit(drop_pack_exe);
MODULE_LICENSE("GPL");



求大神帮帮忙 发表于 2014-05-14 14:21

另外,我用的是2.6.18版本的linux内核源代码

求大神帮帮忙 发表于 2014-05-14 16:45

问题已解决:
sk = inet_lookup(&tcp_hashinfo,iph->saddr,tcph->source,iph->daddr,ntohs(tcph->dest),inet_iif(*skb));
应改为:
sk = inet_lookup(&tcp_hashinfo,iph->saddr,tcph->source,iph->daddr,tcph->dest,inet_iif(*skb));
页: [1]
查看完整版本: linux内核中怎样根据端口号获得与之对应sock