def subnet(options=nil)
known_args = [:Bits, :IPCount, :NumSubnets, :Objectify, :Short]
my_network = self.to_i(:network)
my_mask = self.bits
subnet_bits = my_mask + 1
min_count = nil
objectify = false
short = false
if (options)
if (!options.kind_of? Hash)
raise ArgumentError, "Expected Hash, but #{options.class} provided."
end
NetAddr.validate_args(options.keys,known_args)
if ( options.has_key?(:IPCount) )
subnet_bits = NetAddr.ip_count_to_size(options[:IPCount], @version)
end
if ( options.has_key?(:Bits) )
subnet_bits = options[:Bits]
end
if ( options.has_key?(:NumSubnets) )
num_subnets = options[:NumSubnets]
end
if( options.has_key?(:Short) && options[:Short] == true )
short = true
end
if( options.has_key?(:Objectify) && options[:Objectify] == true )
objectify = true
end
end
num_avail = 2**(subnet_bits - my_mask)
bits_needed = 1
num_subnets = num_avail if (!num_subnets)
until (2**bits_needed >= num_subnets)
bits_needed += 1
end
num_subnets = 2**bits_needed
next_supernet_bits = subnet_bits - bits_needed
if (subnet_bits > @address_len)
raise BoundaryError, "Requested subnet (#{subnet_bits}) does not fit " +
"within the bounds of IPv#{@version}."
end
if (subnet_bits < my_mask)
raise BoundaryError, "Requested subnet (#{subnet_bits}) is too large for " +
"current CIDR space."
end
if (num_subnets > num_avail)
raise "Requested subnet count (#{num_subnets}) exceeds subnets " +
"available for allocation (#{num_avail})."
end
bitstep = 2**(@address_len - subnet_bits)
subnets = self.enumerate(:Bitstep => bitstep, :Limit => num_subnets, :Objectify => true)
new_subnets = []
subnets.each do |subnet|
if (!objectify)
if (short && @version == 6)
new_subnets.push("#{subnet.network(:Short => true)}/#{subnet_bits}")
else
new_subnets.push("#{subnet.network}/#{subnet_bits}")
end
else
new_subnets.push( NetAddr.cidr_build(@version, subnet.to_i(:network), NetAddr.bits_to_mask(subnet_bits,version) ) )
end
end
next_supernet_bitstep = (bitstep * num_subnets)
next_supernet_ip = my_network + next_supernet_bitstep
until (next_supernet_bits == my_mask)
if (!objectify)
next_network = NetAddr.ip_int_to_str(next_supernet_ip, @version)
next_network = NetAddr.shorten(next_network) if (short && @version == 6)
new_subnets.push("#{next_network}/#{next_supernet_bits}")
else
new_subnets.push(NetAddr.cidr_build(@version, next_supernet_ip, NetAddr.bits_to_mask(next_supernet_bits,version) ) )
end
next_supernet_bits -= 1
next_supernet_ip = next_supernet_ip + next_supernet_bitstep
next_supernet_bitstep = next_supernet_bitstep << 1
end
return(new_subnets)
end