chrislovecnm
chrislovecnm

Reputation: 2619

Getting ipv6 subnet mask from net.CIDRMask

I am working on code, and trying to add ipv6 support. The following code is in the current code base for ipv4 support. The code takes a ipv4 ip address and gets the subnet mask for the address on a /32.

// string of ip address
networkInterface["ip_address"] = v.IpAddress[0]
m := net.CIDRMask(v.IpConfig.IpAddress[0].PrefixLength, 32)
subnetMask := net.IPv4(m[0], m[1], m[2], m[3])
networkInterface["subnet_mask"] = subnetMask.String()

I know that net.CIDRMask works with ipv6, I am uncertain how to use it with an ipv6 address.

I am now testing the ip address to determine if the address is ipv4 or ipv6:

testInput := net.ParseIP(v.IpAddress[0])
if testInput.To4() != nil {
// find ipv4 subnet mask
}
if testInput.To16() != nil {
// do ipv6 subnet mask
}

The unit tests for net.CIDRMask have examples working with ipv6 located here: https://golang.org/src/net/ip_test.go

But it is beyond both my golang experience and ipv6 knowledge.

While RTFM'ing the docs https://golang.org/pkg/net/#CIDRMask mention:

func CIDRMask(ones, bits int) IPMask

CIDRMask returns an IPMask consisting of `ones' 1 bits followed by 0s up to a total length of `bits' bits. For a mask of this form, CIDRMask is the inverse of IPMask.Size.

So what values do I use for ones and bits?

This is what is comming back from the api:

$ govc vm.info -json vcsa | jq .VirtualMachines[0].Guest.Net[0].IpConfig.IpAddress [   {
    "IpAddress": "10.20.128.218",
    "PrefixLength": 22,
    "Origin": "",
    "State": "preferred",
    "Lifetime": null   } ]

Thanks in advance!

Upvotes: 0

Views: 2125

Answers (1)

Amit Kumar Gupta
Amit Kumar Gupta

Reputation: 18597

I'm not sure what PrefixLength is, it may be some field defined in one of your structs, but it doesn't appear to be a field on anything in the net package, or in fact anywhere in the standard library: https://golang.org/search?q=PrefixLength.

So I'm not sure what PrefixLength is expected to give, but, I can tell you:

  • IPv4 addresses consist of 32 bits of data (256 x 256 x 256 x 256 total IPs), so when dealing with IPv4, the value for the bits argument to net.CIDRMask should be 32.
  • IPv4 addresses have 128 bits of data, so the bits argument is 128.
  • The subnet mask for a CIDR range corresponding to a single IP will have the maximum number of ones, so the ones value is 32 or 128, depending on whether you're talking IPv4 or IPv6.

Therefore, for IPv4, you should call net.CIDRMask(32, 32), and for IPv6, net.CIDRMask(128, 128). Since these will be the exact same calculations every time, you have the option to simply set the values up front as constants in your code. The correct values are:

Upvotes: 1

Related Questions