2011-02-03 22 views
4

私は、特定のIPアドレスにUDPパケットを送信し、有効期限が切れていることを伝えるルータのICMP応答を待つCプログラムを作成しようとしています。私はちょうど最初にそのメカニズムを理解したいので、それはとても単純です。私が必要とするのは、私のコードをチェックして何が間違っていて何が欠けているのかをフィードバックする人です。私が受信し続けるUDPパケットを送信し、CのルータからICMP応答を受信

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netinet/ip.h> 

// The packet length 
#define PCKT_LEN 8192 

// Source IP, source port, target IP, target port from the command line arguments 
int main(int argc, char *argv[]) 
{ 
    int send, recv, resp; 
    int ttl = 1; // Time to live 
    char buffer[PCKT_LEN]; 

    // Destination address 
    struct sockaddr_in dst; 

    // ICMP Response 
    struct msghdr icmp; 

    memset(buffer, 0, PCKT_LEN); 

    // Create a raw socket with UDP protocol 
    if ((send = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
    { 
     printf("Could not process socket() [send].\n"); 
     return EXIT_FAILURE; 
    } 

    // ICMP Socket 
    if ((recv = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) 
    { 
     printf("Could not process socket() [recv].\n"); 
     return EXIT_FAILURE; 
    } 

    dst.sin_family  = AF_INET; 
    dst.sin_addr.s_addr = inet_addr("74.125.39.106"); 
    dst.sin_port  = htons(60001); 

    // Define time to life 
    if(setsockopt(send, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) 
    { 
     printf("Could not process setsockopt().\n"); 
     return EXIT_FAILURE; 
    } 

    if(sendto(send, buffer, sizeof(buffer), 0, (struct sockaddr *) &dst, sizeof(dst)) < 0) 
    { 
     printf("Could not process sendto().\n"); 
     return EXIT_FAILURE; 
    } 


    if((resp = recvmsg(recv, (struct msghdr *) &icmp, IP_RECVERR|MSG_ERRQUEUE)) < 0) 
    { 
     printf("Could not process recvmsg().\n"); 
     return EXIT_FAILURE; 
    } 

    close(send); 
    close(recv); 

    return 0; 
} 

...それを理解するために全力を与える - 私はCプログラミングで非常に未経験だが、私は割り当てとしてそれをしなければならない「()のrecvmsgを処理できませんでした。」もう何を試していいのか分かりません。 ICMPの回答を受け取り、その送信者のIPアドレスを読んでみたいと思います。

役に立つヒントを楽しみにしています。

よろしくお願いいたします。

+0

'recvfrom'からエラーが何であるのでしょうか? –

+0

it's recvmsg –

+2

printfの直後に 'perror'を呼び出して、エラーの詳細を取得します(http://linux.die.net/man/3/perror)。 – user470379

答えて

5

私は普通

recvfrom(serversock, buf, 100, 0, (struct sockaddr *)&rcv,&size); 

printf("Received packet from %s:%d\nData: %s\n\n", inet_ntoa(rcv.sin_addr), ntohs(rcv.sin_port), buf); 
+0

それは私のコードにすべての魔法がなかった。どうもありがとうございます。私はすでにそれを絶望していました。 –

+0

'NI_NUMERIC'と一緒に' getnameinfo'を使用して、アドレスを印刷可能な数値形式に変換します。 'inet_ntoa'とは異なり、静的な記憶域を使用しないので、スレッドセーフでライブラリコードから安全に使用できます。 –

+0

また、 'inet_ntop()'もあります。 – ninjalj

関連する問題