Icmp Request Received, But Doesn't Reply

ICMP replies seen by tcpdump but ping 100% fails

I finally solved this. It was cause by rp_filter activated on the concerned interface and on all the system as well. I disabled it with: sysctl -w net.ipv4.conf.all.rp_filter=0 (replace all with the interface also).

Send Icmp message but receive nothing?

First you need to insure that the compiler doesn't pad your struct trying to align everything on 4, 8 or 16 byte address boundaries (#pragma pack), then you have to properly align the struct and correctly calculate the checksum. On the response side, you can't treat the buffer as a string, it could have non-ASCII data in it. Also, network byte order is not always the same as the byte order on either of the host architectures, so you should always convert before sending/receiving.

This works. I'll leave it to you to work out what the extra 20 or so bytes in the response are all about.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ws2tcpip.h>
#include <winsock2.h>

#include <fcntl.h>

#include <string.h>
#include <sys/stat.h>

#pragma comment(lib,"Ws2_32.lib")

#define STRING_LENGTH 32

//**************icmp book******************/
#pragma pack(push, 1)
typedef struct icmp_msg {
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t sequence;
uint32_t timestamp;
uint8_t tail[STRING_LENGTH + 2];
} ICMP_MSG;
#pragma pack(pop)

// malloc() is gauranteed to provide suitable alignement.
ICMP_MSG *ping = NULL;

void PrintMsg(ICMP_MSG *msg)
{
printf("Ping:\n\tId: %u16\n\tSequence: %u16\n\tTimestamp: %lu\n\tString: ", ntohs(msg->id), ntohs(msg->sequence), ntohl(msg->timestamp));

char *it = (char*)&(msg->tail[0]);
char *it_end = (char*)msg + sizeof(ICMP_MSG);
while (it < it_end)
{
char *hexString[65] = { 0 };
_itoa_s(*it, (char*)hexString, 32, 16);
printf("0x%s,", (char*)hexString);
it++;
}

printf("\n\n");
}

// Ripped from https://github.com/pocoproject/poco/blob/develop/Net/src/ICMPPacketImpl.cpp#L98 and cleaned-up.
uint16_t Checksum(uint16_t *addr, size_t len)
{
size_t nleft = len;
uint16_t* w = addr;
uint16_t answer;
int32_t sum = 0;

while (nleft > 1)
{
sum += *w++;
nleft -= sizeof(uint16_t);
}

if (nleft == 1)
{
uint16_t u = 0;
*(uint8_t*)(&u) = *(uint8_t*)w;
sum += u;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum & 0xffff;

return answer;
}

int main(void) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

ping = malloc(sizeof(ICMP_MSG));

ping->type = 8;
ping->code = 0;
ping->id = htons(1314);
ping->checksum = 0; // Must be zero prior to checksum calculation.
ping->sequence = 0;
ping->timestamp = htonl(GetTickCount());

// 0x40 == '@' in ASCII
memset(ping->tail, 0x40, STRING_LENGTH);
// NUL pad the last two bytes fo the string.
ping->tail[STRING_LENGTH] = '\0';
ping->tail[STRING_LENGTH + 1] = '\0';

ping->checksum = Checksum((uint16_t*)ping, sizeof(ICMP_MSG));

int res;
int my_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

struct in_addr my_addr;
my_addr.s_addr = inet_addr("127.0.0.1");
//res = inet_pton(AF_INET, "127.0.0.1", &my_addr.s_addr);

struct sockaddr_in sa_t;

sa_t.sin_family = AF_INET;
sa_t.sin_port = htons(0);
sa_t.sin_addr = my_addr;

PrintMsg(ping);

res = sendto(my_socket, (const char*)ping, sizeof(ICMP_MSG), 0, (struct sockaddr *)&sa_t, sizeof(sa_t));

printf("Socket: %d\nsendto returned: %d\n", my_socket, res);

int tmp_add = sizeof(sa_t);

ICMP_MSG *resp = calloc(1, 2048 /*sizeof(ICMP_MSG)*/);

res = recvfrom(my_socket, (char*)resp, 2048, 0, (struct sockaddr *)&sa_t, &tmp_add);

printf("recvfrom returned: %d\n", res);
if (SOCKET_ERROR == res)
{
res = WSAGetLastError();
printf("WSAGetLastError() returned: %d (", res);
switch (res)
{
case WSAEMSGSIZE:
printf("WSAMSGSIZE)\n");
break;
default:
printf("Unexpected)\n");
break;
}
}

PrintMsg(resp);

system("pause");

free(ping);
free(resp);

return 1;

}

unable to receive the answer of a fragmented ICMP Echo Request

There are a lot of reasons why this won’t work:

  • sr() stands for « send receive ». This function already sends the packet, so you don’t need to send it previously
  • sr() returns multiple answers, meaning that it won’t stop if you don’t ^C it or if it timeout. You are looking for sr1() which returns on the first answer
  • scapy cannot (yet) defragment packets « on the flow ». When you are calling sr/sr1, it checks each packet for a possible answer, but there won’t be any as it does not defragment on the flow. For this answer, you need to implement all the « answer checking » yourself, or find another way.

Anyway, I don’t know if a lot of servers will answer such a ICMP

Scapy ICMP echo request (Ping) is not replied while a Ping from the command line gets replies

Scapy may be picking the wrong interface/route.

What I would do is run sr1 with the iface parameter and provide an explicit interface name. Scapy has the get_if_list() function to list your network interfaces but on Windows this could be different. Seeing that you are using Windows you may have to use the 'meaningful name' ie 'Network Connection 1'. Here is a useful link just in case: Python netifaces and scapy: Getting meaningful Interface-names and full IP-Adresses-/Netmask-Information

Ping request not shown in Wireshark if no reply is received, how come?

If you ping via hostname, first there will be a DNS lookup to retrieve the IP address. You will not find an IP address because pc doesn't exists, so Ping will not even try to send a request because it doesn't know where to send it to.



Related Topics



Leave a reply



Submit