Incluso si un tema similar ya existe, he notado que se remonta dos años, por lo que supongo que es más adecuado para abrir uno nuevo ...envío de paquetes UDP desde el núcleo de Linux
Estoy intentando averiguar cómo enviar paquetes UDP desde el Kernel de Linux (3.3.4), para monitorear el comportamiento del generador de números aleatorios (/drivers/char/random.c). Hasta ahora, he logrado controlar algunas cosas debido a las funciones sock_create y sock_sendmsg. Puede encontrar la pieza de código que uso al final de este mensaje. (También es posible que desee descargar el archivo random.c completo modificado here.)
Al insertar este código dentro de las funciones random.c apropiadas, puedo enviar un paquete UDP para cada acceso a/dev/random y/dev/urandom, y cada evento de teclado/mouse utilizado por el generador de números aleatorios para cosechar entropía. Sin embargo, no funciona en absoluto cuando intento monitorear los eventos del disco: genera un pánico en el kernel durante el arranque.
En consecuencia, aquí está mi pregunta principal: ¿Tiene alguna idea de por qué mi código causa tantos problemas cuando se inserta en la función de eventos del disco? (add_disk_randomness)
O bien, he leído sobre netpoll API, que se supone que maneja este tipo de problemas UDP-en-kernel. Lamentablemente, no he encontrado ninguna documentación relevante aparte de una presentación de Red Hat bastante interesante pero obsoleta desde 2005. ¿Crees que debería usar esta API? En caso afirmativo, ¿tiene algún ejemplo?
Cualquier ayuda sería apreciada. Gracias de antemano.
PD: Es mi primera pregunta aquí, así que por favor no dude en decirme si yo estoy haciendo algo mal, lo tendré en cuenta para el futuro :)
#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);
Generalmente, es preferible que no haga nada en el kernel que podría hacer en el espacio de usuario; probablemente sería mejor exponer la información al espacio de usuario a través de mecanismos de registro o sysfs y luego enviar un daemon al sistema remoto . –
Cuando ya existe un tema similar, vincúlelo. Hizo un trabajo razonable al explicar por qué cree que la pregunta existente no es lo suficientemente buena (es posible que haya dicho algo sobre la versión del núcleo más nueva, etc.). Pero tener la pregunta existente fácilmente disponible hace posible que las respuestas se centren en lo que ha cambiado desde entonces. –
@BenVoigt Thx por su consejo. Aquí está el [tema anterior] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin