How to get ICMP reply packet correctly?

Peng Yu pengyu.ut@gmail.com
Wed Mar 3 20:01:27 GMT 2021


Hi,

When I run the following program on Linux. It prints like this. The
source and destination IP addresses ("08 08 08 08 c0 a8 01 68") are on
the data (pckt.msg) of ICMP reply packet. What are "76 01 72 89"?

I don't think ICMP data should have such IP addresses. And I check
with tcpdump. The packet received by tcpdump is correct.

Therefore, I think there is something wrong with the receive code in
my program. Could anybody help make the program correctly receive the
packet. (I still want to send the raw packet as is.) Thanks.

$ ./main 8.8.8.8
sin_family = 2
s_addr = 8080808
sin_port = 0
Packet received with ICMP type 69 code 0
pckt.hdr.checksum 5400
id=0 sequence=0, ttl=96
76 01 72 89 08 08 08 08 c0 a8 01 68 00 00 c8 a2 83 01 78 03 30 31 32
33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49
4a 4b 4c 4d 4e 4f 50 51 52 53

$ cat main.c
// vim: set noexpandtab tabstop=2:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/ip_icmp.h>
#include <time.h>

// Gives the timeout delay for receiving packets
// in seconds
#define RECV_TIMEOUT 1

// ping packet size
#define PING_PKT_S 64
// ping packet structure
struct ping_pkt {
    struct icmphdr hdr;
    unsigned char msg[PING_PKT_S-sizeof(struct icmphdr)];
};

unsigned short checksum(void *b, int len) {
    unsigned short *buf = b;
    unsigned int sum=0;
    unsigned short result;

    for ( sum = 0; len > 1; len -= 2 )
        sum += *buf++;
    if ( len == 1 )
        sum += *(unsigned char*)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}

int main(int argc, char *argv[]) {
    struct sockaddr_in addr_con;
    addr_con.sin_family = AF_INET;
    addr_con.sin_port = htons(0);

    const char *server_ip_addr = argv[1];
    int rval;
    if((rval = inet_pton(AF_INET, server_ip_addr,
&addr_con.sin_addr.s_addr)) == 0) {
        fprintf(stderr, "Invalid IPv4 address: %s\n", server_ip_addr);
        return 1;
    } else if(rval == -1) {
        perror("inet_pton()");
        return 1;
    }

    int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if(sockfd<0) {
        perror("socket()");
        return 1;
    }

    // set socket options at ip to TTL and value to 64,
    // change to what you want by setting ttl_val
    int ttl_val=96;
    if (setsockopt(sockfd, SOL_IP, IP_TTL,  &ttl_val, sizeof(ttl_val)) != 0) {
        perror("setsockopt()");
        return 1;
    }

    // setting timeout of recv setting
    struct timeval tv_out;
    tv_out.tv_sec = RECV_TIMEOUT;
    tv_out.tv_usec = 0;
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out,
sizeof tv_out);

    // send icmp packet in an infinite loop
    struct ping_pkt pckt;
    memset(&pckt, 0, sizeof(pckt));
    pckt.hdr.type = ICMP_ECHO;
    pckt.hdr.un.echo.id = 387;
    pckt.hdr.un.echo.sequence = 888;

    for (int i = 0; i < sizeof(pckt.msg); i++)
        pckt.msg[i] = i+'0';

    pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));

    //send packet
    if (sendto(sockfd, &pckt, sizeof(pckt), 0,
                (struct sockaddr*) &addr_con,
                sizeof(addr_con)) <= 0) {
        puts("Packet Sending Failed!");
        return 1;
    }

    //receive packet
    struct sockaddr_in r_addr;
    unsigned int addr_len=sizeof(r_addr);
    if (recvfrom(sockfd, &pckt, sizeof(pckt), 0, (struct
sockaddr*)&r_addr, &addr_len) <= 0) {
        puts("Packet receive failed!");
    } else {
        printf("sin_family = %0x\n", r_addr.sin_family);
        printf("s_addr = %0x\n", r_addr.sin_addr.s_addr);
        printf("sin_port = %0x\n", r_addr.sin_port);

        printf("Packet received with ICMP type %d code %d\n",
pckt.hdr.type, pckt.hdr.code);
        printf("pckt.hdr.checksum %04x\n", pckt.hdr.checksum);
        printf("id=%d sequence=%d, ttl=%d\n", pckt.hdr.un.echo.id,
pckt.hdr.un.echo.sequence, ttl_val);

        for(int i=0; i<sizeof(pckt.msg); ++i) {
            printf("%02x ", pckt.msg[i]);
        }
        puts("");
    }
    return 0;
}


-- 
Regards,
Peng
-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.c
Type: application/octet-stream
Size: 2928 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-help/attachments/20210303/67773096/attachment.obj>


More information about the Libc-help mailing list