#wireshark cannot parse timestamp field in icmp echo requests

15 messages · Page 1 of 1 (latest)

wide mauve
#

I have that function that sends icmp echo requests, my problem is when I add timestamp to the packet and then I check with wireshark I see it cannot parse it correctly normally u will see timestamp shown in the packet info maybe I am not doing the timestamp correctly ?

func Request(sockfd int, ip string) (*Icmp, error) {
    
    seqN++

    targetIpB := net.ParseIP(ip).To4()

    targetIP := &syscall.SockaddrInet4{
        Addr: [4]byte{
            targetIpB[0], targetIpB[1], 
            targetIpB[2], targetIpB[3],
        },
    }

    icmp := &Icmp{
        id: uint16(rand.Intn(65536)),
        typ: EchoRequest,
        sqn: uint16(seqN),
    }
    
    icmp.data = make([]byte, 8)    

    binary.BigEndian.PutUint64(icmp.data, uint64(time.Now().UnixNano()))

    icmp.checksum = checksum(icmp.Bytes())

    if err := syscall.Sendto(sockfd, icmp.Bytes(), 0, targetIP); err != nil {
        return nil, err
    }

    buf := make([]byte, 1024)

    n, _, err := syscall.Recvfrom(sockfd, buf, 0)

    if err != nil {
        return nil, err
    }

    return FromBytes(buf[20:n]), nil
}
#

I am actually confused about that when I see how echo packet looks like in rfc it doesnt mention timestamp, but how can I add that tho .., utilities like ping in linux adds that timestamp in the request

#

I may look into ping source code but I would appreciate if someone hints me about that

unreal robin
#

can you show the timestamp you get?

wide mauve
#

@unreal robin hello, sorry I went to sleep xD, the thing is I am not getting a timestamp but for example that's how the ping command in linux echo request looks like it has a timestamp field but mine doesn't

#

this how the bytes for my timestamp looks like

#

and that's ping

#

I am not sure if that helps but I tried for example converting these bytes to readable form I assumed its unix time but I am getting large dates lol

#

I saw ping source code they use gettimeofday function

int ping4_send_probe(struct ping_rts *rts, socket_st *sock, void *packet,
             unsigned packet_size __attribute__((__unused__)))
{
    struct icmphdr *icp;
    int cc;
    int i;

    icp = (struct icmphdr *)packet;
    icp->type = ICMP_ECHO;
    icp->code = 0;
    icp->checksum = 0;
    icp->un.echo.sequence = htons(rts->ntransmitted + 1);
    icp->un.echo.id = rts->ident;            /* ID */

    rcvd_clear(rts, rts->ntransmitted + 1);

    if (rts->timing) {
        if (rts->opt_latency) {
            struct timeval tmp_tv;
            gettimeofday(&tmp_tv, NULL);
            memcpy(icp + 1, &tmp_tv, sizeof(tmp_tv));
        } else {
            memset(icp + 1, 0, sizeof(struct timeval));
        }
    }

    cc = rts->datalen + 8;            /* skips ICMP portion */

    /* compute ICMP checksum here */
    icp->checksum = in_cksum((unsigned short *)icp, cc, 0);

    if (rts->timing && !rts->opt_latency) {
        struct timeval tmp_tv;
        gettimeofday(&tmp_tv, NULL);
        memcpy(icp + 1, &tmp_tv, sizeof(tmp_tv));
        icp->checksum = in_cksum((unsigned short *)&tmp_tv, sizeof(tmp_tv), ~icp->checksum);
    }

    i = sendto(sock->fd, icp, cc, 0, (struct sockaddr *)&rts->whereto, sizeof(rts->whereto));

    return (cc == i ? 0 : i);
}

what I noticed is that timeval struct contains two fields seconds and microseconds, and it writes that

#

but I am quite unsure now, I see the timestamp in encoded in 8 bytes, but that struct timeval is 16 bytes

#

in case of 64-bit for sure

#

/* A time value that is accurate to the nearest
   microsecond but also has a range of years.  */
struct timeval
{
#ifdef __USE_TIME_BITS64
  __time64_t tv_sec;        /* Seconds.  */
  __suseconds64_t tv_usec;    /* Microseconds.  */
#else
  __time_t tv_sec;        /* Seconds.  */
  __suseconds_t tv_usec;    /* Microseconds.  */
#endif
};
#endif
#

maybe they are not defining that macro so they used the 32-bit version

#

of the struct

#

but I did try that too like that and still its not working as expected

    binary.BigEndian.PutUint32(icmp.data, uint32(time.Now().Unix()))
    binary.BigEndian.PutUint32(icmp.data, uint32(time.Now().UnixMicro()))