c++boostboost-asioistreamicmp

How to print icmp packet (including all headers) in hex from istream in boost-asio example


I am trying to modify the ICMP boost_asio implementation to print ICMP response and request packets. In the example code I am trying to print the response/reply buffer using below code:

void StartReceive()
{
    gSocket.async_receive_from(gReply.prepare(65536), gReceiver,
        [&](const error_code& error, size_t length)
    {   
        gReply.commit(length);

        ipv4_header ipv4Hdr;
        icmp_header icmpHdr;
        std::string body(BODY.size(), 0); 

        std::istream is(&gReply);

        char c;
        c = is.get();
        while (is)
        {   
            std::cout << std::hex << c;
            c = is.get();
        } 

I tried other methods also to print the buffer from std::istream reply, but it is printing garbage values. I will appreciate if someone can help in printing the buffer in hex format eg:

45 00 00 54 89 4c 00 00 40 01 fe af 0b 0b 0b 02 2c d5 af cb 08 00 e7 f7 44 4a 2a 95 62 c5 12 b2 00 0c 40 a2 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37

Thanks


Solution

  • ostream prints chars as characters, not integers, so std::hex format manipulator does nothing. Instead print as an (unsigned) integer, e.g.:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <iomanip>
    #include <iostream>
    #include <fstream>
    
    int main()
    {
        boost::asio::streambuf gReply;
    
        std::ostream(&gReply) << std::ifstream("main.cpp").rdbuf();
    
        std::istream is(&gReply);
        is >> std::noskipws;
    
        std::cout << std::hex << std::showbase <<  std::setfill('0');
        int col = 0;
        for(unsigned char c; is >> c;)
        {
            std::cout << std::setw(4) << static_cast<int>(c) << ' ';
            if (0 == (++col % 16))
                std::cout << '\n';
        }
    }
    

    Prints its own source in hex:

    0x23 0x69 0x6e 0x63 0x6c 0x75 0x64 0x65 0x20 0x3c 0x62 0x6f 0x6f 0x73 0x74 0x2f 
    0x61 0x73 0x69 0x6f 0x2e 0x68 0x70 0x70 0x3e 00xa 0x23 0x69 0x6e 0x63 0x6c 0x75 
    0x64 0x65 0x20 0x3c 0x69 0x6f 0x6d 0x61 0x6e 0x69 0x70 0x3e 00xa 0x23 0x69 0x6e 
    0x63 0x6c 0x75 0x64 0x65 0x20 0x3c 0x69 0x6f 0x73 0x74 0x72 0x65 0x61 0x6d 0x3e 
    00xa 0x23 0x69 0x6e 0x63 0x6c 0x75 0x64 0x65 0x20 0x3c 0x66 0x73 0x74 0x72 0x65 
    0x61 0x6d 0x3e 00xa 00xa 0x69 0x6e 0x74 0x20 0x6d 0x61 0x69 0x6e 0x28 0x29 00xa 
    0x7b 00xa 0x20 0x20 0x20 0x20 0x62 0x6f 0x6f 0x73 0x74 0x3a 0x3a 0x61 0x73 0x69 
    0x6f 0x3a 0x3a 0x73 0x74 0x72 0x65 0x61 0x6d 0x62 0x75 0x66 0x20 0x67 0x52 0x65 
    0x70 0x6c 0x79 0x3b 00xa 00xa 0x20 0x20 0x20 0x20 0x73 0x74 0x64 0x3a 0x3a 0x6f 
    0x73 0x74 0x72 0x65 0x61 0x6d 0x28 0x26 0x67 0x52 0x65 0x70 0x6c 0x79 0x29 0x20 
    0x3c 0x3c 0x20 0x73 0x74 0x64 0x3a 0x3a 0x69 0x66 0x73 0x74 0x72 0x65 0x61 0x6d 
    0x28 0x22 0x6d 0x61 0x69 0x6e 0x2e 0x63 0x70 0x70 0x22 0x29 0x2e 0x72 0x64 0x62 
    0x75 0x66 0x28 0x29 0x3b 00xa 00xa 0x20 0x20 0x20 0x20 0x73 0x74 0x64 0x3a 0x3a 
    0x69 0x73 0x74 0x72 0x65 0x61 0x6d 0x20 0x69 0x73 0x28 0x26 0x67 0x52 0x65 0x70 
    0x6c 0x79 0x29 0x3b 00xa 0x20 0x20 0x20 0x20 0x69 0x73 0x20 0x3e 0x3e 0x20 0x73 
    0x74 0x64 0x3a 0x3a 0x6e 0x6f 0x73 0x6b 0x69 0x70 0x77 0x73 0x3b 00xa 00xa 0x20 
    0x20 0x20 0x20 0x73 0x74 0x64 0x3a 0x3a 0x63 0x6f 0x75 0x74 0x20 0x3c 0x3c 0x20 
    0x73 0x74 0x64 0x3a 0x3a 0x68 0x65 0x78 0x20 0x3c 0x3c 0x20 0x73 0x74 0x64 0x3a 
    0x3a 0x73 0x68 0x6f 0x77 0x62 0x61 0x73 0x65 0x20 0x3c 0x3c 0x20 0x20 0x73 0x74 
    0x64 0x3a 0x3a 0x73 0x65 0x74 0x66 0x69 0x6c 0x6c 0x28 0x27 0x30 0x27 0x29 0x3b 
    00xa 0x20 0x20 0x20 0x20 0x69 0x6e 0x74 0x20 0x63 0x6f 0x6c 0x20 0x3d 0x20 0x30 
    0x3b 00xa 0x20 0x20 0x20 0x20 0x66 0x6f 0x72 0x28 0x75 0x6e 0x73 0x69 0x67 0x6e 
    0x65 0x64 0x20 0x63 0x68 0x61 0x72 0x20 0x63 0x3b 0x20 0x69 0x73 0x20 0x3e 0x3e 
    0x20 0x63 0x3b 0x29 00xa 0x20 0x20 0x20 0x20 0x7b 00xa 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x73 0x74 0x64 0x3a 0x3a 0x63 0x6f 0x75 0x74 0x20 0x3c 0x3c 0x20 
    0x73 0x74 0x64 0x3a 0x3a 0x73 0x65 0x74 0x77 0x28 0x34 0x29 0x20 0x3c 0x3c 0x20 
    0x73 0x74 0x61 0x74 0x69 0x63 0x5f 0x63 0x61 0x73 0x74 0x3c 0x69 0x6e 0x74 0x3e 
    0x28 0x63 0x29 0x20 0x3c 0x3c 0x20 0x27 0x20 0x27 0x3b 00xa 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x69 0x66 0x20 0x28 0x30 0x20 0x3d 0x3d 0x20 0x28 0x2b 0x2b 
    0x63 0x6f 0x6c 0x20 0x25 0x20 0x31 0x36 0x29 0x29 00xa 0x20 0x20 0x20 0x20 0x20 
    0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x73 0x74 0x64 0x3a 0x3a 0x63 0x6f 0x75 0x74 
    0x20 0x3c 0x3c 0x20 0x27 0x5c 0x6e 0x27 0x3b 00xa 0x20 0x20 0x20 0x20 0x7d 00xa 
    0x7d 00xa 
    

    BONUS / NOTES

    There is no need to use istream on streambuf here:

    Live On Coliru

    gReply.commit(boost::asio::buffer_copy(
        gReply.prepare(64),
        boost::asio::buffer(std::string_view("Hello world!"))));
    
    std::cout << std::hex << std::showbase <<  std::setfill('0');
    int col = 0;
    for(auto it = buffers_begin(gReply.data()),
             end = buffers_end(gReply.data());
        it != end;
        ++it)
    {
        unsigned char c = *it;
        std::cout << std::setw(4) << static_cast<int>(c) << ' ';
        if (0 == (++col % 16))
            std::cout << '\n';
    }
    

    Prints

    0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21 
    

    Extra Bonus

    Note that you can use other (dynamic) buffers instead of streambuf making things easier for this kind of use case:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <iomanip>
    #include <iostream>
    
    int main()
    {
        std::vector<unsigned char> reply;
        auto rbuf = boost::asio::dynamic_buffer(reply);
    
        rbuf.commit(boost::asio::buffer_copy(
            rbuf.prepare(64),
            boost::asio::buffer(std::string_view("Hello world!"))));
    
        std::cout << std::hex << std::showbase <<  std::setfill('0');
    
        for(int col = 0; int ic : reply)
            std::cout << std::setw(4) << ic << (++col % 16 ? ' ' : '\n');
    }
    

    Prints, again:

    0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21