Skip to content

Instantly share code, notes, and snippets.

@gangelo
Last active January 7, 2022 00:17
Show Gist options
  • Select an option

  • Save gangelo/d215f9e7b51a3dc3c9a72191916bd9f4 to your computer and use it in GitHub Desktop.

Select an option

Save gangelo/d215f9e7b51a3dc3c9a72191916bd9f4 to your computer and use it in GitHub Desktop.
Hacking
# Examples:
# Hacking::Networking.network_info_for(ip: '192.168.33.12', mask: '255.255.224.0')
# => {:ip=>[192, 168, 33, 12], :mask=>[255, 255, 224, 0], :cidr_info=>{:cidr=>13, :network=>"192.168.32.0", :cidr_notation=>"192.168.32.0/13"}, :network=>"192.168.32.0", :host=>"0.0.1.12", :total_hosts=>8192}
# Hacking::Networking.network_for(ip: '192.168.33.12', mask: '255.255.224.0') # => "192.168.32.0"
# Hacking::Networking.host_for(ip: '192.168.33.12', mask: '255.255.224.0') # => "0.0.1.12"
# Hacking::Networking.total_hosts_for(mask: '255.255.224.0') # => 8192
# Hacking::Networking.to_binary('192.168.33.12') # => "11000000.10101000.00100001.00001100"
# Hacking::Networking.to_binary('255.255.224.0') # => "11111111.11111111.11100000.00000000"
module Hacking
module Networking
module_function
def network_info_for(ip:, mask:)
ip = octets_for(ip) unless octets?(ip)
mask = octets_for(mask) unless octets?(mask)
{
ip: ip,
mask: mask,
cidr_info: cidr_for(ip: ip, mask: mask),
network: network_for(ip: ip, mask: mask),
host: host_for(ip: ip, mask: mask),
total_hosts: total_hosts_for(mask: mask),
}
end
# Returns the network ip address (as a string) for the given ip address and mask.
def network_for(ip:, mask:)
ip = octets_for(ip) unless octets?(ip)
mask = octets_for(mask) unless octets?(mask)
network_part_octets = []
ip.each_with_index do |octet, index|
network_part_octets << (octet & mask[index])
end
join_octets(network_part_octets)
end
# Returns the host ip address (as a string) for the given ip address and mask.
def host_for(ip:, mask:)
ip = octets_for(ip) unless octets?(ip)
mask = octets_for(mask) unless octets?(mask)
mask = invert(join_octets(mask))
host_octets = []
ip.each_with_index do |octet, index|
host_octets << (octet & mask[index])
end
join_octets(host_octets)
end
# Returns the maximum number of host addresses this network can support.
def total_hosts_for(mask:)
mask = join_octets(mask) if octets?(mask)
2 ** bits_on_for(mask: mask)
end
# Returns the cidr notation given the mask.
def cidr_for(ip:, mask:)
ip = octets_for(ip) unless octets?(ip)
mask = octets_for(mask) unless octets?(mask)
cidr = bits_on_for(mask: join_octets(mask))
network = network_for(ip: ip, mask: mask)
{
cidr: cidr,
network: network,
cidr_notation: "#{network}/#{cidr}",
}
end
# Takes an ip address or mask and converts it to binary ip notation.
# If invert is true, the result will be inverted.
def to_binary(ip)
octets = octets_for(ip).each.map { |octet| '%0*b' % [8, octet] }
join_octets(octets)
end
# Takes an ip address or mask string, and returns the octets in an Array.
def octets_for(ip)
ip.split('.').map do |octet|
octet = octet.to_i
octet = yield octet if block_given?
octet
end
end
# Expects a Fixnum and returns the octet with the bits flipped.
def flip_bits(octet)
octet ^ 0xff
end
# Takes an ip address or mask, inverts it, and returns an Array of octets.
def invert(ip)
octets_for(ip) { |octet| flip_bits(octet) }
end
# Returns the total number of bits on for this mask; mask is inverted prior to counting tbe
# number of bits. No consideration is taken into account for validity of the mask.
def bits_on_for(mask:)
raise "Argument mask (#{mask}) must respond_to? :split" unless mask.respond_to?(:split)
inverted_mask = join_octets(invert(mask))
to_binary(inverted_mask).count('1')
end
# Returns true if object is an Array, assuming it is an Array of octets (integers).
def octets?(object)
return false if object.nil?
object.is_a?(Array)
end
# Joins the Array of octets and returns an ip address or mask (e.g. "192.168.1.1").
def join_octets(octets)
raise "Argument octets (#{octets}) does not respond_to? :join" unless octets.respond_to?(:join)
octets.join('.')
end
private_class_method :invert, :bits_on_for, :octets?, :join_octets
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment