networking - una - subneteo vlsm
¿Cuál es la mejor manera de convertir del bitcount de la red a la máscara de red? (9)
Aquí hay una solución en VBScript, FWIW
option explicit
''whatmask 72.20.10.0/24
If WScript.Arguments.Unnamed.Count < 1 Then
WScript.Echo "WhatMask xxx.xxx.xxx.xxx/xx"
Wscript.Quit
End If
Dim sToFind
Dim aParts
Dim nSubnet
sToFind = WScript.Arguments(0)
aParts = Split( sToFind, "/", 2 )
nSubnet = aParts(1)
if nSubnet < 1 or nSubnet > 32 then
WScript.echo "Subnet out of range [1..32]"
Wscript.quit
end if
Dim sBinary
sBinary = String( nSubnet, "1")
sBinary = sBinary & String( 32 - nSubnet, "0" )
wscript.echo "0x" & lcase( binary2hexadecimal( sBinary ) )
function binary2hexadecimal( sBin )
dim sSlice
dim sResult
dim i
for i = 1 to len( sBin ) step 4
sSlice = mid( sBin, i, 4 )
sResult = sResult & hex( binary2decimal( sSlice ) )
next
binary2hexadecimal = sResult
end function
function binary2decimal( sFourbits )
dim i
dim bit
dim nResult
nResult = 0
for i = 4 to 1 step -1
bit = mid(sFourbits, i, 1 )
nResult = nResult * 2 + bit
next
binary2decimal = nResult
end function
Desde la línea de comando
>whatmask.vbs 123.12.123.17/23
0xfffff700
Por ejemplo, si tengo una especificación de red como 172.20.10.0/24, "24" es la bitcount. ¿Cuál es la mejor manera de convertir eso a una máscara de red como 0xffffff00?
Asumiendo máscara de 32 bits e int de 32 bits.
int keepBits = 24; /* actually get it from somewhere else? */
int mask = (0xffffffff >> (32 - keepBits )) << (32 - keepBits);
Nota: esta no es necesariamente la respuesta a la pregunta "¿Cuál es la mejor manera de obtener la máscara de red para una interfaz?"
Esta no es una pregunta de programación, pero en Linux puedes usar whatmask.
whatmask 72.20.10.0/24
devoluciones
IP Entered = ..................: 72.20.10.0
CIDR = ........................: /24
Netmask = .....................: 255.255.255.0
Netmask (hex) = ...............: 0xffffff00
Wildcard Bits = ...............: 0.0.0.255
------------------------------------------------
Network Address = .............: 72.20.10.0
Broadcast Address = ...........: 72.20.10.255
Usable IP Addresses = .........: 254
First Usable IP Address = .....: 72.20.10.1
Last Usable IP Address = ......: 72.20.10.254
Podrías probar algo simple, como tomar el bitcount y dividir por 4. Eso te daría las F''s principales en la máscara. Y luego tome el resto y cambie de 0 a 3 bits.
Siempre lo hago así (en tu caso cidr = 24):
uint32_t ipv4Netmask;
ipv4Netmask = 0xFFFFFFFF;
ipv4Netmask <<= 32 - cidr;
ipv4Netmask = ntohl(ipv4Netmask);
Esto solo funcionará con ipv4Netmask para ser realmente uint32_t, no lo haga int, ya que int no tiene que ser de 32 bits en cada sistema. El resultado se convierte en orden de bytes de red, ya que es lo que la mayoría de las funciones del sistema esperan.
int keepbits = 24;
int mask = keepbits > 0 ? 0x00 - (1<<(32 - keepbits)) : 0xFFFFFFFF;
¿Por qué perder tiempo con sustracción o declaraciones ternarias?
int suffix = 24;
int mask = 0xffffffff ^ 0xffffffff >> suffix;
Si sabes que tu entero tiene exactamente 32 bits de largo, entonces solo necesitas escribir 0xffffffff una vez.
int32_t mask = ~(0xffffffff >> suffix);
Ambos compilan exactamente el mismo código de ensamblaje.
Tenga cuidado cuando use las respuestas anteriores con un código como:
0xFFFFFFFF << 32 - cidr
o
-1 << 32 - cidr
En C # al menos, enmascarará el conteo de turnos con 0x1F primero. Entonces, para un cidr con el prefijo 0 (es decir, el rango completo de direcciones IPv4):
int cidr=0;
0xFFFFFFFF << (32 - cidr) == 0xFFFFFFFF
que no es lo que quieres En cambio, debes usar:
int cidr=0;
(int)(0xFFFFFFFFL << (32 - cidr)) == 0
/* C# version merging some of the other contributions and corrected for byte order. */
int cidr = 24;
var ipv4Netmask = 0xFFFFFFFF;
ipv4Netmask <<= 32 - cidr;
byte[] bytes = BitConverter.GetBytes(ipv4Netmask);
Array.Reverse(bytes);
ipv4Netmask = BitConverter.ToUInt32(bytes, 0);
// mask is now ready for use such as:
var netmask = new IPAddress(ipv4Netmask);