0

誰かが私のICMPシーケンス番号がすべての要求でインクリメントされない理由を理解するのを手伝ってくれる可能性があります。これがpingプログラムとして使用された場合、各pingでシーケンス番号がインクリメントされます。また、私の往復時間が負の数として表示される理由を誰かが知っていますか?これがpingプログラムの場合も、これは正常に機能しました。

すべてのコードが「機能する」と仮定してください。読みやすくするために一部を削除しました。

void
respond (int signum) {
   struct sockaddr_storage peer_addr;
   socklen_t               peer_addrlen;
   struct sockaddr_in      addr;
   struct sockaddr_in      dstaddr;
   struct iphdr   *        ip;
   struct icmphdr *        icmp;
   struct timeval *        sent;
   int skt;
   int sequence = 0;
   long int length;
   fd_set rdfds;
   int ready;
   int rtt;
   char buff [BUF_SIZE];

   /* Create and check Socket Number */
   skt = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);


    int ttl = 0;
    setsockopt(skt, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0;


       /* Check Socket */
       if (skt < 0) {
          perror ("socket()");
          exit (1);
       }

       /* Set IP Addresses */
       addr.sin_family      = AF_INET;
       addr.sin_port        = 0;
       addr.sin_addr.s_addr = INADDR_ANY;


       /* Check Socket Bind */
       if (bind (skt, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
          perror ("Can't bind socket");
          exit (1);
       }

/* START SEND LOOP*/
int i;
for (i = 0; i < 7; i++){
        ttl+=1;
        setsockopt(skt, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));

        /* IP Buffer */
       ip = (struct iphdr *)buff;
       peer_addrlen = (socklen_t) sizeof (struct sockaddr_storage);
       memset (&dstaddr, 0, sizeof(struct sockaddr_in));
       dstaddr.sin_addr.s_addr = inet_addr(HOSTADDR);
       dstaddr.sin_family = AF_INET;

       /* ICMP Buffer */
       memset (buff, 0, sizeof(buff));
       icmp = (struct icmphdr *) buff;
       icmp->type   = ECHO_REQ;
       icmp->id     = htons(getpid( ) & 0xffff);
       icmp->seqNum = htons(sequence++);


       /* Check Send Time */
       if (gettimeofday ((struct timeval *)icmp->data, NULL)) {
          perror ("Can't establish send time");
          exit (1);
       }

       /*Calculating packet size*/
       length = sizeof(struct icmphdr) + sizeof(struct timeval);
       icmp->checksum = ~(sum (0, buff, length));



       /* Packet too small, ERROR
       SEND Request             */
       if (sendto (skt, buff, length, 0,
             (struct sockaddr *) &dstaddr, sizeof(struct sockaddr_in)) <= 0) {
          perror ("sendto()");
          exit (1);
        }

       /* Define File Descriptor */
       timeout.tv_sec  = 1;
       timeout.tv_usec = 1;
       FD_ZERO(&rdfds);
       FD_SET (skt, &rdfds);

       /* Select Data from File Descriptor */
       ready = select (skt + 1, &rdfds, NULL, NULL, &timeout);
       if (ready < 0) {
          perror ("Select()");
          exit (1);
       }

        /* Recieve Reply */
        memset (buff, 0, sizeof(buff));
       if (recvfrom (skt, buff, sizeof(buff), 0,
            (struct sockaddr *) &peer_addr, &peer_addrlen) <= 0) exit (1);



       /* Check Time Stamp */
       if (gettimeofday (&end, NULL)) {   // Timestamp reception
          perror ("Can't establish time of receipt");
          exit (1);
       }


       /* Check IP Protocol */
       if (ip->version != 4 ||
           sum (0, buff, sizeof(struct iphdr)) != 0xffff ||
           ip->protocol != ICMP)
          exit(1);


       /* Get IP Payload legth and ICMP Address*/
       length = ntohs(ip->length) - ip->hdrlen * 4;       // Length of IP payload
       icmp = (struct icmphdr *)((uint32_t *)ip + ip->hdrlen);   // Find ICMP hdr


       /* Check ICMP response type*/
       if (icmp->type == 11){
           printf("");
           }

      /* if (icmp->type != ECHO_REPL || sum (0, icmp, length) != 0xffff) {
          fprintf (stderr, "Received %s\n", messages[icmp->type]);
          //exit (1);
       } */

       /*   Find the difference between sent and end times in 10s of ms */
       sent = (struct timeval *)icmp->data;
       if ((rtt = (end.tv_usec - sent->tv_usec) / 10) < 0)
          rtt += 10000;  // We've cycled to a new second
       rtt += (end.tv_sec - sent->tv_sec) * 10000;  // Add any seconds

       /* PRINT ICMP REPLY*/
       printf ("%ld bytes from %s: icmp_req=%d ttl=%d time= %0.1f ms\n",
      length,
      iptos(ntohl(ip->srcip)),
      ntohs(icmp->seqNum),
      ip->ttl,
      ((float)rtt) / 10);


} /*END SEND LOOP


   /* 3 Second Probe */
   alarm (5);
}
4

2 に答える 2

2

このコードでシーケンスを0に設定することはなく、intであると宣言するだけです。

于 2013-02-08T00:18:56.273 に答える
1

このコードでは、次のようになります。

   /* IP Buffer */
   ip = (struct iphdr *)buff;
   peer_addrlen = (socklen_t) sizeof (struct sockaddr_storage);
   memset (&dstaddr, 0, sizeof(struct sockaddr_in));
   dstaddr.sin_addr.s_addr = inet_addr(HOSTADDR);
   dstaddr.sin_family = AF_INET;

   /* ICMP Buffer */
   memset (buff, 0, sizeof(buff));
   icmp = (struct icmphdr *) buff;
   icmp->type   = ECHO_REQ;
   icmp->id     = htons(getpid( ) & 0xffff);
   icmp->seqNum = htons(sequence++);

バッファbuffをIPヘッダーとICMPヘッダーの両方で始まるものとして扱っています。構造体の先頭にが含まれていない限り(Linuxバージョンには含まれていません)icmphdr、IPヘッダーのサイズでポインターをオフセットする必要があると思います。icmphdriphdr

icmp = (struct icmphdr*)(buff + sizeof(iphdr));

また、memset (buff, 0, sizeof(buff));IPヘッダーをバッファに書き込んだ後に実行することにより、IPヘッダーを上書きしています。

于 2013-02-08T00:33:46.453 に答える