c ++ - RAW ICMP socket: recvfrom () modtager ikke nogen data

Indlæg af Hanne Mølgaard Plasc

Problem



Følgende kode er et program designet til at sende ICMP-ekko-anmodninger og modtage svar.


/*
    Forgive my lack of error handling :)
*/
SOCKET ASOCKET = INVALID\_SOCKET;
struct sockaddr saddr;
struct sockaddr\_in *to = (struct sockaddr\_in *) &saddr;
struct sockaddr\_in from;
int fromsize = sizeof(from);
std::string ip = "[arbitrary ip address]";

struct ICMP {
    USHORT type;
    USHORT code;
    USHORT cksum;
    USHORT id;
    USHORT seq;
}*\_ICMP;

char sendBuffer[sizeof(struct ICMP)];
char recvBuffer[256];

WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

memset(&saddr, NULL, sizeof(saddr));
ASOCKET = socket(AF\_INET, SOCK\_RAW, IPPROTO\_ICMP);

//  Configure timeout
DWORD timeoutmilsec = 3000;
setsockopt(ASOCKET, SOL\_SOCKET, SO\_RCVTIMEO, (char *)&timeoutmilsec, sizeof(timeoutmilsec));

to->sin\_family = AF\_INET;
inet\_pton(AF\_INET, ip.c\_str(), &(to->sin\_addr));

\_ICMP = new ICMP();

\_ICMP->type = 8;
\_ICMP->code = 0;
\_ICMP->cksum = 0;
\_ICMP->id = rand();
\_ICMP->seq++;
// I have omitted my declaration of checksum() for simplicity
\_ICMP->cksum = checksum((u\_short *)\_ICMP, sizeof(struct ICMP));

memcpy(sendBuffer, \_ICMP, sizeof(struct ICMP));

if (sendto(ASOCKET, sendBuffer, sizeof(sendBuffer), NULL, (sockaddr *)&saddr, sizeof(saddr)) == SOCKET\_ERROR)
{
    printf("sendto() failed with error: \%u
", WSAGetLastError());
    return false;
}

if (recvfrom(ASOCKET, recvBuffer, sizeof(recvBuffer), NULL, (sockaddr *)&from, &fromsize) == SOCKET\_ERROR)
{
    if (WSAGetLastError() == TIMEOUTERROR)
    {
        printf("Timed out

");
        return false;
    }

    printf("recvfrom() failed with error: \%u
", WSAGetLastError());
    return false;
}


Mit problem er, at mit recvfrom() opkald ikke modtager nogen data og returnerer TIMEOUTERROR (10060) på trods af at ping har blevet besvaret (Wireshark fanger anmodningen og svaret bliver sendt). sendto() virker, men recvfrom() opfører sig mærkeligt, og jeg kan ikke finde ud af, hvad problemet er.


Hvad jeg finder interessant er recvfrom() vil kun modtage data, når gatewayen fortæller mig, at en vært ikke kan nås. det vandt ikke, hvis værten er nåbar og har reageret på pingen.

Bedste reference


Problemet ligger i struct ICMP.


type og code af ICMP bør være unsigned char.


Overskriften til ICMP skal være 8-byte, men størrelsen på struct ICMP er 10 bytes.


Så det bør ændres til:


struct ICMP {
    unsigned char type;
    unsigned char code;
    USHORT cksum;
    USHORT id;
    USHORT seq;
}*\_ICMP;

Andre referencer 1


Det viser sig hele tiden, at det var min firewall, der blokerede svarene. Den eneste fejl i min kode var størrelsen af ​​min ICMP-struktur (nævnt af cshu).


Tak for al hjælp for alle.