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
Closed

Comments

@chartol
Copy link

@chartol 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

@davecheney davecheney commented Sep 4, 2020

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

@davecheney
Copy link
Contributor

@davecheney davecheney commented Sep 4, 2020

Possible duplicate of #40606

@chartol
Copy link
Author

@chartol 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 davecheney commented Sep 4, 2020

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

@chartol
Copy link
Author

@chartol 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 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 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

@davecheney davecheney commented Sep 4, 2020

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

@davecheney davecheney commented Sep 4, 2020

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 chartol commented Sep 4, 2020

OK, fine, issue closed.

@chartol chartol closed this Sep 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.