0

目前我正在进行一个研究项目,我们正在尝试运行一个无线网络协议,即由乌帕萨拉大学开发的 aodvuu。该协议是在 linux 内核版本 2.4 x 中开发的,现在我们正在尝试在内核版本 3.8 上运行它。以下是面临问题的相应内核代码(kaodv-netlink.c)。

#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#include <linux/config.h>
#endif
#include <linux/if.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/netlink.h>
#include <linux/version.h>
#include <linux/semaphore.h>
#include <linux/module.h>
#include <net/sock.h>

#include <linux/skbuff.h>


#ifdef KERNEL26
//#include <linux/security_2.h>
#include <linux/security.h>
#endif
#include <net/sock.h>

#include "kaodv-netlink.h"
#include "kaodv-expl.h"
#include "kaodv-queue.h"
#include "kaodv-debug.h"
#include "kaodv.h"

static int peer_pid;
struct sock *sk;
struct net *nt;

static struct sock *kaodvnl;
static DEFINE_SEMAPHORE(kaodvnl_sem);

/* For 2.4 backwards compatibility */
#ifndef KERNEL26
#define sk_receive_queue receive_queue
#define sk_socket socket
#endif

extern int active_route_timeout, qual_th, is_gateway;

static struct sk_buff *kaodv_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_PTR(skb);
    nlh = __nlmsg_put(skb, 0, 0, type, size - sizeof(*nlh),0);

    m = NLMSG_DATA(nlh);

    memcpy(m, data, len);

    nlh->nlmsg_len = SKB_TAIL_PTR(skb) - old_tail;
    NETLINK_CB(skb).portid = 0;  /* from kernel */

    return skb;

      nlmsg_failure:
    if (skb)
        kfree_skb(skb);

    printk(KERN_ERR "kaodv: error creating rt timeout message\n");

    return NULL;
}

void kaodv_netlink_send_debug_msg(char *buf, int len)
{
    struct sk_buff *skb = NULL;

    skb = kaodv_netlink_build_msg(KAODVM_DEBUG, buf, len);

    if (skb == NULL) {
        printk("kaodv_netlink: skb=NULL\n");
        return;
    }

    netlink_broadcast(kaodvnl, skb, peer_pid, AODVGRP_NOTIFY, GFP_USER);
}

void kaodv_netlink_send_rt_msg(int type, __u32 src, __u32 dest)
{
    struct sk_buff *skb = NULL;
    struct kaodv_rt_msg m;

    memset(&m, 0, sizeof(m));

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

    skb = kaodv_netlink_build_msg(type, &m, sizeof(struct kaodv_rt_msg));

    if (skb == NULL) {
        printk("kaodv_netlink: skb=NULL\n");
        return;
    }

/*  netlink_unicast(kaodvnl, skb, peer_pid, MSG_DONTWAIT); */
    netlink_broadcast(kaodvnl, skb, 0, AODVGRP_NOTIFY, GFP_USER);
}

void kaodv_netlink_send_rt_update_msg(int type, __u32 src, __u32 dest,
                      int ifindex)
{
    struct sk_buff *skb = NULL;
    struct kaodv_rt_msg m;

    memset(&m, 0, sizeof(m));

    m.type = type;
    m.src = src;
    m.dst = dest;
    m.ifindex = ifindex;

    skb = kaodv_netlink_build_msg(KAODVM_ROUTE_UPDATE, &m,
                      sizeof(struct kaodv_rt_msg));

    if (skb == NULL) {
        printk("kaodv_netlink: skb=NULL\n");
        return;
    }
    /* netlink_unicast(kaodvnl, skb, peer_pid, MSG_DONTWAIT); */
    netlink_broadcast(kaodvnl, skb, 0, AODVGRP_NOTIFY, GFP_USER);
}

void kaodv_netlink_send_rerr_msg(int type, __u32 src, __u32 dest, int ifindex)
{
    struct sk_buff *skb = NULL;
    struct kaodv_rt_msg m;

    memset(&m, 0, sizeof(m));

    m.type = type;
    m.src = src;
    m.dst = dest;
    m.ifindex = ifindex;

    skb = kaodv_netlink_build_msg(KAODVM_SEND_RERR, &m,
                      sizeof(struct kaodv_rt_msg));

    if (skb == NULL) {
        printk("kaodv_netlink: skb=NULL\n");
        return;
    }
    /* netlink_unicast(kaodvnl, skb, peer_pid, MSG_DONTWAIT); */
    netlink_broadcast(kaodvnl, skb, 0, AODVGRP_NOTIFY, GFP_USER);
}

static int kaodv_netlink_receive_peer(unsigned char type, void *msg,
                      unsigned int len)
{
    int ret = 0;
    struct kaodv_rt_msg *m;
    struct kaodv_conf_msg *cm;
    struct expl_entry e;

    KAODV_DEBUG("Received msg: %s", kaodv_msg_type_to_str(type));

    switch (type) {
    case KAODVM_ADDROUTE:
        if (len < sizeof(struct kaodv_rt_msg))
            return -EINVAL;

        m = (struct kaodv_rt_msg *)msg;

        ret = kaodv_expl_get(m->dst, &e);

        if (ret < 0) {
            ret = kaodv_expl_update(m->dst, m->nhop, m->time,
                        m->flags, m->ifindex);
        } else {
            ret = kaodv_expl_add(m->dst, m->nhop, m->time,
                         m->flags, m->ifindex);
        }
        kaodv_queue_set_verdict(KAODV_QUEUE_SEND, m->dst);
        break;
    case KAODVM_DELROUTE:
        if (len < sizeof(struct kaodv_rt_msg))
            return -EINVAL;

        m = (struct kaodv_rt_msg *)msg;
        kaodv_expl_del(m->dst);
        kaodv_queue_set_verdict(KAODV_QUEUE_DROP, m->dst);
        break;
    case KAODVM_NOROUTE_FOUND:
        if (len < sizeof(struct kaodv_rt_msg))
            return -EINVAL;

        m = (struct kaodv_rt_msg *)msg;
        KAODV_DEBUG("No route found for %s", print_ip(m->dst));
        kaodv_queue_set_verdict(KAODV_QUEUE_DROP, m->dst);
        break;
    case KAODVM_CONFIG:
        if (len < sizeof(struct kaodv_conf_msg))
            return -EINVAL;

        cm = (struct kaodv_conf_msg *)msg;
        active_route_timeout = cm->active_route_timeout;
        qual_th = cm->qual_th;
        is_gateway = cm->is_gateway;
        break;
    default:
        printk("kaodv-netlink: Unknown message type\n");
        ret = -EINVAL;
    }
    return ret;
}

static int kaodv_netlink_rcv_nl_event(struct notifier_block *this,
                      unsigned long event, void *ptr)
{
    struct netlink_notify *n = ptr;


    if (event == NETLINK_URELEASE && n->protocol == NETLINK_AODV && n->portid) {
        if (n->portid == peer_pid) {
            peer_pid = 0;
            kaodv_expl_flush();
            kaodv_queue_flush();
        }
        return NOTIFY_DONE;
    }
    return NOTIFY_DONE;
}

static struct notifier_block kaodv_nl_notifier = {
    .notifier_call = kaodv_netlink_rcv_nl_event,
};

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

static inline void kaodv_netlink_rcv_skb(struct sk_buff *skb)
{
    int status, type, pid, flags, nlmsglen, skblen;
    struct nlmsghdr *nlh;

    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("kaodv_netlink: type=%d\n", type); */
    /* if (type < NLMSG_NOOP || type >= IPQM_MAX) */
/*      RCV_SKB_FAIL(-EINVAL); */
#ifdef KERNEL26
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))

    if (security_sock_rcv_skb(skb))
        RCV_SKB_FAIL(-EPERM);
#else
    if (security_sock_rcv_skb(sk , skb))
        RCV_SKB_FAIL(-EPERM);
#endif
#endif
    //write_lock_bh(&queue_lock);

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

    //write_unlock_bh(&queue_lock);

    status = kaodv_netlink_receive_peer(type, NLMSG_DATA(nlh),
                        skblen - NLMSG_LENGTH(0));
    if (status < 0)
        RCV_SKB_FAIL(status);

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

#if 0
static void kaodv_netlink_rcv_sk(struct sock *sk, int len)
{
    do {
        struct sk_buff *skb;

        if (down_trylock(&kaodvnl_sem))
            return;

        while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
            kaodv_netlink_rcv_skb(skb);
            kfree_skb(skb);
        }

        up(&kaodvnl_sem);

    } while (kaodvnl && kaodvnl->sk_receive_queue.qlen);

    return;
}
#endif

int kaodv_netlink_init(void)
{
    netlink_register_notifier(&kaodv_nl_notifier);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
    kaodvnl = netlink_kernel_create(NETLINK_AODV, kaodv_netlink_rcv_sk);
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    kaodvnl = netlink_kernel_create(NETLINK_AODV, AODVGRP_MAX, kaodv_netlink_rcv_sk, THIS_MODULE);
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
    kaodvnl = netlink_kernel_create(NETLINK_AODV, AODVGRP_MAX, kaodv_netlink_rcv_sk, NULL, THIS_MODULE);
#else
/*  
struct netlink_kernel_cfg cfg = {
    .input = kaodv_netlink_init,
};

kaodvnl = netlink_kernel_create(&init_net, AODVGRP_MAX, &cfg);
*/
kaodvnl = netlink_kernel_create(&init_net,AODVGRP_MAX,
                    kaodv_netlink_rcv_skb, NULL);

static void kaodv_netlink_rcv_sk(struct sk_buff *skb)
 {

struct netlink_kernel_cfg cfg = {
    .input = recv_cmd,
};


kaodvnl = netlink_kernel_create(&init_net, AODVGRP_MAX,cfg);
if (kaodvnl == NULL) {
        printk(KERN_ERR "kaodv_netlink: failed to create netlink socket\n");
        netlink_unregister_notifier(&kaodv_nl_notifier);
        return -1;
    }

return 0;
}
#endif

    return 0;
}

void kaodv_netlink_fini(void)
{
    sock_release(kaodvnl->sk_socket);
    down(&kaodvnl_sem);
    up(&kaodvnl_sem);

    netlink_unregister_notifier(&kaodv_nl_notifier);
}

我得到的错误是

timer_queue.o aodv_socket.o aodv_hello.o aodv_neighbor.o aodv_timeout.o routing_table.o seek_list.o aodv_rreq.o aodv_rrep.o aodv_rerr.o nl.o locality.o 
make -C /home/lp3/aodvuu096/lnx KERNEL_DIR=/lib/modules/3.8.0-31-generic/build KCC=gcc XDEFS=-DDEBUG
make[1]: Entering directory `/home/lp3/aodvuu096/lnx'
make -C /lib/modules/3.8.0-31-generic/build M=/home/lp3/aodvuu096/lnx modules
make[2]: Entering directory `/usr/src/linux-headers-3.8.0-31-generic'
  CC [M]  /home/lp3/aodvuu096/lnx/kaodv-mod.o
  CC [M]  /home/lp3/aodvuu096/lnx/kaodv-debug.o
  CC [M]  /home/lp3/aodvuu096/lnx/kaodv-netlink.o
/home/lp3/aodvuu096/lnx/kaodv-netlink.c: In function ‘kaodv_netlink_init’:
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:372:21: warning: passing argument 3 of ‘netlink_kernel_create’ from incompatible pointer type [enabled by default]
include/linux/netlink.h:48:1: note: expected ‘struct netlink_kernel_cfg *’ but argument is of type ‘void (*)(struct sk_buff *)’
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:372:21: error: too many arguments to function ‘netlink_kernel_create’
include/linux/netlink.h:48:1: note: declared here
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:374:13: error: invalid storage class for function ‘kaodv_netlink_rcv_sk’
/home/lp3/aodvuu096/lnx/kaodv-netlink.c: In function ‘kaodv_netlink_rcv_sk’:
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:378:14: error: ‘recv_cmd’ undeclared (first use in this function)
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:378:14: note: each undeclared identifier is reported only once for each function it appears in
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:382:1: error: incompatible type for argument 3 of ‘netlink_kernel_create’
include/linux/netlink.h:48:1: note: expected ‘struct netlink_kernel_cfg *’ but argument is of type ‘struct netlink_kernel_cfg’
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:386:3: warning: ‘return’ with a value, in function returning void [enabled by default]
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:389:1: warning: ‘return’ with a value, in function returning void [enabled by default]
/home/lp3/aodvuu096/lnx/kaodv-netlink.c: In function ‘kaodv_netlink_init’:
/home/lp3/aodvuu096/lnx/kaodv-netlink.c:374:1: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
make[3]: *** [/home/lp3/aodvuu096/lnx/kaodv-netlink.o] Error 1
make[2]: *** [_module_/home/lp3/aodvuu096/lnx] Error 2
make[2]: Leaving directory `/usr/src/linux-headers-3.8.0-31-generic'
make[1]: *** [kaodv.ko] Error 2
make[1]: Leaving directory `/home/lp3/aodvuu096/lnx'
make: *** [kaodv] Error 2
lp3@lp3-Latitude-E5420:~/aodvuu096$ 
4

1 回答 1

0

You have the answer right there, except it is commented out:

/*  
struct netlink_kernel_cfg cfg = {
    .input = kaodv_netlink_init,
};

kaodvnl = netlink_kernel_create(&init_net, AODVGRP_MAX, &cfg);
*/
kaodvnl = netlink_kernel_create(&init_net,AODVGRP_MAX,
                    kaodv_netlink_rcv_skb, NULL);

Fix the netlink_kernel_create calls to use the new format used in the newer kernels.

于 2013-10-07T05:47:55.623 回答