0

UDPプロトコルを変更して、UDPソケットでconnect()が呼び出されたときに、ルートを見つけることに加えて、 "Hello"パケットも先。linuxカーネルからUDPパケットを送る方法

UDPプロト構造から、ip4_datagram_connectという機能が宛先へのルートを見つける仕事をしていることが分かりました。今この関数の最後に、Helloパケットを送信する必要があります。

  1. udp_sendmsg()は、ユーザー空間からデータをコピーして送信するために使用されるとは思いません。
  2. 私はudp_send_skb()がこんにちはの送信に使用されるべきだと思います。私の問題は、udp_send_skb()に渡されるHelloメッセージ(適切なUDPデータグラムでなければなりません)を格納するための適切なskbuffを作成する方法を知らないことです。私はしかし、この

    int quic_connect(struct sock *sk, struct flowi4 *fl4, struct rtable *rt){ 
    struct sk_buff *skb; 
    char *hello; 
    int err = 0, exthdrlen, hh_len, datalen, trailerlen; 
    char *data; 
    
    hh_len = LL_RESERVED_SPACE(rt->dst.dev); 
    exthdrlen = rt->dst.header_len; 
    trailerlen = rt->dst.trailer_len; 
    datalen = 200; 
    
    //Create a buffer to be send without fragmentation 
    skb = sock_alloc_send_skb(sk, 
         exthdrlen + datalen + hh_len + trailerlen + 15, 
         MSG_DONTWAIT, &err); 
    if (skb == NULL) 
        goto out; 
    
    skb->ip_summed = CHECKSUM_PARTIAL;  // Use hardware checksum 
    skb->csum = 0; 
    skb_reserve(skb, hh_len); 
    skb_shinfo(skb)->tx_flags = 1;   //Time stamp the packet 
    
    
    /* 
    * Find where to start putting bytes. 
    */ 
    data = skb_put(skb, datalen + exthdrlen); 
    skb_set_network_header(skb, exthdrlen); 
    skb->transport_header = (skb->network_header + 
          sizeof(struct iphdr)); 
    
    err = udp_send_skb(skb, fl4); 
    

試してみた、これはカーネルログに私にエラーを与える

BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 
IP: [<ffffffff81686555>] __ip_local_out+0x45/0x80 
PGD 4f4dd067 PUD 4f4df067 PMD 0 
Oops: 0000 [#1] SMP 
Modules linked in: 
CPU: 0 PID: 3019 Comm: client Not tainted 3.13.11-ckt39-test006 #28 
Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 
task: ffff8800598df6b0 ti: ffff880047022000 task.ti: ffff880047022000 
RIP: 0010:[<ffffffff81686555>] [<ffffffff81686555>] __ip_local_out+0x45/0x80 
RSP: 0018:ffff880047023d78 EFLAGS: 00010287 
RAX: 0000000000000001 RBX: ffff880047008a00 RCX: 0000000020000000 
RDX: 0000000000000000 RSI: ffff880047008a00 RDI: ffff8800666fde40 
RBP: ffff880047023d88 R08: 0000000000003200 R09: 0000000000000001 
R10: 0000000000000000 R11: 00000000000001f9 R12: ffff880047008a00 
R13: ffff8800666fde80 R14: ffff880059aec380 R15: ffff880059aec690 
FS: 00007f5508b04740(0000) GS:ffff88007fc00000(0000) knlGS:0000000000000000 
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b 
CR2: 0000000000000018 CR3: 000000004f561000 CR4: 00000000000406f0 
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 
Stack: 
ffff880047023d80 ffff880047008a00 ffff880047023da0 ffffffff8168659d 
ffffffff81c8f8c0 ffff880047023db8 ffffffff81687810 0000000000000000 
ffff880047023df8 ffffffff816ac6be 0000000000000020 ffff880047008a00 
Call Trace: 
[<ffffffff8168659d>] ip_local_out+0xd/0x30 
[<ffffffff81687810>] ip_send_skb+0x10/0x40 
[<ffffffff816ac6be>] udp_send_skb+0x14e/0x3d0 
[<ffffffff816b0e9e>] quic_connect+0x6e/0x80 
[<ffffffff816aa3ff>] __ip4_datagram_connect+0x2bf/0x2d0 
[<ffffffff816aa437>] ip4_datagram_connect+0x27/0x40 
[<ffffffff816b8748>] inet_dgram_connect+0x38/0x80 
[<ffffffff8161fd97>] SYSC_connect+0xc7/0x100 
[<ffffffff817ed471>] ? __schedule+0x341/0x8c0 
[<ffffffff816206e9>] SyS_connect+0x9/0x10 
[<ffffffff817f8d42>] system_call_fastpath+0x16/0x1b 
Code: c8 00 00 00 66 c1 c0 08 66 89 47 02 e8 d5 e0 ff ff 48 8b 53 58 b8 01 00 00 00 48 83 e2 fe 48 81 3d 9d 0e 64 00 f0 73 cc 81 74 26 <4c> 8b 42 18 49 c7 c1 f0 45 68 81 c7 04 24 00 00 00 80 31 c9 48 
RIP [<ffffffff81686555>] __ip_local_out+0x45/0x80 
RSP <ffff880047023d78> 
CR2: 0000000000000018 
---[ end trace 474c5db1b9b19a03 ]--- 

だから私はそれができる前に、私のskbuffに記入する必要があります他に何私の質問され、 udp_send_skbで適切に処理してください。それとも私はここに何か他のものを逃している?

答えて

1

コードにバグがあります。

if (skb_tailroom(hbuff) > 30) { 
    printk("  Enough room for QUIC connect message\n"); 
    hello = kmalloc(30, GFP_ATOMIC);  //You allocate slub memory 
    hello = "Hello from QUIC connect"; //You let 'hello' point to a string, 
             //which is stored somewhere else. 
             //At this point, your slub memory 
             //allocated is lost. 

    memcpy(__skb_put(hbuff, 30), hello, 30); 
    kfree(hello);     //You try to free the memory pointed by 
            //hello as slub memory, I think this is 
            // why you get mm/slub.c bug message. 
} else 

あなたは、このようにコードを変更することができます。

if (skb_tailroom(hbuff) > 30) { 
    printk("  Enough room for QUIC connect message\n"); 

    memcpy(__skb_put(hbuff, 30), "Hello from QUIC connect", 30); 
} else 
+0

ありがとうございます。私は自分のコードでそれを変更します。私はまだ、udp_send_skb関数に渡す前にskbufferを正しく構築する方法を理解していません。 –

+0

私は元の投稿を編集しました –

+0

udp_sendmsg() - > ip_append_data() - > __ip_append_data()?ソケットがskbuffを取得し、データを添付してネットワークスタックに送信します。 – Lin

0

私はちょうどip_send_skb続い機能ip_make_skbを使用します。 ip_make_skbはユーザー空間からデータをコピーするために使用され、私はそれをする必要はありませんでしたので、ダミーポインターを使用して、この関数の必要に応じてゼロ(+ sizeof udphdr)としてコピーする長さを指定しました。これを行うには汚い方法ですが、今のところうまくいきます。 マイコード:

int quic_connect(struct sock *sk, struct flowi4 *fl4, struct rtable *rt, int oif){ 
    struct sk_buff *skb; 
    struct ipcm_cookie ipc; 
    void *hello = "Hello"; 
    int err = 0; 

    ipc.opt = NULL; 
    ipc.tx_flags = 1; 
    ipc.ttl = 0; 
    ipc.tos = -1; 
    ipc.oif = oif; 
    ipc.addr = fl4->daddr; 
    skb = ip_make_skb(sk, fl4, ip_generic_getfrag, hello, sizeof(struct udphdr), 
       sizeof(struct udphdr), &ipc, &rt, 
       0); 
    err = PTR_ERR(skb); 
    if (!IS_ERR_OR_NULL(skb)){ 
     err = udp_send_skb(skb, fl4); 
    } 

    return err;      

} 
関連する問題