简体   繁体   中英

Why is my ICMP sequence number not incrementing? (C Socket Programming)

is it possible someone can help me workout why my ICMP sequence number isn't incrementing on every request, when this was used as a ping program it would increment the sequence number on each ping. Also does anyone have any idea why my Round Trip Times are displaying as negative numbers? This also worked fine when this was a ping program.

Please assume all the code 'works', i have removed some for easier reading.

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);
}

在此代码中,您永远不会将sequence设置为0,而只是声明它是一个int。

In this piece of code:

   /* 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++);

you are treating the buffer buff as starting with both an IP header and an ICMP header. I believe you need to offset the icmphdr pointer by the size of the IP header, unless your icmphdr structure includes an iphdr at its start (which the Linux version does not):

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

Also, you are overswriting the IP header by doing memset (buff, 0, sizeof(buff)); after writing the IP header to the buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM