免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1631 | 回复: 4
打印 上一主题 下一主题

[网络] 使用 Netlink 和 内核通信 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-05 15:16 |只看该作者 |倒序浏览
写一个独立的模块并加载到pc上,应用和内核两端收发是正常的。集成后,应用发送数据内核可以收到,但内核发送数据应用无反应,怀疑是netlink创建出现问题(内核是以多播的方式发送)?netlink初始化如下,请各位大虾明示:
        int len = sizeof(link_sock.nl);
        link_sock.link_nl = socket(AF_NETLINK,SOCK_RAW,NETLINK_LINK);
        if(link_sock.link_nl < 0) {
                perror("create link socket :");
                return -1;
        }

        memset(&peer, 0, sizeof(struct sockaddr_nl));
        peer.nl_family = AF_NETLINK;
        peer.nl_pid = 0;
        peer.nl_groups = 0;

        memset(&link_sock.nl,0,len);
        link_sock.nl.nl_family = AF_NETLINK;
        link_sock.nl.nl_groups = ASNTGRP_LINK_IF;
        //link_sock.nl.nl_groups = 0;
        link_sock.nl.nl_pad = 0;
        link_sock.nl.nl_pid = getpid();
        //link_sock.nl.nl_pid = 0;

        //setsockopt(link_sock.link_nl,SOL_SOCKET,NETLINK_ADD_MEMBERSHIP,&link_sock.nl.nl_groups,sizeof(link_sock.nl.nl_groups));

        if(bind(link_sock.link_nl,(struct sockaddr *)&link_sock.nl,len) < 0) {
                perror("link socket bind :");
                return -1;
        }
        /*这句话有什么作用??*/
        if (getsockname(link_sock.link_nl, (struct sockaddr *) &link_sock.nl, (void *)&len) < 0) {
                perror("Getsockname failed ");
                exit(-1);
        }

论坛徽章:
1
射手座
日期:2013-11-07 09:19:48
2 [报告]
发表于 2013-11-05 18:10 |只看该作者
getsockname有什么用请google。
内核的代码也一并贴出来,应用程序没反应有可能是应用程序的问题,也有可能是内核代码发送有问题。

论坛徽章:
0
3 [报告]
发表于 2013-11-05 21:52 |只看该作者
static int link_netlink_receive_peer(unsigned char type, void *msg, unsigned int len)
{
        int ret = 0;


        switch (type) {
        case 1:
                printk("***************recv successful***********************\n");
                break;
        default:
                printk("link-netlink: Unknown message type\n");
                ret = -EINVAL;
                break;
        }
        return ret;
}
static struct sk_buff* link_netlink_build_msg(int type, void *data, int len)
{
        unsigned char *old_tail;
        size_t size = 0;
        struct sk_buff *skb;
        struct nlmsghdr *nlh;
        void *m;

        size = NLMSG_SPACE(len);
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb)
                goto nlmsg_failure;
        old_tail = skb_tail_pointer(skb);
        nlh = NLMSG_PUT(skb, 0, 0, type, size - sizeof(*nlh));
        m = NLMSG_DATA(nlh);
        memcpy(m, data, len);
        nlh->nlmsg_len = skb_tail_pointer(skb) - old_tail;
        NETLINK_CB(skb).pid = 0; /*from kernel*/
        NETLINK_CB(skb).dst_group = ASNTGRP_LINK_IF;
        return skb;
nlmsg_failure:
        if(skb)
                kfree_skb(skb);
        printk("link: error creating rt timeout message\n");
        return NULL;
}
void link_netlink_send_rt_msg(int type, __u32 src, __u32 dest)
{
        //printk("*******Start send_rt_msg sucessful !*********\n");

        struct sk_buff *skb = NULL;
        struct link_rt_msg m;
        int ret = 0;
        memset(&m, 0, sizeof(m));

        m.src = src;
        m.dest = dest;

        skb = link_netlink_build_msg(type, &m, sizeof(struct link_rt_msg));

        //printk("Send_rt_msg : *******build_msg sucessful !*********  peer_pid === %d\n",peer_pid);

        if (skb == NULL)
        {
                printk("link_netlink: skb = NULL\n");
                return;
        }
        /*netlink_unicast(linknl, skb, peer_pid, MSG_DOWNWAIT)*/
        ret = netlink_broadcast(linknl, skb, 0, ASNTGRP_LINK_IF, GFP_KERNEL);
        printk("ret === %d\n",ret);
}

#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)

static inline void link_netlink_rcv_skb(struct sk_buff *skb)
{


        int status, type, pid, flags, nlmsglen, skblen;
        struct nlmsghdr *nlh;

        //printk("*******Start link_netlink_rcv_skb sucessful !********* %d\n",nlmsglen);
        skblen = skb->len;
        if (skblen < sizeof(struct nlmsghdr)) {
                printk("skblen to small\n");
                return;
        }

        nlh = (struct nlmsghdr *)skb->data;
        nlmsglen = nlh->nlmsg_len;

        if (nlmsglen < sizeof(struct nlmsghdr) || skblen < nlmsglen) {
                printk("nlsmsg=%d skblen=%d to small\n", nlmsglen, skblen);
                return;
        }

        pid = nlh->nlmsg_pid;
        flags = nlh->nlmsg_flags;

        if (pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
                RCV_SKB_FAIL(-EINVAL);

        if (flags & MSG_TRUNC)
                            RCV_SKB_FAIL(-ECOMM);

        type = nlh->nlmsg_type;

        //printk("***************Type = %d*********************\n",type);


        if (peer_pid) {
                if (peer_pid != pid) {
                        //write_unlock_bh(&queue_lock);
                        RCV_SKB_FAIL(-EBUSY);
                }
        } else
                peer_pid = pid;

        //printk("***************Send sucessful!********************\n");        //write_unlock_bh(&queue_lock);

        status = link_netlink_receive_peer(type, NLMSG_DATA(nlh),
                                            skblen - NLMSG_LENGTH(0));
        if (status < 0)
                printk("RCV_SKB_FAIL(status)\n");

        if (flags & NLM_F_ACK)
                netlink_ack(skb, nlh, 0);

        link_netlink_send_rt_msg(MSG_1,1,2);

        return;
}

int link_netlink_init(void)
{
    linknl = netlink_kernel_create(&init_net, NETLINK_LINK, 0, link_netlink_rcv_skb, NULL, THIS_MODULE);

     printk("*******linknl create sucessful !*********\n");

    if (linknl == NULL)
    {
        printk(KERN_ERR "link_netlink: failed to create netlink socket\n");
        return -1;
    }
    return 0;
}

论坛徽章:
0
4 [报告]
发表于 2013-11-05 21:53 |只看该作者
发送应该没有问题,我检测了返回值。

论坛徽章:
1
天蝎座
日期:2013-12-06 18:23:58
5 [报告]
发表于 2013-11-07 21:30 |只看该作者
netlink想起来就是泪啊,回头看看你的码,要是能用code标注起来就好了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP