2012-05-08 24 views
15

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); 
+4

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 . –

+0

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. –

+0

@BenVoigt Thx za poradę. Oto [poprzedni temat] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin

Odpowiedz

13

mi rozwiązać mój problem kilka miesięcy temu. Oto rozwiązanie, którego użyłem.

Standardowy interfejs API do wysyłania pakietów (sock_create, connect, ...) nie może być używany w kilku kontekstach (przerwach). Używanie go w niewłaściwym miejscu prowadzi do KP.

API dla netpoli jest bardziej "niskopoziomowe" i działa w każdym kontekście. Jednakże, istnieje kilka warunków:

  • urządzenia Ethernet
  • IP
  • tylko UDP (nie TCP)
  • Różne komputery do wysyłania i odbierania pakietów (nie można wysłać do siebie.)

Upewnij się, że je szanujesz, ponieważ w razie problemu nie dostaniesz żadnego komunikatu o błędzie. Będzie po cichu zawieść :) Oto trochę kodu.

Deklaracja

#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; 

Inicjowanie

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; 

Zastosowanie

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

Nadzieję, że może komuś pomóc.

+0

jako podniesiony [tutaj] (http://stackoverflow.com/questions/35880786/why-do-i-get-this-error), wersja jądra 3.9 (kwiecień 2013) wprowadziła przełomową zmianę na 'linux/netpoll.h 'więc ten kod nie jest już kompilowany –

0

Panika podczas rozruchu może być spowodowana przez próbę użycia czegoś, co nie zostało jeszcze zainicjalizowane. Patrzenie na ślad stosu może pomóc w ustaleniu, co się właściwie wydarzyło.

Co do twojego problemu, myślę, że próbujesz zrobić prostą rzecz, dlaczego więc nie trzymać się prostych narzędzi? ;) printks może być złym pomysłem, ale dać trace_printk iść. trace_printk jest częścią infrastruktury Ftrace.

Sekcja Korzystanie ślad _printk() w następującym artykule powinny uczyć wszystko, co musisz wiedzieć: http://lwn.net/Articles/365835/

Powiązane problemy