class SimplePing::ICMP

Constants

TYPE_ICMP_DESTINATION_UNREACHABLE
TYPE_ICMP_ECHO_REPLY

ICMP TYPES

TYPE_ICMP_ECHO_REQUEST
TYPE_ICMP_REDIRECT

Attributes

data[RW]
id[RW]
seq_number[RW]
type[RW]

Public Class Methods

new(type:, code: 0, id: nil, seq_number: nil, data: nil) click to toggle source

constructor

@param code [Integer] 0x01 @param type [Integer] 0x01 @param id [Integer] 0x01 @param seq_number [Integer] 0x01 @param data [String] 0x01

# File lib/simple_ping/icmp.rb, line 18
def initialize(type:, code: 0, id: nil, seq_number: nil, data: nil)
  @type = type
  @code = code
  @id = id || gen_id
  @seq_number = seq_number || gen_seq_number
  @data = data || gen_data
  @checksum = checksum
end

Public Instance Methods

is_type_destination_unreachable?() click to toggle source

@return [Boolean]

# File lib/simple_ping/icmp.rb, line 43
def is_type_destination_unreachable?
  @type == TYPE_ICMP_DESTINATION_UNREACHABLE
end
is_type_echo?() click to toggle source

@return [Boolean]

# File lib/simple_ping/icmp.rb, line 33
def is_type_echo?
  @type == TYPE_ICMP_ECHO_REPLY || @type == TYPE_ICMP_ECHO_REQUEST
end
is_type_echo_reply?() click to toggle source

@return [Boolean]

# File lib/simple_ping/icmp.rb, line 38
def is_type_echo_reply?
  @type == TYPE_ICMP_ECHO_REPLY
end
is_type_redirect?() click to toggle source

@return [Boolean]

# File lib/simple_ping/icmp.rb, line 28
def is_type_redirect?
  @type == TYPE_ICMP_REDIRECT
end
successful_reply?(icmp) click to toggle source

Whether the argument ICMP is a reply of this ICMP

@param [ICMP] @return [Boolean]

# File lib/simple_ping/icmp.rb, line 51
def successful_reply?(icmp)
  icmp.id == @id && icmp.seq_number == @seq_number && icmp.is_type_echo_reply?
end
to_trans_data() click to toggle source

Return the data format for sending with the Socket::send method

@return [String]

# File lib/simple_ping/icmp.rb, line 58
def to_trans_data
  bynary_data =
    @type.to_s(2).rjust(8, "0") +
    @code.to_s(2).rjust(8, "0") +
    @checksum.to_s(2).rjust(16, "0") +
    @id.to_s(2).rjust(16, "0") +
    @seq_number.to_s(2).rjust(16, "0")

  data_byte_arr = bynary_data.scan(/.{1,8}/)
  data_byte_arr.map! { |byte| byte.to_i(2).chr } # TO ASCII
  data_byte_arr.join + @data
end

Private Instance Methods

carry_up(num) click to toggle source

Calculate carry in 16bit memo: qiita.com/kure/items/fa7e665c2259375d9a81

@param num [String] ex: “11001100110100011” @return [Integer]

# File lib/simple_ping/icmp.rb, line 78
def carry_up(num)
  carry_up_num = num.length - 16
  original_value = num[carry_up_num, 16]
  carry_up_value = num[0, carry_up_num]
  sum = original_value.to_i(2) + carry_up_value&.to_i(2)
  sum ^ 0xffff
end
checksum() click to toggle source

return checksum value Calculate 1's complement sum for each 16 bits memo: qiita.com/kure/items/fa7e665c2259375d9a81

@return [Integer]

# File lib/simple_ping/icmp.rb, line 91
def checksum
  # Divide into 16 bits
  # ex: ["pi", "ng"]
  data_arr = @data.scan(/.{1,2}/)
  # Calculate each ASCII code
  # ex: [28777, 28263]
  data_arr_int = data_arr.map do |data|
    (data.bytes[0] << 8) + (data.bytes[1].nil? ? 0 : data.bytes[1])
  end
  data_sum = data_arr_int.sum

  sum_with_16bit = (@type << 8 + @code) + @id + @seq_number + data_sum

  # calculate carry
  carry_up(sum_with_16bit.to_s(2).rjust(16, "0"))
end
gen_data() click to toggle source

generate data

TODO: random @return [String]

# File lib/simple_ping/icmp.rb, line 112
def gen_data
  "abcd"
end
gen_id() click to toggle source

generate ID

TODO: random @return [Integer]

# File lib/simple_ping/icmp.rb, line 120
def gen_id
  0x01
end
gen_seq_number() click to toggle source

generate sequence number

TODO: random @return [Integer]

# File lib/simple_ping/icmp.rb, line 128
def gen_seq_number
  0x00af
end