znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
阅读:2372回复:4

netlink 2.6.25 及以后的示例,转自网上

楼主#
更多 发布于:2009-03-02 17:04
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <net/netlink.h>

#define NETLINK_TEST 21

struct sock *nl_sk = NULL;
EXPORT_SYMBOL_GPL(nl_sk);

void nl_data_ready (struct sk_buff *__skb)
{
  struct sk_buff *skb;
  struct nlmsghdr *nlh;
  u32 pid;
  int rc;
  int len = NLMSG_SPACE(1200);
  char str[100];

  printk("net_link: data is ready to read.\n");
  skb = skb_get(__skb);

  if (skb->len >= NLMSG_SPACE(0)) {
    nlh = nlmsg_hdr(skb);
    printk("net_link: recv %s.\n", (char *)NLMSG_DATA(nlh));
    memcpy(str,NLMSG_DATA(nlh), sizeof(str));
    pid = nlh->nlmsg_pid; /*pid of sending process */
    printk("net_link: pid is %d\n", pid);
    kfree_skb(skb);

    skb = alloc_skb(len, GFP_ATOMIC);
    if (!skb){
      printk(KERN_ERR "net_link: allocate failed.\n");
      return;
    }
    nlh = nlmsg_put(skb,0,0,0,1200,0);
    NETLINK_CB(skb).pid = 0;      /* from kernel */

    memcpy(NLMSG_DATA(nlh), str, sizeof(str));
    printk("net_link: going to send.\n");
    rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
    if (rc < 0) {
      printk(KERN_ERR "net_link: can not unicast skb (%d)\n", rc);
    }
    printk("net_link: send is ok.\n");
  }
  return;
}

static int test_netlink(void) {
  nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE);

  if (!nl_sk) {
    printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
    return -EIO;
  }
  printk("net_link: create socket ok.\n");
  return 0;
}

int init_module()
{
  test_netlink();
  return 0;
}
void cleanup_module( )
{
  if (nl_sk != NULL){
    sock_release(nl_sk->sk_socket);
  }
  printk("net_link: remove ok.\n");
}

可惜的是没有发送给用户层数据的代码

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kidoln");
附件名称/大小 下载次数 最后更新
example.rar (2KB)  17 2009-03-02 17:04
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
沙发#
发布于:2009-03-02 17:05
linux kernel 在2.6.25及以后, netlink_kernel_create 改了很多,导致以前的代码无法编译.
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
板凳#
发布于:2009-03-05 22:59
很好. 支持
走走看看开源好 Solaris vs Linux
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
地板#
发布于:2009-04-09 16:09
再支持一下,今天也用到了。不过znsoft提供的代码有点乱,我先给出一个内核框架版的,然后再给一个应用层的框架版。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <net/netlink.h>

/*--------------------------------------------*/
#define NETLINK_SEC_AUTH 25
/*--------------------------------------------*/
static DEFINE_MUTEX(auth_kernel_mutex);
/*--------------------------------------------*/

/* 用户自己的数据逻辑处理 */
static int auth_kernel_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
    int ret = -1;

    /* user data type */
    u16 msg_type = nlh->nlmsg_type;
    u32 pid  = NETLINK_CREDS(skb)->pid;
    u32 uid  = NETLINK_CREDS(skb)->uid;
    u32 sessionid = NETLINK_CB(skb).sessionid;
    uid_t loginuid = NETLINK_CB(skb).loginuid;
    u32 sid  = NETLINK_CB(skb).sid;
    u32 seq  = nlh->nlmsg_seq;
    void *data = NLMSG_DATA(nlh);

    if (nlh->nlmsg_len < sizeof(struct your_self data))
    {
            return -EINVAL;
    }
    struct your_self status_get   = (struct your_self *)data;    

    ....

    return ret;
}

/* 获取netlink 中的msg数据, 并验证 */
static void auth_kernel_recv_skb (struct sk_buff *skb)
{
    if ((security_netlink_recv(skb, CAP_NET_ADMIN) == 0) /* 如果应用空间进程不需要权限,则可去掉该句 */
         && (skb->len >= NLMSG_SPACE(0)))
    {
        int err = 0;
        int rlen = 0;
        struct nlmsghdr *nlh = nlmsg_hdr(skb);

        if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
        {
            return;
        }

        rlen = NLMSG_ALIGN(nlh->nlmsg_len);
        if (rlen > skb->len)
        {
            rlen = skb->len;
        }

        if ((err = auth_kernel_recv_msg(skb, nlh)))
        {
            netlink_ack(skb, nlh, err);
        }
        else if (nlh->nlmsg_flags & NLM_F_ACK)
        {
            netlink_ack(skb, nlh, err);
        }

        skb_pull(skb, rlen);
    }
}

/* socket 内核接收来自应用空间的数据 */
static void auth_kernel_data_ready (struct sk_buff *skb)
{
    mutex_lock(&auth_kernel_mutex); / * 如果是多线程,并有全局变量,要加锁保护,防止重入
                                   注意:这里用的是mutex,而不是spin_lock,原因不言自明 */

    auth_kernel_recv_skb(skb);
    
    mutex_unlock(&auth_kernel_mutex);
}

/* 初始化或者销毁模块 */
static struct sock *g_nl_sk = NULL;
static int __init auth_kernel_init(void)
{
    int ret = -1;
    
    g_nl_sk = netlink_kernel_create(&init_net, NETLINK_SEC_AUTH, 0, auth_kernel_data_ready, NULL, THIS_MODULE);
    
    if(g_nl_sk)
    {
        ret = 0;
    }

    return ret;
}

static void __exit auth_kernel_fini(void)
{
    if(g_nl_sk != NULL)
    {
        netlink_kernel_release(g_nl_sk);
        g_nl_sk = NULL;
    }
}

/* 声明 */
module_init(auth_kernel_init)
module_exit(auth_kernel_fini)

MODULE_LICENSE("GPL");
MODULE_AUTHOR("jonathan <sprbeyond@sohu.com>");
走走看看开源好 Solaris vs Linux
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
地下室#
发布于:2009-04-10 19:45
感谢你:) 我正好也用到这儿.hehe
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
游客

返回顶部