从网络bitcount转换为网络掩码的最佳方法是什么?

时间:2008-10-20 14:17:32

标签: networking bit-manipulation

例如,如果我有像172.20.10.0/24这样的网络规范,那么“24”就是bitcount。将其转换为像0xffffff00这样的网络掩码的最佳方法是什么?

9 个答案:

答案 0 :(得分:7)

假设32位掩码和32位int。

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

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

注意:这不一定是“获取接口的网络掩码的最佳方法是什么?”这个问题的答案。

答案 1 :(得分:3)

我总是这样做(在你的情况下是cidr = 24):

uint32_t ipv4Netmask;

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

这只适用于ipv4Netmask实际上是uint32_t,不要使它成为int,因为int不必是每个系统上的32位。结果转换为网络字节顺序,这是大多数系统功能所期望的。

请注意,如果cidr为零,则此代码将失败,因为代码会将32位变量移位32位,不管您信不信,这是C中未定义的行为。可以预期结果为总是为零,但C标准说这不是定义为开始。如果您的CIDR可以为零(只允许在任何IP地址占位符0.0.0.0/0中),那么代码必须捕获特殊情况。

答案 2 :(得分:1)

这不是编程问题,但在linux中你可以使用whatmask。

whatmask 72.20.10.0/24

返回

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

为什么要用减法或三元语句来浪费时间?

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

如果您知道您的整数正好是32位长,那么您只需要输入0xffffffff一次。

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

两者都编译为完全相同的汇编代码。

答案 5 :(得分:0)

这是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

从命令行

>whatmask.vbs 123.12.123.17/23
 0xfffff700

答案 6 :(得分:0)

使用以下代码时请注意:

0xFFFFFFFF << 32 - cidr

-1 << 32 - cidr

至少在C#中,它会先用0x1F屏蔽移位计数。因此,对于前缀为0的cidr(即整个IPv4地址范围):

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

这不是你想要的。相反,你应该使用:

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

答案 7 :(得分:-1)

你可以尝试一些简单的事情,比如拿掉bitcount并除以4.这会让你在面具中领先F。然后取余数并从0位切换到3位。

答案 8 :(得分:-1)

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