Skip to content

Commit

Permalink
Add Socket::IPAddress#private?
Browse files Browse the repository at this point in the history
  • Loading branch information
jgillich committed Jun 20, 2020
1 parent 02a2e69 commit 91ec552
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
12 changes: 12 additions & 0 deletions spec/std/socket/address_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ describe Socket::IPAddress do
Socket::IPAddress.new(Socket::IPAddress::UNSPECIFIED, 0).unspecified?.should be_true
Socket::IPAddress.new(Socket::IPAddress::UNSPECIFIED6, 0).unspecified?.should be_true
end

it "#private?" do
Socket::IPAddress.new("192.168.0.1", 0).private?.should be_true
Socket::IPAddress.new("192.100.0.1", 0).private?.should be_false
Socket::IPAddress.new("172.16.0.1", 0).private?.should be_true
Socket::IPAddress.new("172.10.0.1", 0).private?.should be_false
Socket::IPAddress.new("10.0.0.1", 0).private?.should be_true
Socket::IPAddress.new("1.1.1.1", 0).private?.should be_false
Socket::IPAddress.new("fd00::1", 0).private?.should be_true
Socket::IPAddress.new("fb00::1", 0).private?.should be_false
Socket::IPAddress.new("2001:4860:4860::8888", 0).private?.should be_false
end
end

describe Socket::UNIXAddress do
Expand Down
18 changes: 17 additions & 1 deletion src/socket/address.cr
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class Socket
# `127.0.0.0/24`. In IPv6 `::1` is the loopback address.
def loopback? : Bool
if addr = @addr4
addr.s_addr & 0x00000000ff_u32 == 0x0000007f_u32
addr.s_addr & 0x000000ff_u32 == 0x0000007f_u32
elsif addr = @addr6
ipv6_addr8(addr) == StaticArray[0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 1_u8]
else
Expand All @@ -238,6 +238,22 @@ class Socket
end
end

# Returns `true` if this IP is a private address.
#
# IPv4 addresses in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined in RFC 1918
# and IPv6 Unique Local Addresses in fc00::/7 as defined in RFC 4193 are considered private.
def private? : Bool
if addr = @addr4
addr.s_addr & 0x000000ff_u32 == 0x00000000a_u32 || # 10.0.0.0/8
addr.s_addr & 0x000000f0ff_u32 == 0x0000010ac_u32 || # 172.16.0.0/12
addr.s_addr & 0x000000ffff_u32 == 0x0000a8c0_u32 # 192.168.0.0/16
elsif addr = @addr6
ipv6_addr8(addr)[0] & 0xfe_u8 == 0xfc_u8
else
raise "unreachable!"
end
end

private def ipv6_addr8(addr : LibC::In6Addr)
{% if flag?(:darwin) || flag?(:openbsd) || flag?(:freebsd) || flag?(:dragonfly) %}
addr.__u6_addr.__u6_addr8
Expand Down

0 comments on commit 91ec552

Please sign in to comment.