c - 如果应用程序在 lxc 容器中运行,则向 Netlink 发送消息失败并显示 ECONNREFUSED

标签 c linux linux-kernel lxc netlink

在 HOST 上运行的用户空间应用程序没有任何问题,但同一应用程序无法在 LXC 容器中运行,出现错误 ECONNREFUSED;
用户空间应用程序在向 netlink 发送消息期间失败并显示 ECONNREFUSED

使用具有命名空间支持的 Linux 内核 3.4 和具有 1.0.2 版本的 LXC。

如下注册myApp.ko内核模块

    netlink_kernel_create(&init_net, ..... );

并且用户空间应用程序在向 netlink 套接字发送消息期间失败;

    sock = socket(PF_NETLINK, SOCK_RAW, ....);

用户空间应用程序正在运行内部 C1 容器,它使用 getpid();对于 nlMsg->nlmsg->pid

    nlMsg->nlmsg_pid = getpid();

接收消息时的 Netlink 注册处理程序甚至没有在内核中调用,但在容器内运行的用户空间应用程序在 sendmsg() 期间失败并显示“连接被拒绝”;

要在容器中运行相同的用户空间应用程序,我需要解决什么问题吗?我什至尝试将常数赋予 pid 变量而不是使用 getpid();但随后也遇到了同样的问题;

  socket(PF_NETLINK, SOCK_RAW, 31)        = 4

  bind(4, {sa_family=AF_NETLINK, pid=812, groups=00000000}, 12) = 0

  sendmsg(4, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\20\0\0\0\2\0\0\0\0\0\0\0,\3\0\0", 16}], msg_controllen=0, msg_flags=0}, 0) = -1 **ECONNREFUSED** (Connection refused)

最佳答案

终于,我找到了解决方案;我们现在需要添加额外的代码来支持 Netlink 感知命名空间。

示例(只是模板)

 struct my_nlns_sock {
    struct list_head list;
    struct sock *sk;
 }
 static LIST_HEAD(my_nlns_sock_list);
 static DEFINE_SPINLOCK(my_nlns_sock_lock); 

 static int __net_init my_nlns_start(struct net *net)
 {
    struct my_nlns_sock *nlsk;

    nlsk = kzalloc(sizeof(*nlsk), GFP_KERNEL);
    if (!nlsk)
        return -ENOMEM;

    nlsk->sk = netlink_kernel_create(net, ...);
    spin_lock_bh(&my_nlns_sock_lock);
    list_add_tail(&nlsk->list, &my_nlns_sock_list);
    spin_unlock_bh(&my_nlns_sock_lock);
 }

 static void my_nlns_exit(struct net *net)
 {
     struct my_nlns_sock *nlsk;

     spin_lock_bh(&my_nlns_sock_lock);
     list_for_each_entry(nlsk, &my_nlns_sock_list, list) {
          if (sock_net(nlsk->sk) == net)
               goto found;
     }
     spin_unlock_bh(&rfal_nl_sock_lock);
     return;
 found:
      list_del(&nlsk->list);
      spin_unlock_bh(&my_nlns_sock_lock);
      netlink_kernel_release(nlsk->sk);
      kfree(nlsk);
 }
 int my_nlns_recv_data(struct sk_buff skbFrom)
 {
     struct my_nlns_sock *nlsk;

     spin_lock_bh(&my_nlns_sock_lock);
     list_for_each_entry(nlsk, &my_nlns_sock_list, list) {
     if (sock_net(nlsk->sk) == net)
           goto found;
     }
     spin_unlock_bh(&my_nlns_sock_lock);
     return;
  found:
        /* Do with data */
  }

关于c - 如果应用程序在 lxc 容器中运行,则向 Netlink 发送消息失败并显示 ECONNREFUSED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35987286/

相关文章:

c - 输出不正确: determine if three digits are unique and add up to a given sum

linux - 在单个系统调用中接收多个数据报

linux-kernel - 如何在 Linux 中启用 cgroups

c - 是否只有在出现页面错误时才会出现虚拟内存区域结构?

复制 glibc 库

c - C 中的字符串操作?

c - c中fputs和puts的区别

linux - 如何在Linux中搜索单词中的某些字母?

c - 使用 TSC(时间戳计数器)计算时间