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