class SubnetCalc
Attributes
octets[R]
to_h[R]
Public Class Methods
new(inputs={})
click to toggle source
# File lib/subnet_calc.rb, line 27 def initialize(inputs={}) @inputs = inputs default_inputs = {hosts: nil, ip: nil, prefix: nil}.merge(inputs) # Using the input(s) supplied: hosts, prefix = %i(hosts prefix).map {|x| default_inputs[x]} @prefixes = 1.upto(32).each_slice(8).to_a =begin #=> [ [1, 2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23, 24], [25, 26, 27, 28, 29, 30, 31, 32] ] =end octets = @prefixes.map.with_index do |octet, j| a = octet.map.with_index do |prefix, i| decimal = 2 ** (octet.length - 1 - i ) h = { prefix: prefix, decimal: decimal, hosts_per_subnet: (2 ** 8) ** (@prefixes.length - 1 - j) * decimal } OpenStruct.new h end OpenStruct.new mask: nil, bits: a end @octets = octets # ------------------------------------ octet_n, bit_n, class_type = if hosts then hosts_per_subnet = octets.flat_map.with_index do |octet,i| octet.bits.map.with_index {|y,j| [i, j, y.hosts_per_subnet] } end # find the smallest decimal value to match the # required number of hosts on a network *r, _ = hosts_per_subnet.reverse.detect {|x| x.last > hosts + 1} network = case hosts when 1..254 'c' when 255..65534 'b' else 'a' end (r + [network]) elsif prefix prefixes = @prefixes.flat_map.with_index do |octet,i| octet.map.with_index {|x,j| [i, j, x]} end *r, _ = prefixes.detect {|x| x.last == prefix} network = case prefix when 24..32 'c' when 16..23 'b' else 'a' end (r + [network]) end # Identify the network bits and the host bits classes = ('a'..'d') # identify the initial network bits for a class *a,b or c* class_n = (classes.to_a.index(class_type) + 1) network_bits = class_n.times.map {|x| Array.new(8, 1)} host_bits = (classes.to_a.length - class_n).times.map {|x| Array.new(8, 0)} address_bits = network_bits + host_bits # add the mask to each octet octets.each.with_index do |octet, i| octet.mask = address_bits[i].join.to_i(2) end bit = octets[octet_n].bits[bit_n] magic_number, hosts_per_subnet, prefix = bit.decimal, bit.hosts_per_subnet, bit.prefix # add the new mask to the octet octets[octet_n].mask = octets[octet_n].bits.map(&:decimal)[0..bit_n].inject(:+) subnet_mask = octets.map(&:mask).join('.') subnet_bits = (subnet_mask.split('.')[class_n]).to_i.to_s(2).count("1") no_of_subnets = segments = 2 ** (subnet_bits) subnets = case class_type when 'c' class_subnets(segments, hosts_per_subnet) when 'b' class_b_subnets(256 / segments, bit.decimal) when 'a' class_a_subnets(256 ** 2 / segments, bit.decimal) end default_inputs[:ip] ||= ['10.0.0.0', '172.16.0.0','192.166.0.0'][class_n-1] ip = (default_inputs[:ip] + ' ') .split('.')[0..class_n-1] first_ip = (ip + [subnets.first.first]).join('.') last_ip = (ip + [subnets.first.last]).join('.') result = { class_type: class_type.upcase, magic_number: magic_number, hosts: hosts_per_subnet - 2, subnet_mask: subnet_mask, subnet_bitmask: subnet_mask.split('.').map {|x| "%08d" % x.to_i.to_s(2)}, prefix: prefix, subnets: subnets, range: "%s-%s" % [first_ip, last_ip], subnet_bits: subnet_bits, max_subnets: 2 ** (subnet_bits) } @octet_n = octet_n @h = result end
Public Instance Methods
to_s()
click to toggle source
# File lib/subnet_calc.rb, line 185 def to_s() tfo = TableFormatter.new tfo.source = @h[:subnets].map.with_index do |x,i| ([i+1] + x.to_h.values).map(&:to_s) end tfo.labels = %w(index: Network: 1st: last: broadcast:) full_subnets_table = tfo.display(markdown: true).to_s subnets_table = if full_subnets_table.lines.length > 14 then (full_subnets_table.lines[0..13] + ["\n ... "]).join else full_subnets_table end # octet broken down tfo2 = TableFormatter.new prefixes = @prefixes[@octet_n].map {|x| '/' + x.to_s} tfo2.source = [@h[:subnet_bitmask][@octet_n].chars, prefixes] tfo2.labels = 8.times.map {|n| (2 ** n).to_s + ':' }.reverse octet_table = tfo2.display(markdown: true).to_s <<EOF Subnet calculator ================= Inputs: #{indent Kvx.new(@inputs).to_s} Summary ------- * Network class: #{@h[:class_type]} * magic number: #{@h[:magic_number]} * hosts per subnet: #{@h[:hosts]} * subnet mask: #{@h[:subnet_mask]} * subnet bitmask: #{@h[:subnet_bitmask].join('.')} * prefix bit-length: #{@h[:prefix]} * range: #{@h[:range]} * subnet_bits: #{@h[:subnet_bits]} * maximum subnets: #{@h[:max_subnets]} Breakdown --------- #{(@octet_n + 1).ordinal} octet: #{indent octet_table} ### Subnets #{indent subnets_table} ----------------------------------------------- EOF end
Private Instance Methods
class_a_subnets(n, block_size)
click to toggle source
# File lib/subnet_calc.rb, line 299 def class_a_subnets(n, block_size) class_subnets(n, block_size) do |network, first, last, broadcast| { network: [network, 0, 0].join('.'), first: [network, 1, 1].join('.'), last: [broadcast, 255, 254].join('.'), broadcast: [broadcast, 255, 255].join('.') } end end
class_b_subnets(n, block_size)
click to toggle source
# File lib/subnet_calc.rb, line 284 def class_b_subnets(n, block_size) class_subnets(n, block_size) do |network, first, last, broadcast| { network: [network, 0].join('.'), first: [network, 1].join('.'), last: [broadcast, 254].join('.'), broadcast: [broadcast, 255].join('.') } end end
class_subnets(n, block_size) { |i,first,last,broadcast| ... }
click to toggle source
# File lib/subnet_calc.rb, line 261 def class_subnets(n, block_size) i = 0 subnets = n.times.inject([]) do |r,n| broadcast = i + block_size - 1 first = i + 1 last = broadcast - 1 h = if block_given? then yield(i,first,last,broadcast) else { network: i, first: first, last: last, broadcast: broadcast } end i += block_size r << OpenStruct.new(h) end end
indent(s, i=2)
click to toggle source
# File lib/subnet_calc.rb, line 314 def indent(s, i=2) s.lines.map{|x| ' ' * i + x}.join end