User Tools

Site Tools


ping.cpp
/*
 * ping.cpp
 *
 * Copyright 2004-2019 Oleg Borodin <borodin@unix7.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */
 
#include <iostream>
 
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp>
 
 
#include <istream>
#include <iostream>
#include <ostream>
 
using namespace boost::asio;
 
struct icmp_header {
    uint8_t icmp_type;
    uint8_t icmp_code;
    uint16_t icmp_cksum;
 
    uint16_t icmp_id;
    uint16_t icmp_seq;
};
 
class icmp_packet {
    public:
        icmp_header header;
 
        friend std::ostream& operator<<(std::ostream& ostream, icmp_packet& packet);
 
        void checksum() {
            const uint16_t * const data = (uint16_t *)&header;
            size_t byte_sz = sizeof(header);
 
            uint32_t accu = 0;
            for (size_t i = 0; i < (byte_sz >> 1); ++i) {
                accu = accu + data[i];
            }
            while (accu >> 16) {
                accu = (accu & 0xffff) + (accu >> 16);
            }
            const uint16_t checksum = ~accu;
            header.icmp_cksum = checksum;
        }
};
 
std::ostream& operator<<(std::ostream& ostream, icmp_packet& packet) {
    return ostream.write((char *)(&packet.header), sizeof(packet.header));
}
 
#define ICMP_ECHOREPLY  0
#define ICMP_ECHO       8
#define ICMP_CODE       0
 
int main(int argc, char **argv) {
 
    io_service io_service;
    ip::icmp::resolver resolver(io_service);
 
    ip::icmp::resolver::query query(ip::icmp::v4(), "wiki.unix7.org", "");
    ip::icmp::resolver::iterator iter = resolver.resolve(query);
    ip::icmp::endpoint destination = *iter;
 
    std::cout
        << "# dest address is "
        << destination.address().to_string()
        << std::endl;
 
    std::time_t now = std::time(0);
    std::cout << std::ctime(&now);
 
    ip::icmp::endpoint endpoint(ip::icmp::v4(), 0);
 
    try {
        ip::icmp::socket socket(io_service, endpoint);
 
        icmp_packet icmp_packet;
        icmp_packet.header.icmp_type = ICMP_ECHO;
        icmp_packet.header.icmp_code = ICMP_CODE;
        icmp_packet.header.icmp_id = htons(1234);
        icmp_packet.header.icmp_cksum = 0;
        icmp_packet.header.icmp_seq = htons(4567);
 
        icmp_packet.checksum();
 
        boost::asio::streambuf request_buffer;
        std::ostream ostream(&request_buffer);
        ostream << icmp_packet;
        socket.send_to(request_buffer.data(), destination);
    }
    catch (std::exception& e) {
            std::cout << "# exception: " << e.what() << "\n";
            return 0;
    }
 
    return 0;
}

Result network dump

16:28:30.892293 IP (tos 0x0, ttl 64, id 35762, offset 0, flags [none], proto ICMP (1), length 28)
    192.168.46.10 > vbsd05.unix7.org: ICMP echo request, id 1234, seq 4567, length 8
	0x0000:  4500 001c 8bb2 0000 4001 cabb c0a8 2e0a  E.......@.......
	0x0010:  5dab d815 0800 e156 04d2 11d7            ]......V....
16:28:30.940162 IP (tos 0x0, ttl 55, id 43562, offset 0, flags [none], proto ICMP (1), length 28)
    vbsd05.unix7.org > 192.168.46.10: ICMP echo reply, id 1234, seq 4567, length 8
	0x0000:  4500 001c aa2a 0000 3701 b543 5dab d815  E....*..7..C]...
	0x0010:  c0a8 2e0a 0000 e956 04d2 11d7            .......V....

First PagePrevious PageBack to overviewNext PageLast Page