Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why IP returned by net.ParseIP length is 16 but the length of net.ParseNet.IP is 4? #41214

Closed
chartol opened this issue Sep 4, 2020 · 11 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@chartol
Copy link

chartol commented Sep 4, 2020

What version of Go are you using (go version)?

$ go version
go version go1.14.6 linux/amd64

Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/dongxifu/.cache/go-build"
GOENV="/home/dongxifu/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/dongxifu/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build070622505=/tmp/go-build -gno-record-gcc-switches"

What did you do?

What did you expect to see?

The length of IP returned by net.ParseIP should equal to net.ParseCIDR's IP, or will make me confused

What did you see instead?

@davecheney
Copy link
Contributor

@chartol can you please update your issue with a piece of sample code that demonstrates the issue. Thank you.

@davecheney davecheney added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Sep 4, 2020
@davecheney
Copy link
Contributor

Possible duplicate of #40606

@chartol
Copy link
Author

chartol commented Sep 4, 2020

// listIPsInRange will list all the ips in range, the range will be the whole network
// when begin and end is empty.
func listIPsInRange(cidr string, begin string, end string) (ips []string) {
	// convert string to IPNet struct
	_, ipv4Net, _ := net.ParseCIDR(cidr)
	mask := binary.BigEndian.Uint32(ipv4Net.Mask)

	var start uint32
	var finish uint32
	if begin != "" && end != "" {
		beginIP := net.ParseIP(begin)
		beginB := beginIP[12:]           // But the IP returned by ParseIP is 16 bytes, I have to split it.
		endIP := net.ParseIP(end)
		endB := endIP[12:]                // But the IP returned by ParseIP is 16 bytes, I have to split it.
		start = binary.BigEndian.Uint32(beginB)   
		finish = binary.BigEndian.Uint32(endB)
	} else {
		start = binary.BigEndian.Uint32(ipv4Net.IP)   // The IPNet.IP can transfer easily like this.
		finish = (start & mask) | (mask ^ 0xffffffff)
	}

	// loop through addresses as uint32
	for i := start; i <= finish; i++ {
		// convert back to net.IP
		ip := make(net.IP, 4)
		binary.BigEndian.PutUint32(ip, i)
		fmt.Println(ip)
		ips = append(ips, ip.String())
	}

	if begin != "" && end != "" {
		return ips
	}

	// Ignore network address and broadcast address
	return ips[1 : len(ips)-1]
}

@davecheney
Copy link
Contributor

davecheney commented Sep 4, 2020

What are the values of cidr, begin, and end you used?

@chartol
Copy link
Author

chartol commented Sep 4, 2020

@davecheney I want get a ip list between begin IP and end IP of a CIDR.
cidr, begin and end input examples:
192.168.9.0/24 192.168.9.20 192.168.9.30
output:
[192.168.9.20, 192.168.9.21...192.168.9.30]
issue #40606 is exactly same as mine.

@chartol
Copy link
Author

chartol commented Sep 4, 2020

@davecheney I want a ip list between begin IP and end IP of a CIDR.
cidr, begin and end input examples:

192.168.9.0/24 192.168.9.20 192.168.9.30

output:

[192.168.9.20, 192.168.9.21...192.168.9.30]

issue #40606 is exactly same as mine.

@chartol
Copy link
Author

chartol commented Sep 4, 2020

What I mean is that IPNet.IP is different from net.IP, one is 16 bytes which contains IP and mask, the other is 4 bytes which contains IP only. I think the net library should have a description at least. Or make me so confused.

@davecheney
Copy link
Contributor

Here is a smaller reproduction

package main

import (
	"fmt"
	"net"
)

func main() {
	begin := "192.168.9.20"
	beginIP := net.ParseIP(begin)
	beginB := beginIP[12:]
	fmt.Println(len(beginIP), len(beginB))
}

@chartol
Copy link
Author

chartol commented Sep 4, 2020

$ cat test.go 
package main

import (
	"fmt"
	"net"
)

func main() {
	cidr := "192.168.9.20/24"
	_, netIP, _ := net.ParseCIDR(cidr)
	begin := "192.168.9.20"
	beginIP := net.ParseIP(begin)
	beginB := beginIP[12:]
	fmt.Println(len(beginIP), len(beginB), len(netIP.IP))
}
$ go run test.go 
16 4 4

So why the length of netIP.IP returned by net.ParseCIDR is 4 but 16?

@davecheney
Copy link
Contributor

So why the length of netIP.IP returned by net.ParseCIDR is 4 but 16?

The only answer I have is, this is just how it works. If you want to assert that the address is an ipv4 address is to call the To4 method.

I don't think this is a bug, just an limitation of the standard library. This is likely a duplicate of #18804

@chartol
Copy link
Author

chartol commented Sep 4, 2020

OK, fine, issue closed.

@chartol chartol closed this as completed Sep 4, 2020
@golang golang locked and limited conversation to collaborators Sep 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

3 participants