How to ping using C sockets
Asked Answered
P

2

8
  • Compiler: Code::Blocks(GNU GCC)
  • Platform: Windows(x86)
  • Includes: winsock.h winsock2.h (ws2_32 is linked as well)

I am currently trying to write a program that will read a text file containing a list of IP-Addresses and ping each IP-Addresses respectively. If the host responds to the ping then the host's IP-Address will be copied to a seconded file specified by the user. Unfourtantly this is the first time I have used C's socket library and I cannot find a good tutorial about how to ping using C. From what I understand of the couple tutorials I did find. I need to included a ICMP header, which is a struct containg the ICMP type, code, and checksum, in a IP datagram. But I have no idea how to go about doing so, should I declare the struct myself or is it declared in a header file? I am assuming that it is in a header but the tutorials contradicted each other about exactly where it is declared. I tired including icmp.h and netinet/icmp.h but my compiler complained that they don't exist so I created my own struct.

    struct echo_request
    {
        char type; // Type
        char code; // Code
        short checksum; // Checksum
        short id; // Identification
        short seq; // Sequence
        int time; // Time
        char data[16]; // Data
    };

I thought that I might be able to get away with it but I wasn't even able to compile my program because my compiler says that in_cksum()(checksum generator) is undefined.

To sum up my questions, what header files should I include, how do I create a ping packet, am I using the correct checksum generator function, should a ping be directed to port 80, and should the socket I use be RAW or DGRAM?

This is what I have so far, please note that I have purposely left out error checking.

    int socket_descriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    struct sockaddr_in address; //Initialize address struct
    memset(&address, 0, sizeof(address)); //Clear address struct

    //Declare address
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ipaddress);
    address.sin_port = htons(80);

    //Bind socket to address
    bind(socket_descriptor, (struct sockaddr *)&address, sizeof(address));

    //Create packet
    struct echo_request packet; //See above for declaration of struct
    memset(packet.data, 1, 16);
    packet.type = 8; //ECHO_REQUEST
    packet.code = 0;
    packet.time = gettime();
    packet.checksum = 0;
    packet.checksum = in_cksum(packet, sizeof(packet));
Philadelphia answered 13/1, 2013 at 19:22 Comment(1)
1) the structure must be packed, make sure that compiler does not align fields 2) does Windows support raw sockets well (I don't know this)?Implantation
S
5

If you don't have to implement the ping from scratch and you want only Windows solution, I'd second Anton's suggestion for IcmpSendEcho. If you have to implement ping, look at how POCO ICMP package is implemented. It is portable code and it runs fine on Windows.

In regards to the specific questions, here are the answers:

what header files should I include

#include <winsock2.h>

how do I create a ping packet

See ICMPv4PacketImpl::initPacket() for an example of IPv4 packet.

am I using the correct checksum generator function

Not for windows. See ICMPPacketImpl::checksum() for an example of checksum function.

should a ping be directed to port 80

No. There's no such thing as port when it comes to ICMP. See Does ICMP use a specific port?

should the socket I use be RAW or DGRAM

It should be RAW.

Sloe answered 14/1, 2013 at 18:55 Comment(2)
@Sloe does ICMP need running as admin and/or root to work?Protract
@Protract usually, yes. see https://mcmap.net/q/476317/-python-non-privileged-icmpSloe
T
4

It looks like you want a real solution, not just reimplementing PING for the sake of it.

I recommend using IP helper (ICMP.dll on pre-WinXP systems), specifically, IcmpSendEcho (or its enhanced versions, IcmpSendEcho2, IcmpSendEcho2Ex, for asynchronous operations).

There is a complete example of "pinging" a host on MSDN. It may be a good starting point.

Update: for GCC (mingw), link with -liphlpapi.

Teliospore answered 13/1, 2013 at 19:41 Comment(2)
Thanks for your response. I am aware of IcmpSendEcho but I want to implement a relatively portable solution.Philadelphia
but if your app does not have admin-privileges then IcmpSendEcho is the only choice according to: https://mcmap.net/q/816900/-why-does-ping-work-without-administrator-privilegesProtract

© 2022 - 2024 — McMap. All rights reserved.