Anche se un argomento simile esiste già, ho notato che risale a due anni, quindi credo che sia più opportuno aprire uno nuovo ...L'invio di pacchetti UDP dal Linux Kernel
sto cercando di capire come inviare pacchetti UDP dal kernel di Linux (3.3.4), per monitorare il comportamento del generatore di numeri casuali (/drivers/char/random.c). Finora, sono riuscito a monitorare alcune cose grazie alle funzioni sock_create e sock_sendmsg. È possibile trovare il tipico pezzo di codice che uso alla fine di questo messaggio. (Si potrebbe anche voler scaricare il file random.c completo modificato here.)
Inserendo questo codice all'interno delle appropriate funzioni random.c, sono in grado di inviare un pacchetto UDP per ogni accesso a/dev/random e/dev/urandom e ogni evento tastiera/mouse usato dal generatore di numeri casuali per raccogliere entropia. Tuttavia non funziona affatto quando provo a monitorare gli eventi del disco: genera un panico del kernel durante l'avvio.
Di conseguenza, ecco la mia domanda principale: Hai idea del motivo per cui il mio codice causa così tanti problemi quando inserito nella funzione eventi del disco? (add_disk_randomness)
In alternativa, ho letto sull'API netpoll, che dovrebbe gestire questo tipo di problemi UDP-in-kernel. Sfortunatamente non ho trovato alcuna documentazione rilevante a parte una presentazione Red Hat abbastanza interessante ma datata del 2005. Pensi che dovrei usare questa API? Se sì, hai qualche esempio?
Qualsiasi aiuto sarebbe apprezzato. Grazie in anticipo.
PS: E 'la mia prima domanda qui, quindi per favore non esitate a dirmi se sto facendo qualcosa di sbagliato, lo terrò a mente per il 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, è preferibile non fare nulla nel kernel che si possa fare in userspace - sarebbe probabilmente meglio esporre le informazioni nello spazio utente tramite meccanismi di registrazione o sysfs e poi avere un demone che lo invia al sistema remoto . –
Quando esiste già un argomento simile, collegarlo ad esso. Hai svolto un lavoro ragionevole spiegando perché ritieni che la domanda esistente non sia abbastanza valida (avrei potuto dire qualcosa sulla versione del kernel più recente, ecc.). Ma avere la domanda esistente facilmente disponibile rende possibile che le risposte si concentrino su ciò che è cambiato da allora. –
@BenVoigt Thx per il vostro consiglio. Ecco [argomento precedente] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin