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 标头开头。我相信您需要将icmphdr指针偏移 IP 标头的大小,除非您的icmphdr结构在其开头包含一个iphdr(Linux 版本没有):

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

此外,在将 IP 标头memset (buff, 0, sizeof(buff));写入缓冲区之后,您将覆盖 IP 标头。

于 2013-02-08T00:33:46.453 回答