首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在使用netlink套接字与python用户通信时不能从内核模块获得消息响应?

为什么在使用netlink套接字与python用户通信时不能从内核模块获得消息响应?
EN

Stack Overflow用户
提问于 2021-07-14 03:15:28
回答 2查看 497关注 0票数 0

我使用netlink套接字与linux内核通信用户python代码,我可以从用户正确地发送消息到内核,但不能从内核获得响应。它显示:“向用户发送bak时出错。”在我的内核代码中

我尝试了所有的方法来获得响应消息:recvrecvfrom recvmsg,然后我的目的是解压它以获得具有以下格式的响应的有效负载: response_message = header +有效负载,但是用户总是无法获得响应。我在执行用户python代码时得到了这样的信息:

代码语言:javascript
运行
复制
pid of sock : 1
seq number of sock : 0
pid of the message send to kernel:  1
seq number of the message send to kernel :  0
return of send  21
waiting for kernel ..

在内核端,当检查syslog文件时,我发现如下:

代码语言:javascript
运行
复制
Jul 14 03:57:32 Bob kernel: [12381.663131] Kernel received :hello  id:XXXX!
Jul 14 03:57:32 Bob kernel: [12381.663132] python pid :1 XXXX
Jul 14 03:57:32 Bob kernel: [12381.663133] seq newsock : 0 id:XXXX!
Jul 14 03:57:32 Bob kernel: [12381.663134] Error while sending back to user  id:XXXX!

我想这个问题可能是由发送方和接收方的消息之间的seq号无效引起的,所以我尝试添加标志(NLM_F_REQUEST)并使用其他消息类型(MSG_SETCFG = 11,MSG_GETCFG =12),但没有工作。

熟悉netlink套接字的人能帮我找出谁来解决这个问题吗?

在这里,我的用户python代码:

代码语言:javascript
运行
复制
import os
import socket
import struct
import ctypes


# types
NLMSG_NOOP = 1
NLMSG_ERROR = 2
NLMSG_DONE = 3
NLMSG_OVERRUN = 4
MSG_SETCFG = 11
MSG_GETCFG = 12
NLMSG_MIN_TYPE = 0x10

# flags
NLM_F_REQUEST = 1
NLM_F_MULTI = 2
NLM_F_ACK = 4
NLM_F_ECHO = 8



class Message:
    def __init__(self, msg_type, flags=0, seq=-1, payload=None):
        self.type = msg_type
        self.flags = flags
        self.seq = seq
        self.pid = 1
        payload = payload or []
        if isinstance(payload, list):
            contents = []
            for attr in payload:
                contents.append(attr._dump())
            self.payload = b''.join(contents)
        else:
            self.payload = payload

    def send(self, conn):
        if self.seq == -1:
            self.seq = conn.seq()

        self.pid = conn.pid
        length = len(self.payload)

        hdr = struct.pack("IHHII", length + 4 * 4, self.type,
                          self.flags, self.seq, self.pid)
        conn.send(hdr + bytes(self.payload, 'utf-8'))

 
class Connection(object):
    """
    Object representing Netlink socket connection to the kernel.
    """
    def __init__(self, nlservice=31, groups=0):
        # nlservice = Netlink IP service
        self.fd = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, nlservice)
        self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
        self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
        self.fd.bind((0, groups)) # pid=0 lets kernel assign socket PID
        self.pid, self.groups = self.fd.getsockname()
        self.pid = 1
        self._seq = 0
        
    def send(self, msg):
        if isinstance(msg, Message):
            if msg.seq == -1: 
                msg.seq = self.seq()
            #msg.seq = 1
            msg.pid = self.pid
            length = len(msg.payload)
            hdr = struct.pack("IHHII", length + 4 * 4, msg.type,
                          msg.flags, msg.seq, msg.pid) 
            msg = hdr + msg.payload.encode('utf-8')
            return self.fd.send(msg)
     
    def recve(self):
        #data, (nlpid, nlgrps) =  self.fd.recvfrom(16384)
        data = self.fd.recv(16384)
        msglen, msg_type, flags, seq, pid = struct.unpack("IHHII", data[:16])
        msg = Message(msg_type, flags, seq, data[16:])
        msg.pid = pid
        if msg_type == NLMSG_DONE:
           print("payload :", msg.payload)
           print("msg.pid :", msg.pid)
           print("msg.seq :", msg.seq)
        if msg.type == NLMSG_ERROR:
            errno = -struct.unpack("i", msg.payload[:4])[0]
            if errno != 0:
                err = OSError("Netlink error: %s (%d)" % (
                                                    os.strerror(errno), errno))
                err.errno = errno
                print("err :",err)
                raise err
        
        #return msg.payload 
         return msg 
        
    def seq(self):
        self._seq += 1
        return self._seq


sock = Connection()

var = 'hello'
msg1 = Message(3,0,-1,var) 
print("pid of sock :", sock.pid)
print ("seq number of sock :",sock._seq)

#res1 = msg1.send(sock)
res1 = sock.send(msg1)
print("pid of the message send to kernel: ", msg1.pid)
print("seq number of the message send to kernel : ", msg1.seq)

print("return of send ", res1)

while 1:
   print("waiting for kernel ..")
   #msgreply = sock.fd.recvmsg(16384)
   res2 = sock.recve()
   print("return of recive ", res2)

下面是我的内核代码:

代码语言:javascript
运行
复制
#include <linux/module.h>
#include <net/mptcp.h>


/********Test deb***********/

#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/init.h>  
#include <net/sock.h>  
#include <linux/socket.h>  
#include <linux/net.h>  
#include <asm/types.h>  
#include <linux/netlink.h>  
#include <linux/netlink.h>  
#include <linux/skbuff.h> 
#include <linux/inetdevice.h>
#include <linux/uio.h>
/****** other lib for other test github ******/
#include <linux/gfp.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
#include <linux/time.h>
#include <net/net_namespace.h>


#define NETLINK_USER 31

#define MSG_SETCFG      0x11

#define MSG_GETCFG      0x12

//#define NETLINK_USERROCK 31

struct sock *nl_sk = NULL;


static void hello_nl_recv_msg(struct sk_buff *skb) {

struct nlmsghdr *nlh;
int pid, seq;
struct sk_buff *skb_out;
int msg_size;
char *msg="Helloo";
char *msgg;
int res;
char *recive;

//printk(KERN_DEBUG "KERNEL MODE id:XXXX!\n");
printk(KERN_INFO "Entering: %s  id:XXXX!\n", __FUNCTION__);
msg_size = strlen(msg);

////recive ////

nlh=(struct nlmsghdr*)skb->data;
//nlh = nlmsg_hdr(skb);
msgg=(char *)NLMSG_DATA(nlh);

printk(KERN_INFO "Kernel received :%s  id:XXXX!\n",msgg);

pid = nlh->nlmsg_pid; //pid of sending process /
//pid = 1; //just set it to 1 like we did in python
printk(KERN_INFO "python pid :%d XXXX", pid);

////////end recive /


///////sending message /

skb_out = nlmsg_new(msg_size,0);

if(!skb_out) {
    printk(KERN_ERR "Failed to allocate new skb  id:XXXX!\n");
    return;
}

//nlh = nlmsg_put(skb, 0, 1, NLMSG_DONE, msg_size + 1, 0);
nlh=nlmsg_put(skb_out,0,0,NLMSG_DONE,msg_size, 0);

NETLINK_CB(skb_out).dst_group = 0; //not in mcast group /
strncpy(nlmsg_data(nlh),msg,msg_size);

seq = nlh->nlmsg_seq;
printk(KERN_INFO "seq newsock : %d id:XXXX!\n", seq);

if(!nlmsg_data(nlh)) {
    printk(KERN_ERR "Failed to copy the message skbout id:XXXX!\n");
    return;
}
   
//printk(KERN_INFO "copied message :" , nlmsg_data(nlh));
//changed pid to 0
res=nlmsg_unicast(nl_sk,skb_out, pid);

if(res<0)
    printk(KERN_INFO "Error while sending back to user  id:XXXX!\n");

/////end send /

}


static int __init hello_init(void) {

printk("Entering: %s id:XXXX!\n",__FUNCTION__);
//This is for 3.6 kernels and above.
struct netlink_kernel_cfg cfg = {
    .input = hello_nl_recv_msg,
};

nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
//nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg,NULL,THIS_MODULE);
if(!nl_sk)
{
    printk(KERN_ALERT "Error creating socket.  id:XXXX!\n");
    return -10;

}

return 0;
}

static void __exit hello_exit(void) {

printk(KERN_INFO "exiting hello module  id:XXXX!\n");
netlink_kernel_release(nl_sk);
}

module_init(hello_init); module_exit(hello_exit);

MODULE_LICENSE("GPL");
EN

回答 2

Stack Overflow用户

发布于 2021-07-14 05:23:51

内核模块中需要注意的两件事

  1. 行的目的是什么"if(!nlmsg_data(nlh))“,因为我们已经关联了有效载荷
  2. (什么是nlmsg_unicast的返回值),因为它会让我们知道为什么返回错误

票数 0
EN

Stack Overflow用户

发布于 2021-12-09 00:07:51

我使用Netlink并在将self.pid = 1更改为self.pid = os.getpid()之后,使用自己的内核模块尝试了python代码。

我能够从内核模块得到响应。当设置为1时,内核模块给出错误-111的问题也是一样的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68371581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档