当前位置: 首页 > 面试题库 >

从Linux内核发送UDP数据包

养鸿运
2023-03-14
问题内容

即使已经存在一个类似的主题,我也注意到它可以追溯到两年前,因此我认为打开一个新主题更为合适。

我试图弄清楚如何从Linux内核(3.3.4)发送UDP数据包,以便监视随机数生成器(/drivers/char/random.c)的行为。到目前为止,由于sock_create和sock_sendmsg函数,我已经设法监视了一些事情。您可以在此消息的末尾找到我使用的典型代码。(您可能还希望在此处下载完整的修改后的random.c文件。)

通过将此代码插入适当的random.c函数中,我能够为每次访问/ dev / random和/ dev /
urandom以及随机数生成器用来收集熵的每个键盘/鼠标事件发送一个UDP数据包。但是,当我尝试监视磁盘事件时,它根本不起作用:它在引导过程中产生内核崩溃。

因此,这是我的主要问题: 您是否知道为什么我的代码在插入磁盘事件函数中时会引起如此多的麻烦? (add_disk_randomness)

另外,我已经阅读了netpoll API,该API应该可以处理此类UDP-in-kernel问题。不幸的是,除了2005年的一个有趣但过时的Red
Hat演示文稿之外,我没有找到任何相关文档。 您认为我应该使用此API吗? 如果是,您有什么例子吗?

任何帮助,将不胜感激。提前致谢。

PS:这是我的第一个问题,所以请不要犹豫告诉我我做错了什么,以后会记住的:)

#include <linux/net.h>
#include <linux/in.h>
#include <linux/netpoll.h>
#define MESSAGE_SIZE 1024
#define INADDR_SEND ((unsigned long int)0x0a00020f) //10.0.2.15
static bool sock_init;
static struct socket *sock;
static struct sockaddr_in sin;
static struct msghdr msg;
static struct iovec iov;

[...]

int error, len;
mm_segment_t old_fs;
char message[MESSAGE_SIZE];

if (sock_init == false)
{
  /* Creating socket */
  error = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
  if (error<0)
    printk(KERN_DEBUG "Can't create socket. Error %d\n",error);

  /* Connecting the socket */
  sin.sin_family = AF_INET;
  sin.sin_port = htons(1764);
  sin.sin_addr.s_addr = htonl(INADDR_SEND);
  error = sock->ops->connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr), 0);
  if (error<0)
    printk(KERN_DEBUG "Can't connect socket. Error %d\n",error);

  /* Preparing message header */
  msg.msg_flags = 0;
  msg.msg_name = &sin;
  msg.msg_namelen  = sizeof(struct sockaddr_in);
  msg.msg_control = NULL;
  msg.msg_controllen = 0;
  msg.msg_iov = &iov;
  msg.msg_control = NULL;
  sock_init = true;
}

/* Sending a message */
sprintf(message,"EXTRACT / Time: %llu / InputPool: %4d / BlockingPool: %4d / NonblockingPool: %4d / Request: %4d\n",
  get_cycles(),
  input_pool.entropy_count,
  blocking_pool.entropy_count,
  nonblocking_pool.entropy_count,
  nbytes*8);
iov.iov_base = message;
len = strlen(message);
iov.iov_len = len;
msg.msg_iovlen = len;
old_fs = get_fs();
set_fs(KERNEL_DS);
error = sock_sendmsg(sock,&msg,len);
set_fs(old_fs);

问题答案:

几个月前我解决了我的问题。这是我使用的解决方案

标准的包发送API(sock_create,connect等)不能在少数情况下使用(中断)。在错误的地方使用它会导致KP。

netpoll API更“底层”,并且可以在每种情况下使用。但是,有几个条件:

  • 以太网设备
  • IP网络
  • 仅UDP(无TCP)
  • 用于发送和接收数据包的不同计算机(您不能自己发送。)

确保尊重他们,因为如果出现问题,您将不会收到任何错误消息。它只会默默地失败:)这是一些代码。

宣言

#include <linux/netpoll.h>
#define MESSAGE_SIZE 1024
#define INADDR_LOCAL ((unsigned long int)0xc0a80a54) //192.168.10.84
#define INADDR_SEND ((unsigned long int)0xc0a80a55) //192.168.10.85
static struct netpoll* np = NULL;
static struct netpoll np_t;

初始化

np_t.name = "LRNG";
strlcpy(np_t.dev_name, "eth0", IFNAMSIZ);
np_t.local_ip = htonl(INADDR_LOCAL);
np_t.remote_ip = htonl(INADDR_SEND);
np_t.local_port = 6665;
np_t.remote_port = 6666;
memset(np_t.remote_mac, 0xff, ETH_ALEN);
netpoll_print_options(&np_t);
netpoll_setup(&np_t);
np = &np_t;

采用

char message[MESSAGE_SIZE];
sprintf(message,"%d\n",42);
int len = strlen(message);
netpoll_send_udp(np,message,len);

希望它可以帮助某人。



 类似资料:
  • 简介 如你所知,我从去年开始写了一系列关于 x86_64 架构汇编语言程序设计的博文。除了大学期间写过一些 Hello World 这样无实用价值的程序之外,我从来没写过哪怕一行的底层代码。那些程序也是很久以前的事情了,就像我刚才说的,我几乎完全没有写过底层代码。直到不久前,我才开始对这些事情感兴趣,因为我意识到我虽然可以写出程序,但是我却不知道我的程序是怎样被组织运行的。 在写了一些汇编代码之后

  • 简介 如你所知,我从去年开始写了一系列关于 x86_64 架构汇编语言程序设计的博文。除了大学期间写过一些 Hello World 这样无实用价值的程序之外,我从来没写过哪怕一行的底层代码。那些程序也是很久以前的事情了,就像我刚才说的,我几乎完全没有写过底层代码。直到不久前,我才开始对这些事情感兴趣,因为我意识到我虽然可以写出程序,但是我却不知道我的程序是怎样被组织运行的。 在写了一些汇编代码之后

  • 我们有一个场景,(UDP客户端程序)向(UP服务器)发送UDP数据包 TCP在数据通信开始之前和结束之后执行握手。UDP没有。 那么,运行在上的应用程序失败的原因是否是上的服务器程序没有准备好(关闭)接收UDP数据包?

  • 基数树 正如你所知道的 Linux 内核通过许多不同库以及函数提供各种数据结构以及算法实现。 这个部分我们将介绍其中一个数据结构 Radix tree。Linux 内核中有两个文件与 radix tree 的实现和API相关: include/linux/radix-tree.h lib/radix-tree.c 首先说明一下什么是 radix tree 。Radix tree 是一种 压缩 tr

  • Linux内核对很多数据结构提供不同的实现方法,比如,双向链表,B+树,具有优先级的堆等等。 这部分考虑这些数据结构和算法。 双向链表 基数树 位数组