Skip to content

Commit

Permalink
Merge pull request #317 from yast/nativerubymethods-ip
Browse files Browse the repository at this point in the history
Use native Ruby implementations in Yast::IP (only)
  • Loading branch information
mvidner committed Jan 13, 2015
2 parents 56df679 + 5735531 commit af5ce1c
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 114 deletions.
151 changes: 48 additions & 103 deletions library/types/src/modules/IP.rb
Expand Up @@ -30,9 +30,12 @@
# $Id$
require "yast"
require "resolv"
require 'ipaddr'

module Yast
class IPClass < Module
include Yast::Logger

def main
textdomain "base"

Expand All @@ -59,9 +62,9 @@ def Valid4
# @param [String] ip IPv4 address
# @return true if correct
def Check4(ip)
return false if ip == nil

!Resolv::IPv4::Regex.match(ip).nil?
IPAddr.new(ip).ipv4?
rescue
false
end

# Describe a valid IPv6 address
Expand All @@ -79,22 +82,9 @@ def Valid6
# @param [String] ip IPv6 address
# @return true if correct
def Check6(ip)
return false if ip == nil

res = !Resolv::IPv6::Regex.match(ip).nil?

# workaround for compressed address as it is hard to check correct number
# in compressed ip using regexp only
if res && ip.include?("::")
prefix, suffix = ip.split("::")
elements = prefix.split(":")
contain_ipv4 = ip.include? "."
elements += suffix.split(":") if suffix
max_elements = contain_ipv4 ? 6 : 7
return elements.size <= max_elements
end

return res
IPAddr.new(ip).ipv6?
rescue
false
end

# If param contains IPv6 in one of its various forms, extracts it.
Expand Down Expand Up @@ -151,34 +141,25 @@ def ValidNetwork
# @return ip address as integer
def ToInteger(ip)
return nil unless Check4(ip)

parts = ip.split(".")
parts.reduce(0) {|r, p| (r << 8) + p.to_i }
IPAddr.new(ip).to_i
end

# Convert IPv4 address from integer to string
# @param [Fixnum] ip IPv4 address
# @return ip address as string
def ToString(ip)
parts = [16777216, 65536, 256, 1].map do |b|
(ip / b) & 255
end

parts.join(".")
IPAddr.new(ip, Socket::AF_INET).to_s
end

# Converts IPv4 address from string to hex format
# @param [String] ip IPv4 address as string in "ipv4" format
# @return [String] representing IP in Hex
# @example IP::ToHex("192.168.1.1") -> "0xC0A80101"
# @example IP::ToHex("10.10.0.1") -> "0x0A0A0001"
# @example IP::ToHex("192.168.1.1") -> "C0A80101"
# @example IP::ToHex("10.10.0.1") -> "0A0A0001"
def ToHex(ip)
int = ToInteger(ip)
return nil unless int

hex = int.to_s(16)

("0" * (8 - hex.size)) + hex.upcase
"%08X" % int
end

# Compute IPv4 network address from ip4 address and network mask.
Expand Down Expand Up @@ -216,16 +197,12 @@ def ComputeBroadcast(ip, mask)
# IPv4ToBits("80.25.135.2") -> "01010000000110011000011100000010"
# IPv4ToBits("172.24.233.211") -> "10101100000110001110100111010011"
def IPv4ToBits(ipv4)
unless Check4(ipv4)
Builtins.y2error("Not a valid IPv4: %1", ipv4)
return nil
end

bits = ToInteger(ipv4).to_s(2)
"0" * (32 - bits.size) + bits
int = ToInteger(ipv4)
return nil unless int
"%032b" % int
end

# Converts 32 bit binary number to its IPv4 repserentation.
# Converts 32 bit binary number to its IPv4 representation.
#
# @param string binary
# @return [String] ipv4
Expand All @@ -236,21 +213,13 @@ def IPv4ToBits(ipv4)
# BitsToIPv4("10111100000110001110001100000101") -> "188.24.227.5"
# BitsToIPv4("00110101000110001110001001100101") -> "53.24.226.101"
def BitsToIPv4(bits)
if Builtins.size(bits) != 32
Builtins.y2error("Not a valid IPv4 in Bits: %1", bits)
return nil
end
if !Builtins.regexpmatch(bits, "^[01]+$")
Builtins.y2error("Not a valid IPv4 in Bits: %1", bits)
return nil
end

return nil unless /\A[01]{32}\z/ =~ bits
ToString(bits.to_i(2))
end

def CheckNetworkShared(network)
if network == nil || network == ""
return false
return false

# all networks
elsif network == "0/0"
Expand All @@ -272,32 +241,23 @@ def CheckNetworkShared(network)
def CheckNetwork4(network)
generic_check = CheckNetworkShared(network)
if generic_check != nil
return generic_check
return generic_check

# 192.168.0.1, 0.8.55.999
elsif Check4(network)
return true
# 192.168.0.0/20, 0.8.55/158
elsif network =~ Regexp.new("^[" + @ValidChars4 + "]+/[0-9]+$")
net_parts = network.split("/")
return Check4(net_parts[0]) &&
Netmask.CheckPrefix4(net_parts[1])

# 192.168.0.0/20, 0.8.55/158
elsif Builtins.regexpmatch(
network,
Ops.add(Ops.add("^[", @ValidChars4), "]+/[0-9]+$")
)
net_parts = Builtins.splitstring(network, "/")
return Check4(Ops.get(net_parts, 0, "")) &&
Netmask.CheckPrefix4(Ops.get(net_parts, 1, ""))

# 192.168.0.0/255.255.255.0, 0.8.55/10.258.12
elsif Builtins.regexpmatch(
network,
Ops.add(
Ops.add(Ops.add(Ops.add("^[", @ValidChars4), "]+/["), @ValidChars4),
"]+$"
)
)
net_parts = Builtins.splitstring(network, "/")
return Check4(Ops.get(net_parts, 0, "")) &&
Netmask.Check4(Ops.get(net_parts, 1, ""))
# 192.168.0.0/255.255.255.0, 0.8.55/10.258.12
elsif network =~ Regexp.new("^[" + @ValidChars4 + "]+/[" + @ValidChars4 + "]+$")
net_parts = network.split("/")
return Check4(net_parts[0]) &&
Netmask.Check4(net_parts[1])

# 192.168.0.1, 0.8.55.999
elsif Check4(network)
return true
end

false
Expand All @@ -315,38 +275,23 @@ def CheckNetwork4(network)
def CheckNetwork6(network)
generic_check = CheckNetworkShared(network)
if generic_check != nil
return generic_check

# 2001:db8:0::1
elsif Check6(network)
return true
return generic_check

# 2001:db8:0::1/64
elsif Builtins.regexpmatch(
network,
Ops.add(
Ops.add(
Ops.add(Ops.add("^[", @ValidChars6), "]+/["),
Netmask.ValidChars6
),
"]+$"
)
)
net_parts = Builtins.splitstring(network, "/")
return Check6(Ops.get(net_parts, 0, "")) &&
Netmask.Check6(Ops.get(net_parts, 1, ""))
elsif network =~ Regexp.new("^[" + @ValidChars6 + "]+/[" + Netmask.ValidChars6 + "]*$")
net_parts = network.split("/")
return Check6(net_parts[0]) &&
Netmask.Check6(net_parts[1])

# 2001:db8:0::1/ffff:ffff::0
elsif Builtins.regexpmatch(
network,
Ops.add(
Ops.add(Ops.add(Ops.add("^[", @ValidChars6), "]+/["), @ValidChars6),
"]+$"
)
)
net_parts = Builtins.splitstring(network, "/")
return Check6(Ops.get(net_parts, 0, "")) &&
Check6(Ops.get(net_parts, 1, ""))
elsif network =~ Regexp.new("^[" + @ValidChars6 + "]+/[" + @ValidChars6 + "]+$")
net_parts = network.split("/")
return Check6(net_parts[0]) &&
Check6(net_parts[1])
# 2001:db8:0::1

elsif Check6(network)
return true
end

false
Expand Down
20 changes: 10 additions & 10 deletions library/types/test/ip_test.rb
Expand Up @@ -122,19 +122,19 @@
# in 32bits arch IP#ToInteger returns Bignum, so equal? returns false
# and eql? has to be used
# in 64bits arch the result is Fixnum and the problem do not appear
expect( IP.ToInteger(k)).to be_eql v
expect( IP.ToInteger(k)).to eq v
end
end

it "returns nil if value is not valid IPv4 in dotted format" do
expect( IP.ToInteger("foobar")).to be_equal nil
expect( IP.ToInteger("foobar")).to eq nil
end
end

describe "#ToString" do
RESULT_MAP_INT.each_pair do |k,v|
it "it returns #{k} for #{v}" do
expect( IP.ToString(v)) == k
expect( IP.ToString(v)).to eq k
end
end
end
Expand All @@ -149,12 +149,12 @@

RESULT_MAP_HEX.each_pair do |k,v|
it "returns #{v} for valid #{k}" do
expect( IP.ToHex(k)) == v
expect( IP.ToHex(k)).to eq v
end
end

it "returns nil if value is not valid IPv4 in dotted format" do
expect( IP.ToHex("foobar")).to be_equal nil
expect( IP.ToHex("foobar")).to eq nil
end
end

Expand All @@ -166,28 +166,28 @@
describe "#IPv4ToBits" do
RESULT_MAP_BITS.each_pair do |k,v|
it "returns bitmap for #{k}" do
expect( IP.IPv4ToBits(k)) == v
expect( IP.IPv4ToBits(k)).to eq v
end
end

it "returns nil if value is not valid IPv4" do
expect( IP.IPv4ToBits("blabla")).to be_equal nil
expect( IP.IPv4ToBits("blabla")).to eq nil
end
end

describe "#BitsToIPv4" do
RESULT_MAP_BITS.each_pair do |k,v|
it "returns #{k} for #{v}" do
expect( IP.BitsToIPv4(v)) == k
expect( IP.BitsToIPv4(v)).to eq k
end
end

it "returns nil if length of bitmap is not 32" do
expect( IP.BitsToIPv4("101")).to be_equal nil
expect( IP.BitsToIPv4("101")).to eq nil
end

it "returns nil if value is not valid bitmap with 0 or 1 only" do
expect( IP.BitsToIPv4("foobar")).to be_equal nil
expect( IP.BitsToIPv4("foobar")).to eq nil
end
end

Expand Down
6 changes: 6 additions & 0 deletions package/yast2.changes
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Tue Jan 13 13:43:40 UTC 2015 - cwh@suse.com

- Use native Ruby implementation (IPAddr) for Yast::IP.
- 3.1.116

-------------------------------------------------------------------
Wed Jan 7 10:55:13 UTC 2015 - jsrain@suse.cz

Expand Down
2 changes: 1 addition & 1 deletion package/yast2.spec
Expand Up @@ -17,7 +17,7 @@


Name: yast2
Version: 3.1.115
Version: 3.1.116
Release: 0
URL: https://github.com/yast/yast-yast2

Expand Down

0 comments on commit af5ce1c

Please sign in to comment.