Netlink socket,libnl - - nl_recvmsgs_default返回-22

时间:2015-04-16 09:46:40

标签: linux linux-kernel kernel netlink

我遇到类似的问题: Netlink sockets and libnl - nl_recvmsgs_default returning -16 (EBUSY)

nl_recvmsgs_defaul()返回此错误值-22(NLE_MSGTYPE_NOSUPPORT)。

有谁知道我为什么会收到这个错误?

以下是示例程序:

内核:

enum {
        DOC_EXMPL_A_UNSPEC,
        DOC_EXMPL_A_MSG,
        __DOC_EXMPL_A_MAX,
};
#define DOC_EXMPL_A_MAX (__DOC_EXMPL_A_MAX - 1)

#define VERSION_NR 1

static struct genl_family doc_exmpl_gnl_family = {
        .id = GENL_ID_GENERATE,        
        .hdrsize = 0,
        .name = "CONTROL_EXMPL",        
        .version = VERSION_NR,                     
};

enum {
        DOC_EXMPL_C_UNSPEC,
        DOC_EXMPL_C_ECHO,
        __DOC_EXMPL_C_MAX,
};
#define DOC_EXMPL_C_MAX (__DOC_EXMPL_C_MAX - 1)

int doc_exmpl_echo(struct sk_buff *skb_2, struct genl_info *info)
{
        struct sk_buff *skb;
        struct nlattr *na, *pos;
        int len, rem, type, rc;
        char * mydata;
        void *msg_head;

        if (info == NULL)
                goto out;

        len = nlmsg_attrlen(info->nlhdr, GENL_HDRLEN);
        na = nlmsg_attrdata(info->nlhdr, GENL_HDRLEN);

        printk(KERN_DEBUG "len1: %d, sizeof: %d ,len: %d", nlmsg_len(info->nlhdr),
               GENL_HDRLEN, len);

        nla_for_each_attr(pos, na, len, rem) {
                type = nla_type(pos);

                mydata = (char *) nla_data(pos);

                printk(KERN_DEBUG "Type: %d", type);

                if (mydata != NULL) 
                        printk(KERN_DEBUG "Data: %s", mydata);
        }

        skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
        if (skb == NULL)
                goto out;

        msg_head = genlmsg_put(skb, 0, info->snd_seq+1, &doc_exmpl_gnl_family, 0, DOC_EXMPL_C_ECHO);
        if (msg_head == NULL) {
                rc = -ENOMEM;
                goto out;
        }

        rc = nla_put_u8(skb, DOC_EXMPL_A_MSG, 8);
        if (rc != 0)
                goto out;

        /* finalize the message */
        genlmsg_end(skb, msg_head);

        //rc = genlmsg_unicast(skb,info->snd_pid );
        rc = genlmsg_unicast(genl_info_net(info), skb,info->snd_pid);
        if (rc != 0)
                goto out;

        printk(KERN_DEBUG "End");
        return 0;

 out:
        printk("an error occured in doc_exmpl_echo:\n");

      return 0;
}

struct genl_ops doc_exmpl_gnl_ops_echo = {
        .cmd = DOC_EXMPL_C_ECHO,
        .flags = 0,
        .policy = NULL,
        .doit = doc_exmpl_echo,
        .dumpit = NULL,
};

用户空间代码

#include <stdio.h>
#include <stdlib.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <net/if.h>

static int expectedId;

static int nlCallback(struct nl_msg* msg, void* arg)
{
    struct nlmsghdr* ret_hdr = nlmsg_hdr(msg);
    struct nlattr *tb_msg[2 + 1];
    char *str;

    if (ret_hdr->nlmsg_type != expectedId)
    {
        // what is this??
        return NL_STOP;
    }

    struct genlmsghdr *gnlh = (struct genlmsghdr*) nlmsg_data(ret_hdr);

    nla_parse(tb_msg, 2, genlmsg_attrdata(gnlh, 0),
              genlmsg_attrlen(gnlh, 0), NULL);

    if (tb_msg[1]) {
        str = nla_get_string(tb_msg[1]);

        printf("str: %s", str);
    }

    return 0;
}

int main(int argc, char **argv) {
        int cmd, rc;
        struct nl_handle *sk;
        struct nl_msg *msg;

        //allocate socket
        sk = nl_handle_alloc();

        //connect to generic netlink
        genl_connect(sk);

        //find the nl80211 driver ID
        expectedId = genl_ctrl_resolve(sk, "CONTROL_EXMPL");

        //allocate a message
        msg = nlmsg_alloc();

        cmd = 1;
        int flags = 0;

        // setup the message
        genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, expectedId, 0, NLM_F_REQUEST, cmd, 1);


        NLA_PUT_STRING(msg, 3, "Hello test");


        nl_send_auto_complete(sk, msg);


        nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM,
                            nlCallback, NULL);

        rc = nl_recvmsgs_default(sk);

        printf("rc = %d \n", rc);

        nlmsg_free(msg);

        return 0;

        nla_put_failure:
        nlmsg_free(msg);
        return 1;
}

1 个答案:

答案 0 :(得分:1)

好的,我发现了问题。

我在内核代码中有错误的序列号,它应该是:

genlmsg_put(skb,0,info-&gt; snd_seq,&amp; doc_exmpl_gnl_family,0,DOC_EXMPL_C_ECHO);

与此问题相同:Netlink sockets and libnl - nl_recvmsgs_default returning -16 (EBUSY)但我还有其他错误。