Advertisement
Guest User

Untitled

a guest
Nov 11th, 2019
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.21 KB | None | 0 0
  1. #include <iostream>
  2. #include <thread>
  3. #include <dnet.h>
  4. #include <cstring>
  5. #include <bits/socket.h>
  6. #include <unistd.h>
  7.  
  8. struct icmp_packet;
  9.  
  10. uint16_t checksum(const icmp_packet *packet);
  11.  
  12. struct icmp_packet {
  13.     icmp_hdr header{};
  14.     uint16_t id = getpid();
  15.     uint16_t seq = 0;
  16.     char msg[56]{};
  17.  
  18.     explicit icmp_packet(const char *msg) {
  19.         header.icmp_type = ICMP_ECHO;
  20.         header.icmp_code = 0;
  21.         strncpy(this->msg, msg, 55);
  22.         update();
  23.     }
  24.  
  25.     inline void update() {
  26.         header.icmp_cksum = 0; // Important: we need to clear previous checksum before calculating a new one
  27.         header.icmp_cksum = checksum(this);
  28.     }
  29. };
  30.  
  31. uint16_t checksum(const icmp_packet *packet) {
  32.     int len = sizeof(*packet);
  33.     auto *current = reinterpret_cast<const uint16_t *>(packet);
  34.     uint32_t sum = 0;
  35.     while (len > 1) {
  36.         len -= 2;
  37.         sum += *current++;
  38.     }
  39.     if (len == 1)
  40.         sum += *reinterpret_cast<const uint8_t *>(current);
  41.     sum = (sum >> 16u) + (sum & 0xFFFFu);
  42.     sum += sum >> 16u;
  43.     return ~sum;
  44. }
  45.  
  46. char *dns_lookup(const char *hostname, sockaddr_in &addr, bool &is_ipv6) {
  47.     static char ip[INET6_ADDRSTRLEN];
  48.     static addrinfo hint{}, *res = nullptr;
  49.     hint.ai_family = PF_UNSPEC;
  50.     hint.ai_flags = AI_ALL;
  51.  
  52.     if (getaddrinfo(hostname, nullptr, &hint, &res)) {
  53.         std::cerr << "Invalid address" << std::endl;
  54.         return nullptr;
  55.     }
  56.     is_ipv6 = res->ai_family == AF_INET6;
  57.     memcpy(&addr, res->ai_addr, sizeof(addr));
  58.     inet_ntop(res->ai_family, &addr.sin_addr, ip, res->ai_addrlen);
  59.     return ip;
  60. }
  61.  
  62. void send_request(int sock_fd, const sockaddr_in &addr, const char *ip_addr, bool is_ipv6 = false) {
  63.     icmp_packet packet("echo request");
  64.     icmp_packet buffer("echo reply");
  65.     sockaddr r_addr{};
  66.     int cnt = 4;
  67.     while (cnt--) {
  68.         if (sendto(sock_fd, &packet, sizeof(packet), 0,
  69.                    reinterpret_cast<const struct sockaddr *>(&addr), sizeof(addr)) < 1) {
  70.             std::cerr << "Failed to send packet" << std::endl;
  71.             continue;
  72.         }
  73.         socklen_t r_len = 0;
  74.         recvfrom(sock_fd, &buffer, sizeof(buffer), 0, &r_addr, &r_len);
  75.         if (buffer.header.icmp_type != 69 || buffer.header.icmp_code) {
  76.             std::cout << "Broken packet" << std::endl;
  77.             continue;
  78.         }
  79.         ++packet.seq;
  80.         packet.update();
  81.         using namespace std::chrono_literals;
  82.         std::this_thread::sleep_for(500ms);
  83.     }
  84.  
  85. }
  86.  
  87. int main(int argc, char **argv) {
  88.     if (argc < 2) {
  89.         std::cout << "Usage: " << argv[0] << " " << "(hostname|ip address)" << std::endl;
  90.         return 1;
  91.     }
  92.     bool is_ipv6 = false;
  93.     sockaddr_in addr{};
  94.     char *ip = dns_lookup(argv[1], addr, is_ipv6);
  95.     puts(ip);
  96.     int sock_fd = socket(is_ipv6 ? AF_INET6 : AF_INET, SOCK_RAW, is_ipv6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP);
  97.     if (sock_fd < 0) {
  98.         std::cerr << "Cannot open socket fd\n" << "Consider running with sudo" << std::endl;
  99.         return sock_fd;
  100.     }
  101.     int ttl = 64;
  102.     setsockopt(sock_fd, is_ipv6 ? SOL_IPV6 : SOL_IP, IP_TTL, &ttl, sizeof(ttl));
  103.     send_request(sock_fd, addr, ip, is_ipv6);
  104.     return 0;
  105. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement