class Subnet::IPv4
- Subnet::IPv4
- Reference
- Object
Overview
Class Subnet::IPv4
is used to handle IPv4 type addresses.
Included Modules
- Comparable(Subnet)
- Enumerable(Subnet::IPv4)
- Subnet
Defined in:
subnet/ipv4.crConstant Summary
-
CLASSFUL =
{/^0../ => 8, /^10./ => 16, /^110/ => 24}
-
This Hash contains the prefix values for Classful networks
Note: classes C, D and E will all have a default prefix of /24 or 255.255.255.0
-
IPV4REGEX =
/((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)/
-
Regular expression to match an IPv4 address
Constructors
-
.new(str : String)
Creates a new IPv4 address object.
- .new(value : JSON::PullParser) : Subnet::IPv4
Class Method Summary
-
.extract(str)
Extract an IPv4 address from a string and returns a new object
-
.parse_classful(ip)
Creates a new IPv4 address object by parsing the address in a classful way.
-
.parse_data(bytes, prefix = 32)
Creates a new IPv4 object from binary data, like the one you get from a network stream.
-
.parse_u32(u32, prefix = 32)
Creates a new IPv4 object from an unsigned 32bits integer.
-
.summarize(args)
Summarization (or aggregation) is the process when two or more networks are taken together to check if a supernet, including all and only these networks, exists.
-
.summarize(*args)
ditto
Instance Method Summary
-
#+(oth)
Returns a new IPv4 object which is the result of the summarization, if possible, of the two objects
-
#-(oth)
Returns the difference between two IP addresses in unsigned int 32 bits format
-
#/(subnets)
ditto
-
#<=>(oth)
Spaceship operator to compare IPv4 objects
-
#[](index)
Returns the octet specified by index
-
#[]=(index, value)
Updated the octet specified at index
-
#a?
Checks whether the ip address belongs to a RFC 791 CLASS A network, no matter what the subnet mask is.
-
#address : String
Returns the address portion of the IPv4 object as a string.
-
#allocate(skip = 0)
Allocates a new ip from the current subnet.
-
#arpa
ditto
-
#b?
Checks whether the ip address belongs to a RFC 791 CLASS B network, no matter what the subnet mask is.
-
#bits
Returns the address portion of an IP in binary format, as a string containing a sequence of 0 and 1
-
#broadcast
Returns the broadcast address for the given IP.
-
#broadcast_u32
Returns the broadcast address in Unsigned 32bits format
-
#c?
Checks whether the ip address belongs to a RFC 791 CLASS C network, no matter what the subnet mask is.
-
#data
Returns the address portion of an IPv4 object in a network byte order format.
-
#each(&)
Iterates over all the IP addresses for the given network (or IP address).
-
#each_host(&)
Iterates over all the hosts IP addresses for the given network (or IP address).
-
#first
Returns a new IPv4 object with the first host IP address in the range.
-
#hexstring
Returns the address portion in hex
-
#hosts
Returns an array with the IP addresses of all the hosts in the network.
-
#includes?(oth : IPv4)
Checks whether a subnet includes the given IP address.
-
#includes_all?(others)
Checks whether a subnet includes all the given IPv4 objects.
-
#includes_all?(*others)
ditto
-
#last
Like its sibling method IPv4#first, this method returns a new IPv4 object with the last host IP address in the range.
-
#link_local?
Checks if an IPv4 address objects belongs to a link-local network RFC3927
-
#loopback?
Checks if an IPv4 address objects belongs to a loopback network RFC1122
-
#multicast?
Checks if an IPv4 address objects belongs to a multicast network RFC3171
-
#netmask
Returns the prefix as a string in IP format
-
#netmask=(addr)
Like
IPv4#prefix=
, this method allow you to change the prefix / netmask of an IP address object. -
#network
Returns a new IPv4 object with the network number for the given IP.
-
#network?
Checks if the IP address is actually a network
-
#network_u32
Returns the network number in Unsigned 32bits format
-
#octet(index)
ditto
-
#octets : Array(Int32)
Returns the address as an array of decimal values
-
#pred
Returns the predecessor to the IP address
-
#prefix : Prefix32
Returns the prefix portion of the IPv4 object as a Subnet::Prefix32 object
-
#prefix=(num)
Set a new prefix number for the object
-
#private?
Checks if an IPv4 address objects belongs to a private network RFC1918
-
#reverse
Returns the IP address in in-addr.arpa format for DNS lookups
-
#size
Returns the number of IP addresses included in the network.
-
#split(subnets = 2)
Splits a network into different subnets
-
#subnet(subprefix)
This method implements the subnetting function similar to the one described in RFC3531.
-
#succ
Returns the successor to the IP address
-
#supernet(new_prefix)
Returns a new IPv4 object from the supernetting of the instance network.
-
#to(e)
Return a list of IP's between @address and the supplied IP
-
#to_i
ditto
-
#to_ipv6
Return the ip address in a format compatible with the IPv6 Mapped IPv4 addresses
- #to_json(json : JSON::Builder)
-
#to_s : String
Returns a string with the address portion of the IPv4 object
-
#to_string
Returns a string with the IP address in canonical form.
-
#to_u32
ditto
-
#u32 : Int64
Returns the address portion in unsigned 32 bits integer format.
Instance methods inherited from module Subnet
ipv4?
ipv4?,
ipv6?
ipv6?,
to_json(json : JSON::Builder)
to_json
Constructor methods inherited from module Subnet
new(value : JSON::PullParser) : Subnet
new,
parse(str) : Subnet
parse
Class methods inherited from module Subnet
deprecate(message = nil)
deprecate,
ntoa(uint)
ntoa,
valid?(addr)
valid?,
valid_ip?(addr)
valid_ip?,
valid_ipv4?(addr)
valid_ipv4?,
valid_ipv4_netmask?(addr)
valid_ipv4_netmask?,
valid_ipv4_subnet?(addr)
valid_ipv4_subnet?,
valid_ipv6?(addr)
valid_ipv6?,
valid_ipv6_subnet?(addr)
valid_ipv6_subnet?
Constructor Detail
Creates a new IPv4 address object.
An IPv4 address can be expressed in any of the following forms:
-
"10.1.1.1/24": ip
#address
and#prefix
. This is the common and suggested way to create an object. -
"10.1.1.1/255.255.255.0": ip
#address
and#netmask
. Although convenient sometimes, this format is less clear than the previous one. -
"10.1.1.1": if the address alone is specified, the prefix will be set as default 32, also known as the host prefix
Examples:
# These two are the same
ip = Subnet::IPv4.new("10.0.0.1/24")
ip = Subnet.parse("10.0.0.1/24")
# These two are the same
Subnet::IPv4.new "10.0.0.1/8"
Subnet::IPv4.new "10.0.0.1/255.0.0.0"
Class Method Detail
Extract an IPv4 address from a string and returns a new object
Example:
str = "foobar172.16.10.1barbaz"
ip = Subnet::IPv4.extract str
ip.to_s
# => "172.16.10.1"
Creates a new IPv4 address object by parsing the address in a classful way.
Classful addresses have a fixed netmask based on the class they belong to:
- Class A, from 0.0.0.0 to 127.255.255.255
- Class B, from 128.0.0.0 to 191.255.255.255
- Class C, D and E, from 192.0.0.0 to 255.255.255.254
Example:
ip = Subnet::IPv4.parse_classful "10.0.0.1"
ip.netmask
# => "255.0.0.0"
ip.a?
# => true
Note that classes C, D and E will all have a default prefix of /24 or 255.255.255.0
Creates a new IPv4 object from binary data, like the one you get from a network stream.
For example, on a network stream the IP 172.16.0.1
is represented with the binary Bytes[172, 16, 10, 1]
.
ip = Subnet::IPv4.parse_data Bytes[172, 16, 10, 1]
ip.prefix = 24
ip.to_string
# => "172.16.10.1/24"
Creates a new IPv4 object from an unsigned 32bits integer.
ip = Subnet::IPv4.parse_u32(167772160)
ip.prefix = 8
ip.to_string
# => "10.0.0.0/8"
The #prefix
parameter is optional:
ip = Subnet::IPv4.parse_u32(167772160, 8)
ip.to_string
# => "10.0.0.0/8"
Summarization (or aggregation) is the process when two or more networks are taken together to check if a supernet, including all and only these networks, exists. If it exists then this supernet is called the summarized (or aggregated) network.
It is very important to understand that summarization can only occur if there are no holes in the aggregated network, or, in other words, if the given networks fill completely the address space of the supernet. So the two rules are:
- The aggregate network must contain +all+ the IP addresses of the original networks;
- The aggregate network must contain +only+ the IP addresses of the original networks;
A few examples will help clarify the above. Let's consider for instance the following two networks:
ip1 = Subnet.parse("172.16.10.0/24")
ip2 = Subnet.parse("172.16.11.0/24")
These two networks can be expressed using only one IP address network if we change the prefix. Let Ruby do the work:
Subnet::IPv4.summarize(ip1, ip2).to_s
# => "172.16.10.0/23"
We note how the network "172.16.10.0/23" includes all the addresses specified in the above networks, and (more important) includes ONLY those addresses.
If we summarized ip1
and ip2
with the following network:
"172.16.0.0/16"
we would have satisfied rule #1 above, but not rule #2. So "172.16.0.0/16"
is not an aggregate network for ip1
and ip2
.
If it's not possible to compute a single aggregated network for all the original networks, the method returns an array with all the aggregate networks found. For example, the following four networks can be aggregated in a single /22:
ip1 = Subnet.parse("10.0.0.1/24")
ip2 = Subnet.parse("10.0.1.1/24")
ip3 = Subnet.parse("10.0.2.1/24")
ip4 = Subnet.parse("10.0.3.1/24")
Subnet::IPv4.summarize(ip1, ip2, ip3, ip4).to_string
# => ["10.0.0.0/22"]
But the following networks can't be summarized in a single network:
ip1 = Subnet.parse("10.0.1.1/24")
ip2 = Subnet.parse("10.0.2.1/24")
ip3 = Subnet.parse("10.0.3.1/24")
ip4 = Subnet.parse("10.0.4.1/24")
Subnet::IPv4.summarize(ip1, ip2, ip3, ip4).map { |i| i.to_string }
# => ["10.0.1.0/24","10.0.2.0/23","10.0.4.0/24"]
Instance Method Detail
Returns a new IPv4 object which is the result of the summarization, if possible, of the two objects
Example:
ip1 = Subnet.parse("172.16.10.1/24")
ip2 = Subnet.parse("172.16.11.2/24")
p (ip1 + ip2).map { |i| i.to_string }
# => ["172.16.10.0/23"]
If the networks are not contiguous, returns the two network numbers from the objects
ip1 = Subnet.parse("10.0.0.1/24")
ip2 = Subnet.parse("10.0.2.1/24")
p (ip1 + ip2).map { |i| i.to_string }
# => ["10.0.0.0/24","10.0.2.0/24"]
Returns the difference between two IP addresses in unsigned int 32 bits format
Example:
ip1 = Subnet.parse("172.16.10.0/24")
ip2 = Subnet.parse("172.16.11.0/24")
puts ip1 - ip2
# => 256
Spaceship operator to compare IPv4 objects
Comparing IPv4 addresses is useful to ordinate them into lists that match our intuitive perception of ordered IP addresses.
The first comparison criteria is the u32 value. For example, 10.100.100.1 will be considered to be less than 172.16.0.1, because, in a ordered list, we expect 10.100.100.1 to come before 172.16.0.1.
The second criteria, in case two IPv4 objects have identical addresses, is the prefix. An higher prefix will be considered greater than a lower prefix. This is because we expect to see 10.100.100.0/24 come before 10.100.100.0/25.
Example:
ip1 = Subnet.parse "10.100.100.1/8"
ip2 = Subnet.parse "172.16.0.1/16"
ip3 = Subnet.parse "10.100.100.1/16"
ip1 < ip2
# => true
ip1 > ip3
# => false
[ip1, ip2, ip3].sort.map { |i| i.to_s }
# => ["10.100.100.1/8","10.100.100.1/16","172.16.0.1/16"]
Returns the octet specified by index
ip = Subnet.parse("172.16.100.50/24")
ip[0]
# => 172
ip[1]
# => 16
ip[2]
# => 100
ip[3]
# => 50
Updated the octet specified at index
ip = Subnet.parse("172.16.100.50/24")
ip[2] = 200
# => #<Subnet::IPv4:0x00000000000000 @address="172.16.200.1",
# => @prefix=32, @octets=[172, 16, 200, 1], @u32=2886780929>
Checks whether the ip address belongs to a RFC 791 CLASS A network, no matter what the subnet mask is.
Example:
ip = Subnet.parse("10.0.0.1/24")
ip.a?
# => true
Returns the address portion of the IPv4 object as a string.
ip = Subnet.parse("172.16.100.4/22")
ip.address
# => "172.16.100.4"
Allocates a new ip from the current subnet. Optional skip parameter can be used to skip addresses.
Will return nil
exception when all addresses have been allocated
Example:
ip = Subnet.parse("10.0.0.0/24")
ip.allocate
# => "10.0.0.1/24"
ip.allocate
# => "10.0.0.2/24"
ip.allocate(2)
# => "10.0.0.5/24"
Uses an internal @allocator which tracks the state of allocated addresses.
Checks whether the ip address belongs to a RFC 791 CLASS B network, no matter what the subnet mask is.
Example:
ip = Subnet.parse("172.16.10.1/24")
ip.b?
# => true
Returns the address portion of an IP in binary format, as a string containing a sequence of 0 and 1
ip = Subnet.parse("127.0.0.1")
ip.bits
# => "01111111000000000000000000000001"
Returns the broadcast address for the given IP.
ip = Subnet.parse("172.16.10.64/24")
ip.broadcast.to_s
# => "172.16.10.255"
Returns the broadcast address in Unsigned 32bits format
ip = Subnet.parse("10.0.0.1/29")
ip.broadcast_u32
# => 167772167
Checks whether the ip address belongs to a RFC 791 CLASS C network, no matter what the subnet mask is.
Example:
ip = Subnet.parse("192.168.1.1/30")
ip.c?
# => true
Returns the address portion of an IPv4 object in a network byte order format.
ip = Subnet.parse("172.16.10.1/24")
ip.data
# => "\254\020\n" + "\001"
It is usually used to include an IP address in a data packet to be sent over a socket.
Iterates over all the IP addresses for the given network (or IP address).
The object yielded is a new IPv4 object created from the iteration.
ip = Subnet.parse("10.0.0.1/29")
ip.each do |i|
p i.address
end
# => "10.0.0.0"
# => "10.0.0.1"
# => "10.0.0.2"
# => "10.0.0.3"
# => "10.0.0.4"
# => "10.0.0.5"
# => "10.0.0.6"
# => "10.0.0.7"
Iterates over all the hosts IP addresses for the given network (or IP address).
ip = Subnet.parse("10.0.0.1/29")
ip.each_host do |i|
p i.to_s
end
# => "10.0.0.1"
# => "10.0.0.2"
# => "10.0.0.3"
# => "10.0.0.4"
# => "10.0.0.5"
# => "10.0.0.6"
Returns a new IPv4 object with the first host IP address in the range.
Example: given the 192.168.100.0/24 network, the first host IP address is 192.168.100.1.
ip = Subnet.parse("192.168.100.0/24")
ip.first.to_s
# => "192.168.100.1"
The object IP doesn't need to be a network: the method automatically gets the network number from it
ip = Subnet.parse("192.168.100.50/24")
ip.first.to_s
# => "192.168.100.1"
Returns the address portion in hex
ip = Subnet.parse("10.0.0.0")
ip.hexstring
# => "0a000000"
Returns an array with the IP addresses of all the hosts in the network.
ip = Subnet.parse("10.0.0.1/29")
ip.hosts.map { |i| i.address }
# => ["10.0.0.1",
# => "10.0.0.2",
# => "10.0.0.3",
# => "10.0.0.4",
# => "10.0.0.5",
# => "10.0.0.6"]
Checks whether a subnet includes the given IP address.
Accepts an Subnet.parse::IPv4 object.
ip = Subnet.parse("192.168.10.100/24")
addr = Subnet.parse("192.168.10.102/24")
ip.includes? addr
# => true
ip.includes? Subnet.parse("172.16.0.48/16")
# => false
Checks whether a subnet includes all the given IPv4 objects.
ip = Subnet.parse("192.168.10.100/24")
addr1 = Subnet.parse("192.168.10.102/24")
addr2 = Subnet.parse("192.168.10.103/24")
ip.includes_all?(addr1, addr2)
# => true
Like its sibling method IPv4#first, this method returns a new IPv4 object with the last host IP address in the range.
Example: given the 192.168.100.0/24 network, the last host IP address is 192.168.100.254
ip = Subnet.parse("192.168.100.0/24")
ip.last.to_s
# => "192.168.100.254"
The object IP doesn't need to be a network: the method automatically gets the network number from it
ip = Subnet.parse("192.168.100.50/24")
ip.last.to_s #=> "192.168.100.254"
Checks if an IPv4 address objects belongs to a link-local network RFC3927
Example:
ip = Subnet "169.254.0.1"
ip.link_local?
#=> true
Checks if an IPv4 address objects belongs to a loopback network RFC1122
Example:
ip = Subnet.parse "127.0.0.1"
ip.loopback?
# => true
Checks if an IPv4 address objects belongs to a multicast network RFC3171
Example:
ip = Subnet.parse "224.0.0.0/4"
ip.multicast?
# => true
Returns the prefix as a string in IP format
ip = Subnet.parse("172.16.100.4/22")
ip.netmask
# => "255.255.252.0"
Like IPv4#prefix=
, this method allow you to
change the prefix / netmask of an IP address
object.
ip = Subnet.parse("172.16.100.4")
puts ip
# => 172.16.100.4/16
ip.netmask = "255.255.252.0"
puts ip
# => 172.16.100.4/22
Returns a new IPv4 object with the network number for the given IP.
ip = Subnet.parse("172.16.10.64/24")
ip.network.to_s
# => "172.16.10.0"
Checks if the IP address is actually a network
ip = Subnet.parse("172.16.10.64/24")
ip.network?
# => false
ip = Subnet.parse("172.16.10.64/26")
ip.network?
# => true
Returns the network number in Unsigned 32bits format
ip = Subnet.parse("10.0.0.1/29")
ip.network_u32
# => 167772160
Returns the address as an array of decimal values
ip = Subnet.parse("172.16.100.4")
ip.octets
# => [172, 16, 100, 4]
Returns the predecessor to the IP address
Example:
ip = Subnet.parse("192.168.45.23/16")
ip.pred.to_string
=> "192.168.45.22/16"
Returns the prefix portion of the IPv4 object as a Subnet::Prefix32 object
ip = Subnet.parse("172.16.100.4/22")
ip.prefix
# => 22
ip.prefix.class
# => Subnet::Prefix32
Set a new prefix number for the object
This is useful if you want to change the prefix to an object created with IPv4.parse_u32 or if the object was created using the classful mask.
ip = Subnet.parse("172.16.100.4")
puts ip
# => 172.16.100.4/16
ip.prefix = 22
puts ip
# => 172.16.100.4/22
Checks if an IPv4 address objects belongs to a private network RFC1918
Example:
ip = Subnet.parse "10.1.1.1/24"
ip.private?
# => true
Returns the IP address in in-addr.arpa format for DNS lookups
ip = Subnet.parse("172.16.100.50/24")
ip.reverse
# => "50.100.16.172.in-addr.arpa"
Returns the number of IP addresses included in the network. It also counts the network address and the broadcast address.
ip = Subnet.parse("10.0.0.1/29")
ip.size
# => 8
Splits a network into different subnets
If the IP Address is a network, it can be divided into
multiple networks. If self
is not a network, this
method will calculate the network from the IP and then
subnet it.
If subnets
is an power of two number, the resulting
networks will be divided evenly from the supernet.
network = Subnet.parse("172.16.10.0/24")
network / 4 # implies map{|i| i.to_string}
# => ["172.16.10.0/26",
# => "172.16.10.64/26",
# => "172.16.10.128/26",
# => "172.16.10.192/26"]
If num
is any other number, the supernet will be
divided into some networks with a even number of hosts and
other networks with the remaining addresses.
network = Subnet.parse("172.16.10.0/24")
network / 3 # implies map{|i| i.to_string}
# => ["172.16.10.0/26",
# => "172.16.10.64/26",
# => "172.16.10.128/25"]
Returns an array of IPv4 objects
This method implements the subnetting function similar to the one described in RFC3531.
By specifying a new prefix, the method calculates the network number for the given IPv4 object and calculates the subnets associated to the new prefix.
For example, given the following network:
ip = Subnet.parse "172.16.10.0/24"
we can calculate the subnets with a /26 prefix
ip.subnet(26).map{&:to_string)
#=> ["172.16.10.0/26", "172.16.10.64/26", "172.16.10.128/26", "172.16.10.192/26"]
The resulting number of subnets will of course always be a power of two.
Returns the successor to the IP address
Example:
ip = Subnet.parse("192.168.45.23/16")
ip.succ.to_string
=> "192.168.45.24/16"
Returns a new IPv4 object from the supernetting of the instance network.
Supernetting is similar to subnetting, except that you getting as a result a network with a smaller prefix (bigger host space). For example, given the network
ip = Subnet.parse("172.16.10.0/24")
you can supernet it with a new /23 prefix
ip.supernet(23).to_string
# => "172.16.10.0/23"
However if you supernet it with a /22 prefix, the network address will change:
ip.supernet(22).to_string
# => "172.16.8.0/22"
If new_prefix
is less than 1, returns 0.0.0.0/0
Return a list of IP's between @address and the supplied IP
ip = Subnet..parse("172.16.100.51/32")
ip.to("172.16.100.100")
# => ["172.16.100.51",
# => "172.16.100.52",
# => ...
# => "172.16.100.99",
# => "172.16.100.100"]
Return the ip address in a format compatible with the IPv6 Mapped IPv4 addresses
Example:
ip = Subnet.parse("172.16.10.1/24")
ip.to_ipv6
# => "ac10:0a01"
Returns a string with the address portion of the IPv4 object
ip = Subnet.parse("172.16.100.4/22")
ip.to_s
# => "172.16.100.4"
Returns a string with the IP address in canonical form.
ip = Subnet.parse("172.16.100.4/22")
ip.to_string
# => "172.16.100.4/22"
Returns the address portion in unsigned 32 bits integer format.
This method is identical to the C function inet_pton to create a 32 bits address family structure.
ip = Subnet.parse("10.0.0.0/8")
ip.to_i
# => 167772160