= ruby-ip library
This is a library for manipulating IP addresses.
{}[https://travis-ci.org/G7M3/ruby-ip2]
{}[https://coveralls.io/github/G7M3/ruby-ip2?branch=master]
== Installation
Gem:: gem install ruby-ip
Source:: git clone git://github.com/G7M3/ruby-ip2.git
== Feature overview
* Create from string and to string
require 'ip'
ip = IP.new("192.0.2.53/24")
ip.to_s # "192.0.2.53/24"
ip.to_i # 3221226037
ip.to_b # 11000000000000000000001000110101
ip.to_hex # "c0000235"
ip.to_addr # "192.0.2.53"
ip.to_arpa # "53.2.0.192.in-addr.arpa."
ip.pfxlen # 24
* Convert from IPAddr to IP and back to IPAddr
# new IPAddr
ipaddr = IPAddr.new('192.168.2.1')
# => #
# convert it to IP
ip_from_ipaddr = IP.new_ntoh(ipaddr.hton)
# =>
# and back to IPAddr
ipaddr_from_ip = IPAddr.new_ntoh(ip_from_ipaddr.hton)
# => #
* Qualify IP address with "routing context" (VRF)
ip = IP.new("192.0.2.53/24@cust1")
ip.to_s # "192.0.2.53/24@cust1"
ip.to_addrlen # "192.0.2.53/24"
ip.ctx # "cust1"
* Clean implementation of IP::V4 and IP::V6 as subclasses of IP
ip1 = IP.new("192.0.2.53/24") #
ip2 = IP.new("2001:db8:be00::/48") #
ip1.is_a?(IP::V4) # true
* Create directly from integers or hex
ip = IP::V4.new(3221226037, 24, "cust1")
ip = IP::V4.new("c0000235", 24, "cust1")
* Netmask manipulation
ip = IP.new("192.0.2.53/24")
ip.network #
ip.network(1) #
ip.broadcast #
ip.broadcast(-1) #
ip.mask # 255
ip.size # 256
ip.netmask.to_s # "255.255.255.0"
ip.wildmask.to_s # "0.0.0.255"
* Address masking
ip = IP.new("192.0.2.53/24")
ip.offset? # true
ip.offset # 53
ip.mask!
ip.to_s # "192.0.2.0/24"
ip.offset? # false
* Simple IP arithmetic
ip = IP.new("192.0.2.53/24")
ip + 4 #
ip | 7 #
ip ^ 7 #
~ip #
* Advanced Subnet Operations
sn = IP.new('192.168.0.0/24')
ip = IP.new('192.168.0.48/32')
sn.split [#,
#] (2 evenly divided subnets)
sn.divide_by_subnets(3) [#,
#,
#,
#] (4 evenly divided subnets)
#keep in mind this always takes into account a network and broadcast address
sn.divide_by_hosts(100) [#,
#] (128 hosts each)
ip = IP.new('192.168.0.48/32')
ip.is_in?(sn)
=> true
* Deaggregate subnets from range
IP.new('1.2.0.0').deaggregate(IP.new('1.3.255.255'))
=> [#]
IP.new('1.2.0.0').deaggregate(IP.new('1.4.255.255'))
=> [#, #]
IP.new('2001:db8:85a3:8d3::').deaggregate(IP.new('2001:0db8:85a3:08d3:ffff:ffff:ffff:ffff'))
=> [#]
IP.new('2001:db8:85a3:8d3::').deaggregate(IP.new('2001:db8:85a3:8d3:1::'))
=> [#, #]
* Convert to and from a compact Array representation
ip1 = IP.new("192.0.2.53/24@cust1")
ip1.to_a # ["v4", 3221226037, 24, "cust1"]
ip2 = IP.new(["v4", 3221226037, 24, "cust1"])
ip1 == ip2 # true
* Hex array representation, useful when talking to languages which don't
have Bignum support
ip1 = IP.new("2001:db8:be00::/48@cust1")
ip1.to_ah # ["v6", "20010db8be0000000000000000000000", 48, "cust1"]
ip2 = IP.new(["v6", "20010db8be0000000000000000000000", 48, "cust1"])
ip1 == ip2 # true
* Addresses are Comparable, sortable, and can be used as Hash keys
* Addresses can be stored in a VARBINARY(16) database column as string of bytes
# == Schema Information
#
# Table name: ipaddresses
#
# id :integer not null, primary key
# address :binary(16)
# pfxlen :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_ipaddresses_on_address (address)
# index_ipaddresses_on_pfxlen (pfxlen)
#
require 'ip'
class IpAddress < ActiveRecord::Base
validates_uniqueness_of :address, scope: [:pfxlen]
validates_presence_of :address, :pfxlen
# IpAddress.last.address returns an IP object
def address
IP.new("#{IP.new_ntoh(super).to_s}/#{pfxlen}")
end
# Address can be set with string:
# ipaddress = IpAddress.new({address: '2001:db8:be00::/128'})
# Or IP object:
# ip = IP.new('2001:db8:be00::/128')
# ipaddress = IpAddress.new({address: ip})
def address=(arg)
ip = IP.new(arg)
self.pfxlen = ip.pfxlen
super(ip.hton)
end
end
== Why not IPAddr?
Ruby bundles an IPAddr class (ipaddr.rb). However there are a number of
serious problems with this library.
1. Given an IP address with a netmask or prefix (e.g. 192.0.2.0/24) it's
very hard to get access to the netmask part. It involves digging around
instance variables.
2. It's impossible to deal with an off-base address with prefix, because
IPAddr forcibly masks it to the base. e.g. 192.0.2.53/24 is stored as
192.0.2.0/24
3. IPAddr uses calls to the socket library to validate IP addresses, and
this can trigger spurious DNS lookups when given an invalid IP address.
ruby-ip does not depend on the socket library at all, unless you
require 'ip/socket' to have access to the Socket::AF_INET and
Socket::AF_INET6 constants.
== Copying
You may use, distribute and modify this software under the same terms as
ruby itself (see LICENSE.txt and COPYING.txt)