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 previouslysr()
returns multiple answers, meaning that it won’t stop if you don’t ^C it or if it timeout. You are looking forsr1()
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
Can't Run Executable Linked with Libc
Linux/Gcc: Ldd Functionality from Inside a C/C++ Program
How to Open Remotely Installed Sonar on a Browser
Valgrind Does Not Work with Wsl
Shell Script, Saving the Command Value to a Variable
How to Mount a Usb Drive on Android Things
Calculate and Print the Average Value of Strings in a Column
Save and Restore Terminal Content
How to Pass Shell Variables as Command Line Argument to a Shell Script
Write(2)/Read(2) Atomicity Between Processes in Linux
Rename Multiple Files While Keeping the Same Extension on Linux
Why Can't I Sys_Write from a Pointer to Stack Memory, Using Int 0X80
How to Build Msi Package on a Linux Server
Write-Only Mapping a O_Wronly Opened File Supposed to Work
Platform Independent Resource Management
Signal Handling in Asm: Why am I Receiving Sigsegv When Invoking the Sys_Pause Syscall
Define Function in Unix/Linux Command Line (E.G. Bash)
Where to Start Learning About Linux Dma/Device Drivers/Memory Allocation