Как написать user_space. c с python для связи kerner linuk - PullRequest
0 голосов
/ 30 мая 2020

Этот код записан в user_space с c langauage (ссылка: https://gist.github.com/arunk-s/c897bb9d75a6c98733d6):

#include <sys/socket.h>
#include <linux/netlink.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define NETLINK_USER 31

#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;

int main()
{
sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0)
return -1;

memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */

bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));

memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */

nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;

strcpy(NLMSG_DATA(nlh), "Hello");

iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

printf("Sending message to kernel\n");
sendmsg(sock_fd,&msg,0);
printf("Waiting for message from kernel\n");

/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf("Received message payload: %s\n", (char *)NLMSG_DATA(nlh));
close(sock_fd);
}

как преобразовать приведенный выше код с python (Этот код не работает для user_space):

import socket
import os
from ctypes import *
from sys import platform, version, version_info

RUNNING_PYTHON3 = version_info[0] == 3
RUNNING_PYPY = ("pypy" in version.lower())
RUNNING_WINDOWS = (platform == 'win32')
RUNNING_LINUX = platform.startswith('linux')
RUNNING_FREEBSD = (platform.startswith('freebsd')
                   or platform.startswith('gnukfreebsd'))
RUNNING_OPENBSD = platform.startswith('openbsd')
RUNNING_MACOSX = (platform == 'darwin')
RUNNING_BSD = RUNNING_FREEBSD or RUNNING_MACOSX or RUNNING_OPENBSD

HAS_PROC = RUNNING_LINUX
HAS_PTRACE = (RUNNING_BSD or RUNNING_LINUX)

if RUNNING_BSD:
    sa_family_t = c_ubyte
else:
    sa_family_t = c_ushort



class sockaddr_nl(Structure):
    _fields_ = (
        ("nl_family", sa_family_t),
        ("nl_pad", c_ushort),
        ("nl_pid", c_uint32),
        ("nl_groups", c_uint32),
    )


class struct_iovec(Structure):
    _fields_ = [
        ("iov_base", c_void_p),
        ("iov_len", c_size_t),
    ]


class struct_msghdr(Structure):
    _fields_ = [
        ("msg_name", c_void_p),
        ("msg_namelen", c_uint32),
        ("msg_iov", POINTER(struct_iovec)),
        ("msg_iovlen", c_size_t),
        ("msg_control", c_void_p),
        ("msg_controllen", c_size_t),
        ("msg_flags", c_int),
    ]


class struct_cmsghdr(Structure):
    _fields_ = [
        ("cmsg_len", c_size_t),
        ("cmsg_level", c_int),
        ("cmsg_type", c_int),
    ]


class sock_extended_err(Structure):
    """
    {
        uint32_t ee_errno;   /* error number */
        uint8_t  ee_origin;  /* where the error originated */
        uint8_t  ee_type;    /* type */
        uint8_t  ee_code;    /* code */
        uint8_t  ee_pad;     /* padding */
        uint32_t ee_info;    /* additional information */
        uint32_t ee_data;    /* other data */
        /* More data may follow */
    };
    """
    _fields_ = [
        ("ee_errno", c_uint32),
        ("ee_origin", c_uint8),
        ("ee_type", c_uint8),
        ("ee_code", c_uint8),
        ("ee_pad", c_uint8),
        ("ee_info", c_uint32),
        ("ee_data", c_uint32),
    ]

    def getdict(self):
        return dict((field, getattr(self, field)) for field, _ in self._fields_)


libc = CDLL("libc.so.6")
recvmsg = libc.recvmsg
recvmsg.argtypes = [c_int, POINTER(struct_msghdr), c_int]
recvmsg.retype = c_int

sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_USERSOCK)
sock.bind((os.getpid(), 0))

dest_addr = sockaddr_nl()
dest_addr.nl_family = socket.AF_NETLINK
dest_addr.nl_pid = 0
dest_addr.nl_groups = 0

while True:
    try:

        bufsize = 20
        buf = create_string_buffer(bufsize)
        ctrl_bufsize = sizeof(struct_cmsghdr) + sizeof(sock_extended_err) + sizeof(c_size_t)
        ctrl_buf = create_string_buffer(ctrl_bufsize)

        iov = struct_iovec()
        iov.iov_base = cast(buf, c_void_p)
        iov.iov_len = bufsize

        msg = struct_msghdr()
        msg.msg_name = dest_addr
        msg.msg_namelen = 0
        msg.msg_iov = pointer(iov)
        msg.msg_iovlen = 1
        msg.msg_control = cast(ctrl_buf, c_void_p)
        msg.msg_controllen = ctrl_bufsize
        msg.msg_flags = 0

        sock.sendmsg(msg)

        print(sock.recvfrom(1024))
    except Exception as e:
        print('Exception', e)

Как преобразовать код c в python? Мне нужно связаться с netlinkKernel. c () (user_kernel: https://gist.github.com/arunk-s/c897bb9d75a6c98733d6)

...