Question

J'utilise la gemme d'adresse IP et il ne semble pas avoir la capacité de convertir un masque de réseau de la forme

255.255.255.0 

dans le formulaire CIDR

/24

Quelqu'un at-il une idée pour convertir rapidement le premier en second?

Était-ce utile?

La solution

Voici le moyen rapide et sale

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

Il devrait y avoir une fonction adéquate pour cela, je ne pouvais pas trouver cela, donc je compte juste "1"

Si vous envisagez d'utiliser la fonction dans plusieurs endroits et que cela ne vous dérange pas, vous pouvez utiliser la fonctionnalité Monkeypatchatch:

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

Ensuite, vous obtenez

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

Autres conseils

Comme pour votre information et pour que les informations restent facilement accessibles pour ceux qui recherchent ...

Voici un moyen simple de convertir du format CIDR au format masque de réseau:

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

Par exemple:

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"

Voici une approche plus mathématique, évitant les chaînes à tout prix:

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

avec " masque " étant une chaîne comme 255.255.255.0. Vous pouvez le modifier et changer le premier argument en "masque". si & masque; masque " est déjà une représentation entière d'une adresse IP.

Ainsi, par exemple, masque serait "255.255.255.0", IPAddr.new (masque, Socket :: AF_INET) .to_i deviendrait 0xffffff00, qui est ensuite xoré avec 0xffffffff, ce qui équivaut à 255.

Nous ajoutons 1 à cela pour en faire une plage complète de 256 hôtes, puis trouvons la base de journal 2 sur 256, ce qui équivaut à 8 (les bits utilisés pour l'adresse de l'hôte), puis nous soustrayons ce 8 de 32, ce qui équivaut à 24. (les bits utilisés pour l’adresse réseau).

Nous convertissons ensuite en entier car Math.log2 renvoie un float.

Conversion rapide et sale:

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

= > Je divise un masque dans un tableau

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

= > Pour chaque élément du tableau:

.to_i

= > Convertir en entier

.to_s (2)

= > Convertir un entier en binaire

.rjust (8, "0")

= > Ajouter un rembourrage

= > Carte retourne un tableau avec la même cardinalité

.join

= > Convertir un tableau en chaîne complète

.count ("1")

= > Comptez " 1 " caractères = > Donner un masque 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"

Si vous n'avez pas besoin d'utiliser l'adresse IP gem, vous pouvez le faire avec le netaddr bijou

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"

Le code réalise le masquage en accédant à la variable d'instance privée * @ mask_addr) de l'instance IPAddr (adresse, passée à serialize_ipaddr). Ce n’est pas recommandé (car les variables d’instance ne font pas partie de l’API publique des classes, mais ici, c’est mieux que d’analyser la chaîne de #inspect à mon avis.

Le processus est donc le suivant:

  1. Récupère la variable d'instance @mask_addr qui représente le masque de réseau
  2. Obtenez sa représentation binaire, par exemple 255.255.255.0 - > 4294967040 - > 1111111111111111111111110000000000
  3. Comptez le nombre 1-s du nombre base 2 pour obtenir le masque CIDR (24)
  4. Créez une chaîne comprenant l'adresse & amp; masque

EDIT: ajout d'une explication à la mise en oeuvre comme demandé par NathanOliver

Voici un moyen de le faire sans la gemme IPAddr

(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top