2013-09-30 35 views
0

目前我正在研究一個我們試圖運行無線網絡協議的研究項目,即由uppasala大學開發的aodvuu。協議是在Linux內核版本2.4 x中開發的,現在我們試圖在內核版本3.8上運行它。以下是面臨問題的相應內核代碼(kaodv-netlink.c)。內核代碼中的netlink_kernel_create在編譯內核3.8時不工作x

#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 
[email protected]:~/aodvuu096$ 
+0

根據http://lxr.free-electrons.com/source/include/linux/netlink.h?v=3.8 netlink_kernel_create()需要* 4 *參數。對於不同的內核版本,你已經有了各種宏,爲它們調整內核3.8。 – scai

回答

0

你有答案就在那裏,但它被註釋掉:

/* 
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); 

修復netlink_kernel_create調用使用中所使用的新格式更新的內核。