Skip to content

Instantly share code, notes, and snippets.

@flou
Created June 19, 2015 19:52
Show Gist options
  • Save flou/eff349acffbe93060327 to your computer and use it in GitHub Desktop.
Save flou/eff349acffbe93060327 to your computer and use it in GitHub Desktop.
class Network
# Create a new network
# @param address [String] the address of the network formatted as
# "10.0.0.0/16" or "10.0.0.0/255.255.255.0"
def initialize(address)
@address = address
@ip = to_binary(address.split("/")[0])
@mask = to_binary(address.split("/")[1])
end
# Returns the mask for the network in binary form
# @param format [Boolean] add dots (.) between bit groups
# @return [String] network mask in binary form
def mask(format: false)
format ? self.class.pretty_print_address(@mask) : @mask
end
# Returns the IP for the network in binary form
# @param format [Boolean] add dots (.) between bit groups
# @return [String] network IP in binary form
def ip(format: false)
format ? self.class.pretty_print_address(@ip) : @ip
end
# Returns the number of possible addresses in the network
# @return [Integer] Number of possible addresses in the network
def available_addresses
network = machine_part(mask, ip)
2 ** network.length
end
def self.mask_to_binary(mask = "/16", format: false)
mask.gsub!(/\//, "") if mask.start_with?("/")
bin = ("1" * mask.to_i).ljust(32, "0")
format ? pretty_print_address(bin) : bin
end
def self.mask_to_decimal(mask = "/16", format: false)
mask = mask_to_binary(mask, format: true)
# mask.gsub!(/\//, "") if mask.start_with?("/")
bin = mask.split(".").map { |c| c.to_i(2) }
format ? pretty_print_address(bin) : bin
end
def self.mask_for_addresses_required(addresses_needed)
puts addresses_needed
Math.log(next_power_of_two(addresses_needed), 2).round(0)
end
private
def to_binary(address)
if address.include?(".")
address.split(".").map { |c| format("%08B", c) }.join
else
("1" * address.to_i).ljust(32, "0")
end
end
def machine_part(mask = self.mask, ip = self.ip)
length = mask.scan(/0+$/).first.size
ip.chars.last(length).join
end
def self.pretty_print_address(addr)
addr.gsub(/.{8}(?=.)/, '\0.')
end
def self.next_power_of_two(i)
return 1 if i <= 0
val = i
val -= 1
val = (val >> 1) | val
val = (val >> 2) | val
val = (val >> 4) | val
val = (val >> 8) | val
val = (val >> 16) | val
val = (val >> 32) | val if i.class == Bignum
val + 1
end
end
net = Network.new("192.168.0.255/16")
formatted = { format: true }
puts "Mask: #{net.mask(formatted)}"
puts "IP: #{net.ip(formatted)}"
# puts "#{net.available_addresses} addresses"
# puts Network.mask_to_binary("/16", formatted)
p = Network.mask_for_addresses_required(63)
# puts Network.mask_to_binary("/#{32 - p}", formatted)
# puts Network.mask_to_decimal("/#{32 - p}", formatted)
puts Network.mask_to_binary("/#{32 - p}", formatted).split(".").map { |c| c.to_i(2) }.join(".")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment