红宝石中的网络掩码到CIDR

时间:2009-12-01 12:33:25

标签: ruby ip

我一直在使用ip-address gem,它似乎无法从表单的网络掩码转换

255.255.255.0 

进入CIDR表格

/24

有没有人有想法如何快速将前者转换为后者?

7 个答案:

答案 0 :(得分:13)

这是快速而肮脏的方式

require 'ipaddr'
puts IPAddr.new("255.255.255.0").to_i.to_s(2).count("1")

应该有适当的功能,我找不到,所以我只算“1”

如果你打算在很多地方使用这个功能而不介意monkeypatching,这可能会有所帮助:

IPAddr.class_eval
  def to_cidr
    "/" + self.to_i.to_s(2).count("1")
  end
end

然后你得到

IPAddr.new('255.255.255.0').to_cidr
# => "/24"

答案 1 :(得分:10)

就像一个FYI一样,并且为那些正在搜索的人提供便于查阅的信息......

以下是从CIDR转换为网络掩码格式的简单方法:

def cidr_to_netmask(cidr)
  IPAddr.new('255.255.255.255').mask(cidr).to_s
end

例如:

cidr_to_netmask(24) #=> "255.255.255.0"
cidr_to_netmask(32) #=> "255.255.255.255"
cidr_to_netmask(16) #=> "255.255.0.0"
cidr_to_netmask(22) #=> "255.255.252.0"

答案 2 :(得分:5)

这是一种更加数学化的方法,不惜一切代价避免使用字符串:

def cidr_mask
    Integer(32-Math.log2((IPAddr.new(mask,Socket::AF_INET).to_i^0xffffffff)+1))
end

“mask”是一个像255.255.255.0这样的字符串。如果“mask”已经是IP地址的整数表示,您可以修改它并将第一个参数更改为“mask”。

例如,如果mask是“255.255.255.0”,则IPAddr.new(mask,Socket :: AF_INET).to_i将变为0xffffff00,然后与0xffffffff xor'd,等于255.

我们将其加1以使其成为256个主机的完整范围,然后找到256的对数基数2,等于8(用于主机地址的位),然后从32减去8,等于24 (用于网络地址的位)。

然后我们转换为整数,因为Math.log2返回一个浮点数。

答案 3 :(得分:5)

快速而肮脏的转换:

"255.255.255.0".split(".").map { |e| e.to_i.to_s(2).rjust(8, "0") }.join.count("1").split(".")

=>我在数组中分割掩码

.map { |e| e.to_i.to_s(2).rjust(8, "0") }

=>对于Array中的每个元素:

.to_i

=>转换为整数

.to_s(2)

=>将整数转换为二进制

.rjust(8, "0")

=>添加填充

=> Map返回具有相同基数的数组

.join

=>将数组转换为完整的字符串

.count("1")

=>计数“1”字符=>给出CIDR面具

    def mask_2_ciddr mask
      "/" + mask.split(".").map { |e| e.to_i.to_s(2).rjust(8, "0") }.join.count("1").to_s
    end

    mask_2_ciddr "255.255.255.0"
    => "/24"
    mask_2_ciddr "255.255.255.128"
    => "/25"

答案 4 :(得分:2)

如果您不需要使用ip-address gem,可以使用netaddr gem

执行此操作
require 'netaddr'

def to_cidr_mask(dotted_mask)
  NetAddr::CIDR.create('0.0.0.0/'+dotted_mask).netmask
end

to_cidr_mask("255.224.0.0") # => "/11" 

答案 5 :(得分:1)

require 'ipaddr'

def serialize_ipaddr(address)
  mask = address.instance_variable_get(:@mask_addr).to_s(2).count('1')
  "#{address}/#{mask}"
end

serialize_ipaddr(IPAddr.new('192.168.0.1/24')) # => "192.168.0.0/24"

代码通过访问IPAddr实例的私有实例变量* @mask_addr来实现屏蔽(地址,传递给serialize_ipaddr)。这不是推荐的方式(因为实例变量不是类公共API的一部分,但在这里它比在我看来从 #inspect 解析字符串更好。

所以过程如下:

  1. 获取代表netmask的实例变量 @mask_addr
  2. 获取其二进制表示,例如255.255.255.0 -> 4294967040 -> 11111111111111111111111100000000
  3. 计算base-2数字中的1-s以获得CIDR掩码(24)
  4. 组成一个包含地址和字符串的字符串。掩蔽
  5. 编辑:根据NathanOliver的要求添加了对实施的解释

答案 6 :(得分:0)

这是没有IPAddr宝石的一种方法

(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')