Created
March 11, 2023 04:21
-
-
Save ch1ago/8a1ca4bf460a2ed7ac184716e18ca9dc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'socket' | |
class MyIcmpSocket | |
ICMP_ECHO_REQUEST_TYPE = 8 | |
ICMP_ECHO_REQUEST_CODE = 0 | |
ICMP_HEADER_SIZE = 8 | |
def initialize | |
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP) | |
end | |
def ping(host) | |
icmp_id = Process.pid & 0xffff | |
icmp_seq = 0 | |
icmp_data = "ping #{host} packet" | |
# Construct ICMP echo request packet | |
icmp_header = [ICMP_ECHO_REQUEST_TYPE, ICMP_ECHO_REQUEST_CODE, 0, icmp_id, icmp_seq].pack('CCnS>S>') | |
icmp_checksum = calc_checksum(icmp_header + icmp_data) | |
icmp_packet = [ICMP_ECHO_REQUEST_TYPE, ICMP_ECHO_REQUEST_CODE, icmp_checksum, icmp_id, icmp_seq, icmp_data].pack('CCnS>S>a*') | |
# Send ICMP echo request packet and receive response | |
sockaddr = Socket.sockaddr_in(0, host) | |
start_time = Time.now | |
@socket.send(icmp_packet, 0, sockaddr) | |
response_packet, sockaddr = @socket.recvfrom(1024) | |
end_time = Time.now | |
# Parse ICMP echo response packet | |
response_header = response_packet[0, ICMP_HEADER_SIZE] | |
response_type, response_code, response_checksum, response_id, response_seq = response_header.unpack('CCnS>S>') | |
raise "Invalid ICMP echo response packet" unless response_type == 0 && response_code == 0 && response_id == icmp_id && response_seq == icmp_seq | |
round_trip_time = (end_time - start_time) * 1000 | |
# Return round-trip time | |
round_trip_time | |
end | |
private | |
def calc_checksum(data) | |
sum = 0 | |
data.scan(/.{2}/m).map { |word| sum += word.unpack('n')[0] } | |
sum = (sum >> 16) + (sum & 0xffff) | |
sum += sum >> 16 | |
~sum & 0xffff | |
end | |
end | |
# This code creates a raw socket using Socket, which allows it to send and | |
# receive ICMP packets directly. The ping method constructs an ICMP echo | |
# request packet, sends it to the specified host, and receives the response. | |
# The round-trip time is then calculated and returned. The calc_checksum | |
# method is used to calculate the checksum for the ICMP packet. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment