[英]Sending small UDP packets from the Linux Kernel to LOOPBACK
情況:我的代碼基本上被黑客入侵了Linux內核的驅動程序。 我想在用戶空間中通知一個關於值得注意的原始事件的應用程序,然后才能將它們發送到主系統。
解決方案的步驟:我在這里找到了一個從內核空間發送UDP數據包的好例子: http : //kernelnewbies.org/Simple_UDP_Server 。 他們使用INADDR_LOOPBACK作為目標地址,這正是我想要的。
由於這是中斷上下文,我決定使用工作隊列來發送數據包(我得到了BUG:在沒有它的情況下進行原子調度)。 因此,我的發送代碼基於kernelnewbies代碼,該代碼包含在主進程中使用INIT_WORK和schedule_work觸發的工作隊列結構中。 我沒有宣布自己的工作隊列。
我沒有使用Netpoll API,因為此問題表明無法從localhost發送數據。 “你不能發給自己”
問題:從內核發送並從我的UDP接收器接收的數據很少匹配。 我不知道為什么會這樣。
用於測試的虛擬數據的代碼,包括工作隊列的結構的定義:
static struct socket *sock_send;
static struct sockaddr_in addr_send;
static struct ksocket_workmessage {
unsigned char *buf;
int len;
struct work_struct workmessage;
} workmsg;
unsigned char testmsg[] = {'T', 'e', 's', 't', 'i', 'n', 'g', 'm', 's', 'g', '\0'};
workmsg.buf = testmsg;
workmsg.len = 11;
INIT_WORK(&workmsg.workmessage, handle_workmessage);
schedule_work(&workmsg.workmessage);
發送實際數據包就像kernelnewbies示例中的“int ksocket_send”。 唯一的區別是我的send_socket是靜態的,我必須從工作隊列中獲取buf和len與container_of。 我在一個完全靜態的環境中工作。 我的handle_workmessage方法也是靜態的:
static void handle_workmessage(struct work_struct *work)
{
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
int size = 0;
struct ksocket_workmessage *workmsg = container_of(work, struct ksocket_workmessage, workmessage);
if (sock_send->sk==NULL)
return;
iov.iov_base = workmsg->buf;
iov.iov_len = workmsg->len;
msg.msg_flags = 0;
msg.msg_name = &addr_send;
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
oldfs = get_fs();
set_fs(KERNEL_DS);
size = sock_sendmsg(sock_send,&msg,workmsg->len);
set_fs(oldfs);
}
接收端如下所示:
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr;
socklen_t len;
unsigned char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(REC_PORT);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;;)
{
n = recv(sockfd,mesg,1000,0);
printf("-------------------------------------------------------\n");
mesg[n] = 0;
printf("Received the following: %d bytes\n", n);
printf("%s",mesg);
printf("%c",mesg[0]);
printf(",%c",mesg[1]);
printf(",%c",mesg[2]);
printf(",%c",mesg[3]);
printf(",%c",mesg[4]);
printf(",%c",mesg[5]);
printf(",%c",mesg[6]);
printf(",%c",mesg[7]);
printf(",%c",mesg[8]);
printf(",%c\n",mesg[9]);
//printf("%c\n",mesg[0]);
printf("-------------------------------------------------------\n");
memset(mesg, 0, sizeof(mesg));
}
}
輸出看起來已損壞,即使我總是發送完全相同的消息用於測試目的:
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
����d����,�,�,�,d,�,�,�,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,�,�,�,�,2,k,�,�,�
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�<����,<,�,�,�,,,,
,=
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,,%,�,,,,,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
TestingmsgT,e,s,t,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
����Vk��1k ,�,�,�,�,V,k,�,�,1
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
TestingmsgT,e,s,t,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,,,,,�,,�,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,,
,�,,,,,�,<
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
這可能是什么原因? 由於它有時與預期輸出“TestingmsgT,e,s,t,i,n,g,m,s,g”有效,因此它不應該是技術限制。 也不會發生數據包碎片,因為我只發送11個字節。 也沒有丟包。 每次我發送數據包時,它也會被收到。
更新:它工作..但我不知道為什么首先,感謝來自alk的評論,我忘了顯而易見的。 在發送數據之前記錄。 我在調用schedule_work之前做了日志。 現在我直接在我的send方法workmsg-> buf中登錄,甚至在存儲到iov的void *指針之前。 那里的數據已經被破壞了。
struct ksocket_workmessage有一個char *,我的數據是char []並被分配給struct的指針。
我現在做的是更改我的struct ksocket_workmessage中的數據類型:
struct ksocket_workmessage {
unsigned char buf[11];
int len;
struct work_struct workmessage;
} workmsg;
由於我沒有指針,我無法創建我的unsigned char testmsg [],所以我直接分配了buf:
workmsg.buf[0] = 'T';
workmsg.buf[1] = 'e';
workmsg.buf[2] = 's';
workmsg.buf[3] = 't';
workmsg.buf[4] = 'i';
workmsg.buf[5] = 'n';
workmsg.buf[6] = 'g';
workmsg.buf[7] = 'm';
workmsg.buf[8] = 's';
workmsg.buf[9] = 'g';
workmsg.buf[10] = '\0';
如果有人能告訴我我最初的方法失敗了,我很樂意接受它作為正確的答案。
因為它有時會起作用,有時候我不會建議問題是你正在尋找已經免費的內存()d。 因此,內容有時是正確的,有時它們會被破壞。 由於本地緩沖區很好,因此必須在內核中將其復制到本地內存之前。
確實是unsigned char testmsg[]
聲明為局部變量?
由於消息不會立即發送,因此您傳遞的testmsg地址位於堆棧中。 如果存在后續的功能調用,則它們將在發送之前重寫消息的內容。 然后,您有時會看到正確的信息,有時則看不到。 取決於工作的安排。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.