【问题标题】:An error while attempting to write a netlink socket program in C尝试在 C 中编写 netlink 套接字程序时出错
【发布时间】:2013-11-04 07:47:24
【问题描述】:

第一件事,你可以在my previous post找到我的情况的详细信息

在过去的一天中,我一直在尝试第一次尝试 netlink 套接字程序。

我并没有试图让我听起来好像我没有从我在互联网上找到的其他人的示例代码中获得所有这些代码,因为我们都知道我就是这样做的。

但我一直在尝试对代码进行逆向工程(见结尾),经过数小时的调试,我终于让它编译没有错误。但是在尝试运行它之后,我收到消息“Segmentation Fault (Core Dumped)”。

现在我知道这个错误与尝试从无效的内存位置读取有关,但老实说,我不理解拼接在一起的一半代码,所以如果有人能指出我哪里出错了,我将不胜感激它。

如果您能解释一下我在尝试通过一般的 netlink 套接字发送消息时的正确/错误做法,我也将非常感谢您。例如,我会将消息放在哪里?因为我真的不知道我现在用我的代码原样发送什么消息。任何帮助表示赞赏!

#include <sys/socket.h>       /*  socket definitions        */
#include <sys/types.h>        /*  socket types              */
#include <linux/netlink.h>  /* netlink functions */
#include <sys/uio.h>        /* scatter-gather definition for iovec */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


/*  Global constants  */

#define ECHO_PORT          (2002)
#define MAX_LINE           (1000)

int socketHolder; // declare variable to hold Socket

// Set up configuration for destination which holds the socket to be used to communicate with the Kernel
struct sockaddr_nl dest; // declare variable to hold Socket Address
// Set up configuration for the netlink message header
struct nlmsghdr *netlinkHeader; // declare variable to hold message to be sent
// Set up configuration for the scatter-gather function for expediting writing to buffer
struct iovec iov;
// Set up configuration for the message header for simplifying message parameters to be sent
struct msghdr message;

int main()
{

memset(&dest, 0, sizeof(dest)); // set socket Address to all 0
dest.nl_family = AF_NETLINK; // set socket family to AF_NETLINK
dest.nl_pad = 0; // defaults to 0
dest.nl_pid = 0; // set address of netlink socket to 0 because we're going to the kernel
dest.nl_groups = 0; // set to 0 because we're doing unicast

netlinkHeader->nlmsg_pid = 0; // set sender port number to 0 because we're in kernel

iov.iov_base = (caddr_t)netlinkHeader; // set address of buffer
iov.iov_len = netlinkHeader->nlmsg_len; // set length of buffer

message.msg_name = (caddr_t) &dest; // set socket name
message.msg_namelen = sizeof(dest); // set length of name
message.msg_iov = &iov; // I have no idea what this is
message.msg_iovlen = 1; // number of iov blocks
message.msg_control = NULL;  // ignore
message.msg_controllen = 0;  // ignore
message.msg_flags = 0;  //ignore

socketHolder = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); // declare Socket and assign to holder variable

bind(socketHolder, (struct sockaddr *) &dest, sizeof(dest)); // bind the destination settings to socketHolder

int sender = sendmsg(socketHolder, &message, 0); // send the message

}

【问题讨论】:

    标签: c sockets netlink


    【解决方案1】:

    不幸的是,我对netlink 不是很熟悉。但是您的错误(非常)可能在这里:

    netlinkHeader->nlmsg_pid = 0; // set sender port number to 0 because we're in kernel
    

    由于您从未初始化 netlinkHeader,即确保指针指向您可以读写的内存,因此这是未定义的行为。在实践中,它通常会导致分段错误,因为您正在访问一些随机地址并且您的操作系统会阻止您的进程破坏事物。

    完全不知道为什么这是一个指针,您或许应该尝试将其设为struct nlmsghdr 类型的实际实例,因为这听起来好像您想操纵地址。

    此外,注释暗示代码取自内核代码,而您的代码不是内核代码,这可能暗示还有其他问题。

    【讨论】:

    • 谢谢!你的建议解决了我的问题。我将 netlinkHeader 更改为实际实例而不是指针(我将其更改为最初是为了满足编译时遇到的另一个错误)并且只是将 -> 更改为 .在几行和繁荣中,我们重新开始营业(我想哈哈)。并且代码应该与内核对话并将信息传递给内核(比如一个字符串),以便内核可以将其写入系统日志。尽管我仍然不确定该消息的实际来源……我猜这是下一个任务。无论如何,再次感谢!
    【解决方案2】:

    如果您确定导致分段错误的行会有所帮助,但从您显示的代码来看,它似乎是下面的行。

    netlinkHeader->nlmsg_pid = 0;
    

    您尚未初始化 netlinkHeader 指针以指向某个有效的内存位置,因此当您尝试将值 0 写入属性 netlinkHeader-&gt;nlmsg_pid 时,会导致您看到的错误。

    【讨论】:

    • 感谢您指出这一点!对不起,我会指出分段错误在哪里,但我不知道它是在哪里引起的。我将 netlinkHeader 声明更改为 nlmsghdr 的实际实例之一,而不是指针并解决了它。
    猜你喜欢
    • 1970-01-01
    • 2020-09-11
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多