public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
From: Peng Yu <pengyu.ut@gmail.com>
To: libc-help <libc-help@sourceware.org>
Subject: How to get ICMP reply packet correctly?
Date: Wed, 3 Mar 2021 14:01:27 -0600	[thread overview]
Message-ID: <CABrM6wmqkbps3JwzdT_sx2k6dv5L2_5FO6t9dj1yrcVtqkTN0w@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 4091 bytes --]

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

[-- Attachment #2: main.c --]
[-- Type: application/octet-stream, Size: 2928 bytes --]

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

                 reply	other threads:[~2021-03-03 20:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABrM6wmqkbps3JwzdT_sx2k6dv5L2_5FO6t9dj1yrcVtqkTN0w@mail.gmail.com \
    --to=pengyu.ut@gmail.com \
    --cc=libc-help@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).