philiprehberger-ip_addr

Tests Gem Version Last updated

Enhanced IP address library with CIDR, classification, and range operations

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-ip_addr"

Or install directly:

gem install philiprehberger-ip_addr

Usage

require "philiprehberger/ip_addr"

ip = Philiprehberger::IpAddr.parse('192.168.1.1')
ip.v4?      # => true
ip.private? # => true
ip.to_i     # => 3232235777
ip.to_s     # => "192.168.1.1"

Classification

ip = Philiprehberger::IpAddr.parse('127.0.0.1')
ip.loopback?  # => true

ip = Philiprehberger::IpAddr.parse('224.0.0.1')
ip.multicast? # => true

ip = Philiprehberger::IpAddr.parse('::1')
ip.v6?      # => true
ip.loopback? # => true

ip = Philiprehberger::IpAddr.parse('169.254.1.1')
ip.link_local? # => true

ip = Philiprehberger::IpAddr.parse('10.0.0.1')
ip.reserved?   # => true (private, loopback, multicast, or link-local)

ip = Philiprehberger::IpAddr.parse('8.8.8.8')
ip.reserved?   # => false

Comparison and Arithmetic

a = Philiprehberger::IpAddr.parse('10.0.0.1')
b = Philiprehberger::IpAddr.parse('10.0.0.5')
a < b       # => true
a.succ.to_s # => "10.0.0.2"
b.pred.to_s # => "10.0.0.4"

[b, a].sort.map(&:to_s) # => ["10.0.0.1", "10.0.0.5"]

CIDR Ranges

range = Philiprehberger::IpAddr.range('10.0.0.0/24')
range.size                    # => 256
range.include?('10.0.0.42')   # => true
range.include?('10.0.1.1')    # => false

range = Philiprehberger::IpAddr.range('10.0.0.0/30')
range.each { |ip| puts ip }
range.to_a.map(&:to_s)  # => ["10.0.0.0", "10.0.0.1", "10.0.0.2", "10.0.0.3"]

Subnet Operations

range = Philiprehberger::IpAddr.range('192.168.1.0/24')
range.network.to_s   # => "192.168.1.0"
range.broadcast.to_s # => "192.168.1.255"
range.netmask        # => "255.255.255.0"
range.prefix         # => 24

other = Philiprehberger::IpAddr.range('192.168.1.128/25')
range.overlap?(other) # => true

Subnet splitting

range = Philiprehberger::IpAddr.range('10.0.0.0/24')
range.subnets(prefix: 26).map(&:to_s)
# => ["10.0.0.0/26", "10.0.0.64/26", "10.0.0.128/26", "10.0.0.192/26"]

range.subnets(prefix: 26).first.size # => 64

v6 = Philiprehberger::IpAddr.range('2001:db8::/32')
v6.subnets(prefix: 34).count # => 4

range.subnets(prefix: 26) # => #<Enumerator: ...> when called without a block

API

Method Description
IpAddr.parse(str) Parse an IP address string into an Address
IpAddr.range(cidr) Create a CIDR range object
Address#v4? True if IPv4
Address#v6? True if IPv6
Address#private? True if private/ULA address
Address#loopback? True if loopback address
Address#multicast? True if multicast address
Address#link_local? True if link-local address
Address#reserved? True if private, loopback, multicast, or link-local
Address#to_i Numeric representation
Address#to_s String representation
Address#<=>(other) Compare addresses for sorting
Address#succ Next IP address
Address#pred Previous IP address
Range#size Number of addresses in range
Range#include?(ip) Check if address is in range
Range#each Iterate over all addresses
Range#to_a Array of all addresses
Range#network Network address of the CIDR block
Range#broadcast Broadcast/last address of the CIDR block
Range#prefix CIDR prefix length
Range#netmask Subnet mask (dotted-decimal for IPv4)
Range#overlap?(other) Check if two ranges share addresses
Range#subnets(prefix:) Yield equal-size child subnets at the given prefix length

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT