从Linux内核发送UDP数据包

即使已经存在类似的话题,我注意到它可以追溯到两年,所以我觉得打开一个新的更合适。

我试图弄清楚如何从Linux Kernel(3.3.4)发送UDP数据包,以便监视随机数生成器(/drivers/char/random.c)的行为。 到目前为止,由于sock_create和sock_sendmsg函数,我已经设法监视了一些事情。 你可以在这封邮件的结尾find我使用的典型代码。 (你也可以在这里下载完整的修改后的random.c文件。)

通过在合适的random.c函数中插入这个代码,我可以为每个访问发送一个UDP数据包到/ dev / random和/ dev / urandom,而随机数发生器使用的每个键盘/鼠标事件收集熵。 但是,当我尝试监视磁盘事件时,它根本不起作用:它在启动时会产生内核恐慌。

因此,这里是我的主要问题: 你有什么想法,当我的代码插入磁盘事件function时,为什么导致这么多的麻烦? (add_disk_randomness)

另外,我已经读过关于netpoll API,这是应该处理这种UDP-in-kernel问题的。 不幸的是,除了2005年相当有趣但过时的红帽演示,我还没有find任何相关的文档。 你认为我应该使用这个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); 

Solutions Collecting From Web of "从Linux内核发送UDP数据包"

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

标准的数据包发送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); 

希望它可以帮助别人。

引导过程中的恐慌可能是由于您尝试使用尚未初始化的内容引起的。 查看堆栈跟踪可能有助于确定实际发生的情况。

至于你的问题,我想你是想做一件简单的事情,那么为什么不坚持简单的工具? ;)printks确实可能不好,但给trace_printk一个去。 trace_printk是Ftrace基础结构的一部分。

在下面的文章中使用trace _printk()应该教会你需要知道的一切: http : //lwn.net/Articles/365835/