たとえば、172.20.10.0/24 のようなネットワーク仕様がある場合、「24」がビット数です。それを 0xffffff00 のようなネットマスクに変換する最良の方法は何ですか?
9 に答える
32 ビットのマスクと 32 ビットの整数を想定しています。
int keepBits = 24; /* actually get it from somewhere else? */
int mask = (0xffffffff >> (32 - keepBits )) << (32 - keepBits);
注: これは必ずしも「インターフェイスのネットワーク マスクを取得する最善の方法は何ですか?」という質問に対する答えではありません。
私はいつもそのようにしています(あなたの場合cidr = 24):
uint32_t ipv4Netmask;
ipv4Netmask = 0xFFFFFFFF;
ipv4Netmask <<= 32 - cidr;
ipv4Netmask = htonl(ipv4Netmask);
これは、ipv4Netmask が実際に uint32_t である場合にのみ機能します。すべてのシステムで int が 32 ビットである必要はないため、int にしないでください。結果は、ほとんどのシステム関数が期待するネットワーク バイト オーダーに変換されます。
がゼロの場合、このコードは失敗することに注意してください。コードcidrは 32 ビット変数を 32 ビットシフトするため、信じられないかもしれませんが、これは C では定義されていない動作です。結果は常にゼロであると予想されますが、C 標準では、これはそもそも定義されていません。CIDR がゼロになる可能性がある場合 (これは、任意の IP アドレス プレースホルダー 0.0.0.0/0 でのみ許可されます)、コードは特殊なケースをキャッチする必要があります。
減算や 3 項ステートメントで時間を無駄にするのはなぜですか?
int suffix = 24;
int mask = 0xffffffff ^ 0xffffffff >> suffix;
整数の長さが正確に 32 ビットであることがわかっている場合は、0xffffffff と入力する必要があるのは 1 回だけです。
int32_t mask = ~(0xffffffff >> suffix);
どちらもまったく同じアセンブリ コードにコンパイルされます。
これはプログラミングに関する質問ではありませんが、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
int keepbits = 24;
int mask = keepbits > 0 ? 0x00 - (1<<(32 - keepbits)) : 0xFFFFFFFF;
次のようなコードで以前の回答を使用する場合は注意してください。
0xFFFFFFFF << 32 - cidr
また
-1 << 32 - cidr
少なくとも C# では、最初に 0x1F でシフト カウントをマスクします。したがって、プレフィックス 0 (つまり、IPv4 アドレス範囲全体) を持つ cidr の場合:
int cidr=0;
0xFFFFFFFF << (32 - cidr) == 0xFFFFFFFF
これはあなたが望むものではありません。代わりに、次を使用する必要があります。
int cidr=0;
(int)(0xFFFFFFFFL << (32 - cidr)) == 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
ビット数を取得して 4 で除算するなど、簡単なことを試すことができます。これにより、マスク内の先頭の F が得られます。そして余りを取って、0 ビットから 3 ビットに切り替えます。
/* 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);