Frage

Ich habe die IP-Adresse gem benutzen und es scheint nicht die Möglichkeit zu haben, von einer Netzmaske der Form zu konvertieren

255.255.255.0 

in die CIDR Form

/24

Hat jemand eine Idee hat, wie man schnell die ersteren zum letzteren umwandeln?

War es hilfreich?

Lösung

Hier ist die schnelle und schmutzige Art und Weise

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

Es sollte eine einwandfreie Funktion für das sein, konnte ich nicht feststellen, dass, so dass ich nur „1“ zähle

Wenn Sie vorhaben, die Funktion in einer Reihe von Orten zu verwenden und nicht monkeypatching nichts, das helfen könnte:

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

Sie erhalten dann

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

Andere Tipps

So wie ein FYI, und die Informationen zu halten, leicht zugänglich für diejenigen, die suchen ...

Hier ist eine einfache Möglichkeit, von CIDR-Format zu konvertieren Netmask:

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

Zum Beispiel:

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"

Hier ist ein mathematischer Ansatz, Streicher unter allen Umständen vermieden werden:

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

mit „Maske“ ist eine Zeichenkette wie 255.255.255.0. Sie können es ändern, und das erste Argument ändern, um nur „Maske“, wenn „Maske“ ist schon eine ganze Zahl Darstellung einer IP-Adresse.

So zum Beispiel, wenn Maske "255.255.255.0" ist, IPAddr.new (Maske, Socket :: AF_INET) .to_i würde 0xffffff00 werden, die dann mit 0xffffffff XOR-verknüpft wird, die 255 gleich

Wir fügen 1, dass es ein umfassendes Angebot von 256 Hosts zu machen, dann die Log-Basis finden 2 von 256, die 8 (für die Host-Adresse verwendet, um die Bits) gleich, dann subtrahieren, dass 8 von 32, die 24 gleich (die Bits für die Netzwerkadresse verwendet wird).

Wir werfen dann integer, weil Math.log2 einen Schwimmer zurück.

Schnell und schmutzig Umwandlung:

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

=> I gespalten Maske in einem Array

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

=> Für jedes Element in Array:

.to_i

=> Konvertieren in integer

.to_s(2)

=> Konvertieren integer in binären

.rjust(8, "0")

=> Add padding

=> Karte ein Array mit der gleichen Mächtigkeit zurückkehren

.join

=> Konvertieren Array in eine vollständige Zeichenfolge

.count("1")

=> "1" Zeichen Count => Geben Sie CIDR Maske

    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"

Wenn Sie nicht brauchen, um IP-Adresse gem zu verwenden, können Sie dies mit der 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" 
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"

Der Code löst die Maskierung von privaten Instanzvariablen Zugriff auf * @ mask_addr) von IPAddr Instanz (Adresse, in serialize_ipaddr bestanden). Dies wird nicht empfohlen Art und Weise (wie die Instanzvariablen nicht Teil der Klassen öffentlichen API sind aber hier ist es besser als das Parsen der Zeichenfolge #inspect in meiner Meinung nach.

So wird das Verfahren wie folgt:

  1. Holen Sie sich das Instanzvariable @mask_addr , die netmask
  2. steht
  3. Get seine binäre Darstellung z.B. 255.255.255.0 -> 4294967040 -> 11111111111111111111111100000000
  4. Zählen Sie die 1-s in der Basis-2 Nummer CIDR-Maske zu erhalten (24)
  5. Erstellen Sie eine Zeichenkette, die aus der Adresse und Maske bis

EDIT: Hinzugefügt Erklärung für die Umsetzung, wie durch NathanOliver angefordert

Hier ist ein Weg, um es ohne das IPAddr Juwel zu tun

(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top