Skip to content

Instantly share code, notes, and snippets.

@yantene
Last active March 21, 2020 15:35
Show Gist options
  • Save yantene/7be11d07ea60feb5e29d to your computer and use it in GitHub Desktop.
Save yantene/7be11d07ea60feb5e29d to your computer and use it in GitHub Desktop.
Ruby で ping を行うプログラムです. 嘘つきました.応答の受信機能はありません.
require 'socket'
class ICMPEchoMessage
TYPE = 0x08
CODE = 0x00
def initialize(id = rand(0..0xffff))
@id = id.freeze
@seq = 0x0000
@socket = Socket.open(
Socket::PF_INET, # IPv4
Socket::SOCK_RAW, # RAW Socket
Socket::IPPROTO_ICMP # ICMP
)
end
def send(dest_host, data)
dest = Socket.sockaddr_in(nil, dest_host)
@socket.send(packet_data(@seq += 1, data).pack('C*'), 0, dest)
end
private
def packet_data(seq, data, csum = checksum(seq, data))
[TYPE, CODE] +
to_bytes(csum, 2) +
to_bytes(@id, 2) +
to_bytes(seq, 2) +
data
end
# calcurate checksum
def checksum(seq, data)
to_bytes(
packet_data(seq, data, 0).each_slice(2).inject(0) do |m, i|
m + to_num((i << 0)[0, 2])
end
).each_slice(2).to_a.reverse.inject(0) do |m, i|
m + to_num(i.reverse)
end ^ 0xffff
end
# Fixnum to byte array
def to_bytes(num, size = (num.bit_length / 8.0).ceil)
Array.new(size) do |i|
(num >> (i * 8)) & 0xff
end.reverse
end
# Byte array to fixnum
def to_num(bytes)
bytes.inject { |m, i| (m << 8) + i }
end
end
require './icmp_echo_message'
# 送信先ホスト
host = ARGV[0]
# 送信間隔 [ms]
sleep = ARGV[1] || 1000
# エポック秒を逆順のバイト配列にしたもの
timestamp = -> do
now = Time.now.to_i
Array.new(8) { |i| (now >> (i * 8)) & 0xff }
end.call
ping = ICMPEchoMessage.new
loop do
ping.send(host, timestamp)
sleep sleep / 1000.0
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment