Nawet jeśli podobny temat już istnieje, zauważyłem, że sięga dwóch lat, więc myślę, że to bardziej właściwe, aby otworzyć nową jednego ...wysyłanie pakietów UDP od jądra Linux
Próbuję dowiedzieć się, jak wysyłać pakiety UDP z jądra Linux (3.3.4), aby monitorować zachowanie generatora liczb losowych (/drivers/char/random.c). Do tej pory udało mi się monitorować kilka rzeczy dzięki funkcjom sock_create i sock_sendmsg. Możesz znaleźć typowy fragment kodu, którego używam na końcu tej wiadomości. (Możesz również pobrać całkowicie zmodyfikowany plik random.c here.)
Wstawiając ten kod do odpowiednich funkcji random.c, jestem w stanie wysłać pakiet UDP dla każdego dostępu do/dev/random i/dev/urandom, oraz każde zdarzenie keyboard/mouse używane przez generator liczb losowych do zbierania entropii. Jednak to nie działa, gdy próbuję monitorować zdarzenia dysku: generuje panikę jądra podczas uruchamiania.
W związku z tym, oto moje główne pytanie: Masz pojęcie, dlaczego mój kod powoduje tak wiele problemów, gdy jest wstawiony w funkcji zdarzeń dysku? (add_disk_randomness)
Alternatywnie, czytałem o API Netpoll, który ma obsługiwać tego rodzaju problemy z UDP-in-jądro. Niestety nie znalazłem żadnej istotnej dokumentacji poza dość interesującą, ale przestarzałą prezentacją Red Hat z 2005 roku. Czy uważasz, że powinienem raczej użyć tego API? Jeśli tak, czy masz jakiś przykład?
Każda pomoc zostanie doceniona. Z góry dzięki.
PS: To jest moje pierwsze pytanie tutaj, więc nie wahaj się powiedzieć, czy robię coś źle, będę o tym pamiętać na przyszłość :)
#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);
Generalnie lepiej jest nie robić nic w jądrze, które można zrobić w przestrzeni użytkownika - lepiej byłoby ujawnić informacje w przestrzeni użytkownika za pomocą mechanizmów logowania lub sysfs, a następnie wysłać demona do systemu zdalnego . –
Gdy podobny temat już istnieje, dodaj do niego link. Wykonałeś rozsądną pracę wyjaśniając, dlaczego uważasz, że istniejące pytanie nie jest wystarczająco dobre (mogłem powiedzieć coś o nowszej wersji jądra itp.). Ale łatwe udostępnienie istniejącego pytania umożliwia odpowiedź na to, co zmieniło się od tego czasu. –
@BenVoigt Thx za poradę. Oto [poprzedni temat] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin