2012-05-08 8 views
15

からUDPパケットを送信します乱数ジェネレータ(/drivers/char/random.c)の動作を監視するために、Linuxカーネル(3.3.4)からUDPパケットを送信する方法を解説します。これまでは、sock_create関数とsock_sendmsg関数のためにいくつかのことを監視してきました。このメッセージの最後に私が使用する典型的なコードを見つけることができます。 (完全修飾random.cファイルhereをダウンロードすることもできます)。は私がしようとしている...私はそれが新鮮なものを開くために、より適切だと思うので、それは2年さかのぼること</p> <p>に気づいた、類似したトピックがすでに存在する場合でも、Linuxカーネル

このコードを適切なrandom.c関数内に挿入すると、/ dev/randomへのアクセスごとにUDPパケットを送信できます/ dev/urandom、および乱数ジェネレータがエントロピーを収穫するために使用する各キーボード/マウスイベントです。しかし、ディスクイベントを監視しようとすると、まったく動作しません。起動時にカーネルパニックが発生します。

私の主な質問は次のとおりです。ディスクイベント機能にコードを挿入すると、なぜ私のコードが問題になるのですか?(add_disk_randomness)

また、この種のUDPカーネルの問題を処理するはずのnetpoll APIについても読んだことがあります。残念ながら2005年のかなり面白いですが時代遅れのRed Hatプレゼンテーションから離れて関連する文書は見つかりませんでした。私はむしろこの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

:次の記事でトレース _printkを使用して

セクションは()あなたが知る必要があるすべてを教える必要があります。ここで私が使った解決策があります。

標準のパケット送信API(sock_create、connect、...)は、いくつかのコンテキスト(中断)では使用できません。間違った場所でそれを使用すると、KPが発生します。

netpoll APIはより "低レベル"であり、すべてのコンテキストで動作します。しかし、いくつかの条件があります。

  • イーサネットデバイス
  • 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; 

初期

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

がカーネルバージョン3.9(2013年4月)で 'linux/netpoll.h 'に改訂されました(http://stackoverflow.com/questions/35880786/why-do-i-get-this-error) 'このコードはもうコンパイルされません –

0

起動時のパニックは、まだ初期化されていないものを使用しようとしていることが原因です。スタックトレースを見ると、実際に何が起きたかを知るのに役立ちます。

あなたの問題としては、単純なことをやろうとしていると思います。単純なツールを使用してみませんか? ;)printksは実際には悪い考えかもしれませんが、trace_printkを実行してください。 trace_printkは、Ftraceインフラストラクチャの一部です。私は数ヶ月前に私の問題を解決し http://lwn.net/Articles/365835/

関連する問題

 関連する問題