Class: IPAddress::IPv4

Inherits:
IPAddress show all
Defined in:
lib/ipaddress/ipv4.rb

Overview

Name

IPAddress::IPv4 - IP version 4 address manipulation library

Synopsis

require 'ipaddress'

Description

Class IPAddress::IPv4 is used to handle IPv4 type addresses.

Constant Summary collapse

CLASSFUL =

This Hash contains the prefix values for Classful networks

Note that classes C, D and E will all have a default prefix of /24 or 255.255.255.0

{
  8  => /\A0../,  # Class A, from 0.0.0.0 to 127.255.255.255
  16 => /\A10./,  # Class B, from 128.0.0.0 to 191.255.255.255
  24 => /\A110/   # Class C, D and E, from 192.0.0.0 to 255.255.255.254
}
INTERNAL_RE =
%r{ (?: #{part} \. ){3} #{part} }xo
RE =

Regular expression to match an IPv4 address

%r{ \A #{INTERNAL_RE} \z }xo
Prefix =
Prefix32
MAX_PREFIX =
Prefix::MAX
PREFIX_RE =
%r{ \A (?: [12]?\d | 3[0-2] ) \z }x

Constants inherited from IPAddress

AUTHORS, GEM, NAME, VERSION

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from IPAddress

#<=>, #at, #bits, #boundaries, #broadcast, #broadcast_i, #distance, #each, #each_host, #each_i, #exact_supernet, #first, #hash, #hosts, #include?, #include_all?, #include_exactly?, #inspect, #ipv4?, #ipv6?, #last, #mapped, #network, #network?, #network_i, #new_prefix, #overlap?, #overlap_i?, parse, #proper_supernet, #range, #size, #span, #span_i, #split, #subnet, subtract, #subtract, subtract!, #succ, #summarize, summarize, #supernet, #to_string, valid?, valid_ipv4?, valid_ipv4_netmask?, valid_ipv6?

Methods included from Conversions

#addr2ary, #addr2bits, #ary2addr, #ary2data, #ary2int, #bits2addr, #data2ary, #data2bits, #data2int, #int2addr, #int2ary, #int2data

Constructor Details

#initialize(str) ⇒ IPv4

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 = IPAddress::IPv4.new("10.0.0.1/24")
ip = IPAddress("10.0.0.1/24")

# These two are the same
IPAddress::IPv4.new("10.0.0.1/8")
IPAddress::IPv4.new("10.0.0.1/255.0.0.0")


170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/ipaddress/ipv4.rb', line 170

def initialize(str)
  ip, netmask = split_ip_and_netmask(str)

  if netmask.nil? || netmask =~ PREFIX_RE
    @_prefix = netmask || 32
  elsif self.class.valid_ipv4_netmask?(netmask)
    @prefix  = Prefix.parse_netmask(netmask)
  else
    raise ArgumentError, "Invalid netmask #{netmask.inspect}"
  end

  @address, @octets = ip, addr2ary(ip)
end

Class Method Details

.extract(str, prefix = MAX_PREFIX) ⇒ Object

Extract an IPv4 address from a string and returns a new object

Example:

str = "foobar172.16.10.1barbaz"
ip = IPAddress::IPv4.extract(str)

ip.to_s
  #=> "172.16.10.1"


129
130
131
# File 'lib/ipaddress/ipv4.rb', line 129

def extract(str, prefix = MAX_PREFIX)
  new("#{INTERNAL_RE.match(str)}/#{prefix}")
end

.extract_all(str, prefix = MAX_PREFIX) ⇒ Object



133
134
135
# File 'lib/ipaddress/ipv4.rb', line 133

def extract_all(str, prefix = MAX_PREFIX)
  str.scan(INTERNAL_RE).map! { |m| new("#{m}/#{prefix}") }
end

.parse_classful(ip) ⇒ Object

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 = IPAddress::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

Raises:

  • (ArgumentError)


110
111
112
113
114
115
# File 'lib/ipaddress/ipv4.rb', line 110

def parse_classful(ip)
  raise ArgumentError, "Invalid IP #{ip.inspect}" unless valid_ipv4?(ip)

  bits = '%.8b' % ip.to_i
  new("#{ip.strip}/#{CLASSFUL.find { |_, re| re === bits }.first}")
end

.parse_data(data, prefix = MAX_PREFIX) ⇒ Object

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 “254020n001”.

ip = IPAddress::IPv4.parse_data("\254\020\n\001", 24)

ip.to_string
  #=> "172.16.10.1/24"


83
84
85
# File 'lib/ipaddress/ipv4.rb', line 83

def parse_data(data, prefix = MAX_PREFIX)
  parse_i(data2int(data), prefix)
end

.parse_i(i, prefix = MAX_PREFIX) ⇒ Object Also known as: parse_u32

Creates a new IPv4 object from an unsigned 32bits integer.

ip = IPAddress::IPv4.parse_u32(167772160)

ip.to_string
  #=> "10.0.0.0/32"

The prefix parameter is optional:

ip = IPAddress::IPv4.parse_u32(167772160, 8)

ip.to_string
  #=> "10.0.0.0/8"


65
66
67
# File 'lib/ipaddress/ipv4.rb', line 65

def parse_i(i, prefix = MAX_PREFIX)
  instantiate { @int, @_prefix = i, prefix }
end

.private_netsObject



137
138
139
140
141
142
143
# File 'lib/ipaddress/ipv4.rb', line 137

def private_nets
  @private_nets ||= %w[
    10.0.0.0/8
    172.16.0.0/12
    192.168.0.0/16
  ].map! { |i| new(i) }
end

Instance Method Details

#[](index) ⇒ Object Also known as: octet, group

Returns the octet specified by index

ip = IPAddress("172.16.100.50/24")

ip[0]
  #=> 172
ip[1]
  #=> 16
ip[2]
  #=> 100
ip[3]
  #=> 50


332
333
334
# File 'lib/ipaddress/ipv4.rb', line 332

def [](index)
  octets[index]
end

#a?Boolean

Checks whether the ip address belongs to a RFC 791 CLASS A network, no matter what the subnet mask is.

Example:

ip = IPAddress("10.0.0.1/24")

ip.a?
  #=> true


384
385
386
# File 'lib/ipaddress/ipv4.rb', line 384

def a?
  lazy_attr(:a_p) { CLASSFUL[8] === bits }
end

#addressObject

Returns the address portion of the IPv4 object as a string.

ip = IPAddress("172.16.100.4/22")

ip.address
  #=> "172.16.100.4"


197
198
199
# File 'lib/ipaddress/ipv4.rb', line 197

def address
  lazy_attr(:address) { ary2addr(octets) }
end

#b?Boolean

Checks whether the ip address belongs to a RFC 791 CLASS B network, no matter what the subnet mask is.

Example:

ip = IPAddress("172.16.10.1/24")

ip.b?
  #=> true


400
401
402
# File 'lib/ipaddress/ipv4.rb', line 400

def b?
  lazy_attr(:b_p) { CLASSFUL[16] === bits }
end

#c?Boolean

Checks whether the ip address belongs to a RFC 791 CLASS C network, no matter what the subnet mask is.

Example:

ip = IPAddress("192.168.1.1/30")

ip.c?
  #=> true


416
417
418
# File 'lib/ipaddress/ipv4.rb', line 416

def c?
  lazy_attr(:c_p) { CLASSFUL[24] === bits }
end

#dataObject

Returns the address portion of an IPv4 object in a network byte order format.

ip = IPAddress("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

a = Socket.open(params) # socket details here
ip = IPAddress("10.1.1.0/24")
binary_data = ["Address: "].pack("a*") + ip.data

# Send binary data
a.puts binary_data


314
315
316
# File 'lib/ipaddress/ipv4.rb', line 314

def data
  lazy_attr(:data) { int2data(to_i) }
end

#netmaskObject

Returns the prefix as a string in IP format

ip = IPAddress("172.16.100.4/22")

ip.netmask
  #=> "255.255.252.0"


225
226
227
# File 'lib/ipaddress/ipv4.rb', line 225

def netmask
  lazy_attr(:netmask) { prefix.to_ip }
end

#new_netmask(addr) ⇒ Object

Like IPv4#prefix=, this method allow you to change the prefix / netmask of an IP address object.

ip = IPAddress("172.16.100.4")

ip.to_string
  #=> 172.16.100.4/16

ip2 = ip.new_netmask("255.255.252.0")

ip2.to_string
  #=> 172.16.100.4/22


244
245
246
# File 'lib/ipaddress/ipv4.rb', line 244

def new_netmask(addr)
  new_prefix(Prefix.parse_netmask(addr))
end

#octetsObject Also known as: groups

Returns the address as an array of decimal values

ip = IPAddress("172.16.100.4")

ip.octets
  #=> [172, 16, 100, 4]


256
257
258
# File 'lib/ipaddress/ipv4.rb', line 256

def octets
  lazy_attr(:octets) { int2ary(to_i) }
end

#prefixObject

Returns the prefix portion of the IPv4 object as a IPAddress::Prefix32 object

ip = IPAddress("172.16.100.4/22")

ip.prefix
  #=> 22

ip.prefix.class
  #=> IPAddress::Prefix32


213
214
215
# File 'lib/ipaddress/ipv4.rb', line 213

def prefix
  lazy_attr(:prefix, false) { Prefix.new(@_prefix) }
end

#private?Boolean

Checks if an IPv4 address objects belongs to a private network RFC1918

Example:

ip = IPAddress "10.1.1.1/24"
ip.private?
  #=> true


368
369
370
# File 'lib/ipaddress/ipv4.rb', line 368

def private?
  lazy_attr(:private_p) { self.class.private_nets.any? { |i| i.include?(self) } }
end

#reverseObject Also known as: arpa

Returns the IP address in in-addr.arpa format for DNS lookups

ip = IPAddress("172.16.100.50/24")

ip.reverse
  #=> "50.100.16.172.in-addr.arpa"


352
353
354
# File 'lib/ipaddress/ipv4.rb', line 352

def reverse
  lazy_attr(:reverse) { "#{ary2addr(octets.reverse)}.in-addr.arpa" }
end

#to_iObject Also known as: u32, to_u32

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 = IPAddress("10.0.0.0/8")

ip.to_i
  #=> 167772160


288
289
290
# File 'lib/ipaddress/ipv4.rb', line 288

def to_i
  lazy_attr(:int) { ary2int(octets) }
end

#to_ipv6Object

Return the ip address in a format compatible with the IPv6 Mapped IPv4 addresses

Example:

ip = IPAddress("172.16.10.1/24")

ip.to_ipv6
  #=> "ac10:0a01"


431
432
433
# File 'lib/ipaddress/ipv4.rb', line 431

def to_ipv6
  lazy_attr(:to_ipv6) { '%.4x:%.4x' % int2data(to_i).unpack('n2') }
end

#to_sObject

Returns a string with the address portion of the IPv4 object

ip = IPAddress("172.16.100.4/22")

ip.to_s
  #=> "172.16.100.4"


271
272
273
# File 'lib/ipaddress/ipv4.rb', line 271

def to_s
  address
end

#versionObject



184
185
186
# File 'lib/ipaddress/ipv4.rb', line 184

def version
  4
end