2012-05-08 2 views
15

Даже если подобная тема уже существует, я заметил, что она восходит два года, таким образом, я предполагаю, что это более целесообразно, чтобы открыть свежую один ...Отправка UDP пакетов из ядра Linux

Пытаюсь выяснить, как отправлять UDP-пакеты из ядра Linux (3.3.4), чтобы отслеживать поведение генератора случайных чисел (/drivers/char/random.c). До сих пор мне удалось контролировать несколько вещей благодаря функциям sock_create и sock_sendmsg. Вы можете найти типичный фрагмент кода, который я использую в конце этого сообщения. (Вы также можете загрузить полный модифицированный файл random.c here.)

Вставив этот код в соответствующие функции random.c, я могу отправить UDP-пакет для каждого доступа к/dev/random и/dev/urandom, а также каждое событие клавиатуры/мыши, используемое генератором случайных чисел для сбора энтропии. Однако он не работает вообще, когда я пытаюсь контролировать события диска: он генерирует панику ядра во время загрузки.

Следовательно, вот мой главный вопрос: У вас есть идеи, почему мой код вызывает столько проблем при вставке в функцию событий диска? (add_disk_randomness)

В качестве альтернативы, я прочитал об API netpoll, который должен обрабатывать такие проблемы UDP-в-ядре. К сожалению, я не нашел никакой соответствующей документации, кроме довольно интересной, но устаревшей презентации Red Hat от 2005 года. Как вы думаете, я должен использовать этот 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); 
+4

Как правило, желательно, чтобы вы ничего не делали в ядре, которое вы могли бы сделать в пользовательском пространстве, - вероятно, было бы лучше разоблачить информацию в пользовательском пространстве через механизмы ведения журнала или sysfs, а затем отправить демон в удаленную систему , –

+0

Если подобная тема уже существует, ссылайтесь на нее. Вы сделали разумную работу, объяснив, почему вы считаете, что существующий вопрос недостаточно хорош (я мог бы сказать что-то о более новой версии ядра и т. Д.). Но имея доступный существующий вопрос, он позволяет получить ответы на то, что изменилось с тех пор. –

+0

@BenVoigt Thx для вашего совета. Вот [предыдущая тема] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin

ответ

13

я решил мою проблему несколько месяцев назад. Вот решение, которое я использовал.

Стандартный пакетный API (sock_create, connect, ...) не может использоваться в нескольких контекстах (прерывания). Использование его в неправильном месте приводит к КП.

API netpoll более «низкоуровневый» и работает в любом контексте. Тем не менее, есть несколько условий:

  • устройство Ethernet
  • 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; 

Initialization

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

Надеется, что это может помочь кому-то.

+0

как поднятый [здесь] (http://stackoverflow.com/questions/35880786/why-do-i-get-this-error), версия ядра 3.9 (апрель 2013 г.) сделала разбитое изменение на 'linux/netpoll.h 'поэтому этот код больше не компилируется –

0

Паника во время загрузки может быть вызвана тем, что вы пытаетесь использовать что-то, еще не инициализированное. Глядя на стек стека может помочь выяснить, что на самом деле произошло.

Что касается вас, я думаю, что вы пытаетесь сделать простую вещь, так почему бы не использовать простые инструменты? ;) printks может быть плохой идеей, но дать trace_printk a go. trace_printk является частью инфраструктуры Ftrace.

Раздел с использованием трассировки _printk() в следующей статье, должны научить вас все, что вам нужно знать: http://lwn.net/Articles/365835/

Смежные вопросы