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

ipv6 header was stripped from the ip packets in packetConn read apis #40143

Closed
yusong0926 opened this issue Jul 10, 2020 · 6 comments
Closed

ipv6 header was stripped from the ip packets in packetConn read apis #40143

yusong0926 opened this issue Jul 10, 2020 · 6 comments

Comments

@yusong0926
Copy link

@yusong0926 yusong0926 commented Jul 10, 2020

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

$ go version
go version go1.14.1 darwin/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=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/songyu/Library/Caches/go-build"
GOENV="/Users/songyu/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/songyu/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/82/ywnjzhzn0bv_9w46jyyxp5kh0000gp/T/go-build674890034=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

tried all apis (ipConn, icmp packetConn), couldn't get ip header from the ip packets especially for ipv6 using read or readFrom api.

func main() {
conn, err := icmp.ListenPacket("ip6:ipv6-icmp", "::")
if err != nil {
log.Fatal(err)
}

for {
    var msg []byte
    length, sourceIP, err := conn.ReadFrom(msg)
   //msg was only the payload of the packets, ipv6 header was stripped from it. I want to get hopLimit from the header
    if err != nil {
        log.Println(err)
        continue
    }

    log.Printf("message = '%s', length = %d, source-ip = %s", string(msg), length, sourceIP)
}
_ = conn.Close()

}

What did you expect to see?

read ipv6 header and read hopLimit or ttl from ip header for icmp packets.

What did you see instead?

ipv6 header was stripped. Read or readfrom only receive ip payload.

@davecheney
Copy link
Contributor

@davecheney davecheney commented Jul 10, 2020

Can you please provide some sample code. Thank you.

@yusong0926
Copy link
Author

@yusong0926 yusong0926 commented Jul 10, 2020

@davecheney added

@acln0
Copy link
Contributor

@acln0 acln0 commented Jul 10, 2020

Go is only giving you what the operating system network stack is giving you. Here is the relevant code:

Here, package icmp selects the protocol for the ip6 transport. Here, it calls net.ListenPacket in order to create the socket. Through ListenConfig, it ends up calling listenIP on a *net.sysDialer. listenIP calls internetSocket, which is a thin wrapper around socket. Moving back up the stack, the netFD created in socket is wrapped in an *IPConn and returned as the net.PacketConn implementation from ListenPacket.

When you call ReadFrom on an *IPConn, the inner implementation is only a thin wrapper around (*poll.FD).ReadFrom, which, itself, is a thin wrapper around syscall.Recvfrom.

Based on this, it is my understanding that none of the Go code in your call stack strips IPv6 headers away. A C program which calls socket(), bind(), followed by recvfrom(), would also not return the IPv6 headers, as far as I can tell. Perhaps there is another way to tell the operating system to return this data to you, but I am not aware of it. Perhaps something connected with using recvmsg() and requesting it in the ancillary data section? I skimmed through the man pages for a little bit, but I couldn't find anything.

@davecheney
Copy link
Contributor

@davecheney davecheney commented Jul 10, 2020

@yusong0926 could you describe a little more what you mean by IPv6 header? Do you mean the ethernet frame data?

@seankhliao
Copy link
Contributor

@seankhliao seankhliao commented Jul 10, 2020

@yusong0926 L2/L3 headers are only accessible through raw sockets, you'll need to make syscalls to get them, as explained in https://css.bz/2016/12/08/go-raw-sockets.html

@davecheney
Copy link
Contributor

@davecheney davecheney commented Jul 10, 2020

Closing, answered. Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.

For asking questions, see:

@davecheney davecheney closed this Jul 10, 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
4 participants
You can’t perform that action at this time.