views:

2104

answers:

8

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  A: 

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
Eric Hogue
A: 

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.

kchau
+2  A: 

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?"

tvanfosson
Another one that assumes keepBits > 0.
bk1e
Actually, I set keepBits equal to 24 so it is by definition > 0
tvanfosson
And less than 32...
tvanfosson
+2  A: 
int keepbits = 24;
int mask = keepbits > 0 ? 0x00 - (1<<(32 - keepbits)) : 0xFFFFFFFF;
Robert
What if keepbits == 0? Watch out, those integer overflows will get you.
bk1e
If keepbits is 0, then the '1' will shift all the way out of the register (assuming 32-bit register) and the netmask will be 0. Isn't that the correct answer?
Robert
http://en.wikipedia.org/wiki/Bitwise_operation#Shifts_in_C.2C_C.2B.2B_and_Java says left-shift is undefined if an overflow occurs. MSVC and GCC both evaluate 1<<32 as 1, not 0.
bk1e
That's good to know. Thanks, bk1e.
Robert
int mask = keepbits > 0 ? 0x00 - (1<<(32 - keepbits)) : 0xFFFFFFFF;
Jon B
You should declare mask as uint32_t.
stepancheg
A: 

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

uint32_t ipv4Netmask;

ipv4Netmask = 0xFFFFFFFF;
ipv4Netmask <<= 32 - cidr;
ipv4Netmask = ntohl(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.

Mecki
A: 

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
boost
A: 

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.

joeforker
A: 
/* 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(mask);
Chris Weber