2012-05-08 33 views
15

Ngay cả khi một chủ đề tương tự đã tồn tại, tôi nhận thấy rằng nó ngày trở lại hai năm, vì vậy tôi đoán nó là thích hợp hơn để mở một tươi ...gửi gói tin UDP từ Kernel Linux

Tôi đang cố gắng để tìm ra cách gửi gói UDP từ hạt nhân Linux (3.3.4), để theo dõi hành vi của trình tạo số ngẫu nhiên (/drivers/char/random.c). Cho đến nay, tôi đã quản lý để theo dõi một vài điều do các hàm sock_create và sock_sendmsg. Bạn có thể tìm thấy đoạn mã điển hình mà tôi sử dụng ở cuối thư này. (Bạn cũng có thể muốn tải xuống tệp random.c đã sửa đổi hoàn chỉnh here.)

Bằng cách chèn mã này vào các hàm random.c thích hợp, tôi có thể gửi gói UDP cho mỗi truy cập vào/dev/ngẫu nhiên và/dev/urandom, và mỗi sự kiện bàn phím/chuột được sử dụng bởi trình tạo số ngẫu nhiên để thu thập entropy. Tuy nhiên nó không hoạt động chút nào khi tôi cố gắng theo dõi các sự kiện đĩa: nó tạo ra sự hoảng sợ hạt nhân trong khi khởi động.

Do đó, đây là câu hỏi chính của tôi: Bạn có biết tại sao mã của tôi gây ra nhiều rắc rối khi được chèn vào chức năng sự kiện đĩa không? (add_disk_randomness)

Hoặc, tôi đã đọc về API netpoll, được cho là xử lý loại vấn đề UDP-in-hạt nhân này. Rất tiếc, tôi không tìm thấy bất kỳ tài liệu nào có liên quan ngoài một bản trình bày khá thú vị nhưng đã lỗi thời của Red Hat từ năm 2005. Bạn có nghĩ rằng tôi nên sử dụng API này không? Nếu có, bạn có ví dụ nào không?

Mọi trợ giúp sẽ được đánh giá cao. Cảm ơn trước.

PS: Đó là câu hỏi đầu tiên của tôi ở đây, vì vậy xin vui lòng đừng ngần ngại cho tôi biết nếu tôi làm sai điều gì, tôi sẽ giữ nó trong tâm trí cho tương lai :)


#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

Nói chung, tốt hơn là bạn không làm bất kỳ thứ gì trong kernel bạn có thể làm trong không gian người dùng - có lẽ tốt hơn là hiển thị thông tin cho không gian người dùng thông qua cơ chế ghi nhật ký hoặc sysfs và sau đó có một daemon gửi nó đến hệ thống từ xa . –

+0

Khi một chủ đề tương tự đã tồn tại, hãy liên kết với chủ đề đó. Bạn đã làm một công việc hợp lý giải thích lý do tại sao bạn nghĩ rằng câu hỏi hiện tại là không đủ tốt (tôi có thể đã nói điều gì đó về phiên bản hạt nhân mới hơn, vv). Nhưng có sẵn câu hỏi hiện có dễ dàng làm cho câu trả lời có thể tập trung vào những gì đã thay đổi kể từ đó. –

+0

@BenVoigt Thx để được tư vấn. Đây là [chủ đề trước] (http://stackoverflow.com/questions/1814485/sending-udp-packet-in-linux-kernel). – tvuillemin

Trả lời

13

tôi giải quyết vấn đề của tôi cách đây vài tháng. Đây là giải pháp tôi đã sử dụng.

API gửi gói chuẩn (sock_create, connect, ...) không thể được sử dụng trong một vài ngữ cảnh (gián đoạn). Sử dụng nó ở sai vị trí dẫn đến KP.

API netpoll là "cấp thấp" hơn và hoạt động trong mọi ngữ cảnh. Tuy nhiên, có một số điều kiện:

  • thiết bị Ethernet
  • mạng IP
  • UDP chỉ (không TCP)
  • máy tính khác nhau cho việc gửi và nhận các gói (Bạn không thể gửi cho chính mình.)

Đảm bảo tôn trọng chúng, vì bạn sẽ không nhận được bất kỳ thông báo lỗi nào nếu có sự cố. Nó sẽ chỉ âm thầm thất bại :) Đây là một chút mã.

Tuyên bố

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

Khởi

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; 

Sử dụng

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

Hy vọng nó có thể giúp ai đó.

+0

được nêu ra [tại đây] (http://stackoverflow.com/questions/35880786/why-do-i-get-this-error), phiên bản hạt nhân 3.9 (tháng 4 năm 2013) đã thực hiện một thay đổi đột phá đối với 'linux/netpoll.h 'do đó, mã này không còn biên dịch –

0

Hoảng loạn trong khi khởi động có thể do bạn cố gắng sử dụng thứ gì đó chưa được khởi tạo. Nhìn vào dấu vết ngăn xếp có thể giúp tìm ra những gì thực sự đã xảy ra.

Đối với bạn vấn đề, tôi nghĩ bạn đang cố gắng làm một điều đơn giản, vậy tại sao không gắn bó với các công cụ đơn giản? ;) máy in có thể là ý tưởng tồi thực sự, nhưng cho trace_printk một đi. trace_printk là một phần của cơ sở hạ tầng Ftrace.

Mục Sử dụng dấu vết _printk() trong bài viết sau đây sẽ dạy cho bạn mọi thứ bạn cần biết: http://lwn.net/Articles/365835/

Các vấn đề liên quan