netlink socket问题,内核opps 0002

时间:2013-02-06 20:53:19

标签: linux netlink

我尝试将一些数据从用户模式发送到我的内核模块。但是当它发送内容时,会触发内核错误:

错误:无法处理内核分页请求ad ffff88022f168bc0

IP:[< ...>] build_skb + 0xf5 / 0x1c0

#include "socket.hpp"

using namespace std;

KernelSocket::KernelSocket(DataLink * dl){
    this->dl = dl;

    this->sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
    if(sock_fd<0) {
        printf("unable to create socket%d\n", sock_fd);
        exit(-1);
    }
    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid();
    //src_addr.nl_groups = 0;

    bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
    memset(&dest_addr, 0, sizeof(dest_addr));
    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK;
    dest_addr.nl_pid = 0;
    dest_addr.nl_groups = 0;

    nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
    memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;

    reportLocalAddress();

}

void KernelSocket::sendToKernel(string data){

    int length = data.length();
    char c;
    c = (length%0xff);
    data.insert(0, 1, c);
    c = (length/0xff);
    data.insert(0, 1, c);

    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;
    memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);

    iov.iov_base = (void *)nlh;
    iov.iov_len = nlh->nlmsg_len;
    //iov.iov_len = length;
    msg.msg_name = (void *)&dest_addr;
    msg.msg_namelen = sizeof(dest_addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    sendmsg(sock_fd,&msg,0);
}

void KernelSocket::reportLocalAddress(){
    int length = 6;
    string data = dl->localAddress.toString();
    data.insert(0,1, 0xff);
    data.insert(0,1, 0xff);

    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;
    memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);

    iov.iov_base = (void *)nlh;
    iov.iov_len = nlh->nlmsg_len;
    msg.msg_name = (void *)&dest_addr;
    msg.msg_namelen = sizeof(dest_addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    sendmsg(sock_fd,&msg,0);
    printf("send mac address to kernel\n");

}

void * kernelSocketWorkLoop(void * kernelSocket){
    int length,ret;
    KernelSocket * ks = (KernelSocket *) kernelSocket;
    while(1){
        ret = recvmsg(ks->sock_fd, &(ks->msg), MSG_DONTWAIT);
        if(ret>=0){
            string c;
            c.assign((char *)NLMSG_DATA(ks->nlh));
            length = c[0]*0xff+c[1];
            ks->dl->packetDownBuffer.push(c);

        }
        sleep(1);
    }
}

我现在正在使用此期间代码。有人对这个问题有意见吗?感谢〜

这是我用来接收消息的内核模块中的函数。

static void ss_recv(struct sk_buff *skb){
    struct nlmsghdr *nlh;
    int len;
    char * c;
    struct uwmodem_priv* priv = NULL;
    priv = netdev_priv(dev);

    printk("in ss_recv\n");
    nlh = (struct nlmsghdr *)skb->data;
    if(nlh->nlmsg_pid>0){
        priv->daemon_pid = nlh->nlmsg_pid;
        len = nlh->nlmsg_len - NLMSG_HDRLEN;
        c = kmalloc(len, GFP_ATOMIC);
        if(c==NULL){
            printk("Fail to allocate c\n");
        }
        memcpy(c, nlmsg_data(nlh), len);
        if(c[0]==0xff && c[1]==0xff){
            printk("Set MacAddress(%d) \n", nlh->nlmsg_pid);
            //for mac address
            memcpy(dev->dev_addr, c+2, ETH_ALEN);

        }else{
            len = c[0]*0xff+c[1];

            //printk("Kernel Length:[%d][%d][%d]\n", c[0], c[1], c[2]);

            printk("Kernel received from (%d)[%d]: \n", nlh->nlmsg_pid,len);
            uwmodem_rx(dev, c+2, len);
        }

        kfree(c);
    }
    //printk("Exit ss_recv\n");
}

0 个答案:

没有答案