What's the best way to convert from network bitcount to netmask?

喜欢而已 提交于 2019-11-29 14:08:21

问题


For example, if I have a network spec like 172.20.10.0/24, "24" is the bitcount. What's the best way to convert that to a netmask like 0xffffff00 ?


回答1:


Why waste time with subtraction or ternary statements?

int suffix = 24;
int mask = 0xffffffff ^ 0xffffffff >> suffix;

If you know your integer is exactly 32 bits long then you only need to type 0xffffffff once.

int32_t mask = ~(0xffffffff >> suffix);

Both compile to the exact same assembly code.




回答2:


Assuming 32-bit mask and 32-bit int.

int keepBits = 24;  /* actually get it from somewhere else? */

int mask = (0xffffffff >> (32 - keepBits )) << (32 - keepBits);

Note: this isn't necessarily the answer to the question "What's the best way to get the network mask for an interface?"




回答3:


I always do it like that (in your case cidr = 24):

uint32_t ipv4Netmask;

ipv4Netmask = 0xFFFFFFFF;
ipv4Netmask <<= 32 - cidr;
ipv4Netmask = htonl(ipv4Netmask);

This will only work with ipv4Netmask to be actually uint32_t, don't make it int, as int doesn't have to be 32 Bit on every system. The result is converted to network byte order, as that's what most system functions expect.

Note that this code will fail if cidr is zero as then the code would shift a 32 bit variable by 32 bit and, believe it or not, that is undefined behavior in C. One would expect the result to always be zero but the C standard says that this is not defined to begin with. If your CIDR can be zero (which would only be allowed in the any IP address placeholder 0.0.0.0/0), then the code must catch special case.




回答4:


This is not a programming question, but in linux you can use whatmask.

whatmask 72.20.10.0/24

returns

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



回答5:


int keepbits = 24;
int mask = keepbits > 0 ? 0x00 - (1<<(32 - keepbits)) : 0xFFFFFFFF;



回答6:


Here's a solution in 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

From the command line

>whatmask.vbs 123.12.123.17/23
 0xfffff700



回答7:


Be careful when you use the previous answers with code like:

0xFFFFFFFF << 32 - cidr

or

-1 << 32 - cidr

In C# at least, it will mask the shift count with 0x1F first. So, for a cidr with prefix 0 (ie the entire IPv4 address range):

int cidr=0;
0xFFFFFFFF << (32 - cidr) == 0xFFFFFFFF

which is not what you want. Instead, you should use:

int cidr=0;
(int)(0xFFFFFFFFL << (32 - cidr)) == 0



回答8:


You could try something simple, like taking the bitcount and dividing by 4. That'd give you the leading F's in the mask. And then take the remainder and have a switch from 0 bits to 3 bits.




回答9:


/* 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);


来源:https://stackoverflow.com/questions/218604/whats-the-best-way-to-convert-from-network-bitcount-to-netmask

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!