Domanda

Sto usando la gemma dell'indirizzo IP e non sembra avere la possibilità di convertire da una maschera di rete del modulo

255.255.255.0 

nel modulo CIDR

/24

Qualcuno ha idee su come convertire rapidamente il primo nel secondo?

È stato utile?

Soluzione

Ecco il modo rapido e sporco

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

Dovrebbe esserci una funzione adeguata per questo, non sono riuscito a trovarlo, quindi conto solo " 1 "

Se utilizzerai la funzione in un certo numero di posti e non ti dispiace il monkeypatching, questo potrebbe aiutare:

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

Quindi ottieni

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

Altri suggerimenti

Proprio come una FYI e per mantenere le informazioni facilmente accessibili per coloro che stanno cercando ...

Ecco un modo semplice per convertire da CIDR in formato maschera di rete:

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

Ad esempio:

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"

Ecco un approccio più matematico, evitando le stringhe a tutti i costi:

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

con " maschera " essendo una stringa come 255.255.255.0. Puoi modificarlo e cambiare il primo argomento in solo " mask " se "maschera" è già una rappresentazione intera di un indirizzo IP.

Quindi, ad esempio, se la maschera fosse " 255.255.255.0 " ;, IPAddr.new (maschera, socket :: AF_INET) .to_i diventerebbe 0xffffff00, che viene quindi xor'd con 0xffffffff, che equivale a 255.

Aggiungiamo 1 a quello per renderlo un intervallo completo di 256 host, quindi troviamo la base di registro 2 di 256, che è uguale a 8 (i bit utilizzati per l'indirizzo host), quindi sottraggiamo quell'8 da 32, che equivale a 24 (i bit utilizzati per l'indirizzo di rete).

Quindi eseguiamo il cast su intero perché Math.log2 restituisce un float.

Conversione rapida e sporca:

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

= > Ho diviso la maschera in un array

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

= > Per ogni elemento nell'array:

.to_i

= > Converti in intero

.to_s (2)

= > Converti intero in binario

.rjust (8, " 0 ")

= > Aggiungi imbottitura

= > La mappa restituisce un array con la stessa cardinalità

.join

= > Converti array in una stringa completa

.count (" 1 ")

= > Conta " 1 " caratteri = > Dai maschera 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"

Se non è necessario utilizzare la gemma dell'indirizzo IP, è possibile farlo con netaddr gemma

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"

Il codice ottiene il mascheramento accedendo alla variabile di istanza privata * @ mask_addr) dell'istanza di IPAddr (indirizzo, passato in serialize_ipaddr). Questo non è un metodo raccomandato (poiché le variabili di istanza non fanno parte dell'API pubblica delle classi ma qui è meglio che analizzare la stringa da #inspect a mio avviso.

Quindi il processo è il seguente:

  1. Ottieni la variabile di istanza @mask_addr che rappresenta la maschera di rete
  2. Ottieni la sua rappresentazione binaria, ad es. 255.255.255.0 - > 4294967040 - > 11111111111111111111111100000000
  3. Contare gli 1-s nel numero base-2 per ottenere la maschera CIDR (24)
  4. Crea una stringa composta dall'indirizzo & amp; mascherare

EDIT: aggiunta spiegazione all'implementazione come richiesto da NathanOliver

Ecco un modo per farlo senza la gemma IPAddr

(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top