.github
alerting
client
config
controller
core
docs
example
jsonpath
k8s
k8stest
metric
pattern
security
storage
util
vendor
cloud.google.com
github.com
go.etcd.io
golang.org
x
crypto
net
bpf
context
http
http2
icmp
dstunreach.go
echo.go
endpoint.go
extension.go
helper_posix.go
interface.go
ipv4.go
ipv6.go
listen_posix.go
listen_stub.go
message.go
messagebody.go
mpls.go
multipart.go
packettoobig.go
paramprob.go
sys_freebsd.go
timeexceeded.go
idna
internal
ipv4
ipv6
AUTHORS
CONTRIBUTORS
LICENSE
PATENTS
oauth2
sys
term
text
time
google.golang.org
gopkg.in
k8s.io
sigs.k8s.io
modules.txt
watchdog
web
.dockerignore
.gitattributes
.gitignore
Dockerfile
LICENSE.md
Makefile
README.md
config.yaml
go.mod
go.sum
main.go
174 lines
4.2 KiB
Go
174 lines
4.2 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package icmp
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"golang.org/x/net/internal/iana"
|
|
"golang.org/x/net/ipv4"
|
|
"golang.org/x/net/ipv6"
|
|
)
|
|
|
|
// An Echo represents an ICMP echo request or reply message body.
|
|
type Echo struct {
|
|
ID int // identifier
|
|
Seq int // sequence number
|
|
Data []byte // data
|
|
}
|
|
|
|
// Len implements the Len method of MessageBody interface.
|
|
func (p *Echo) Len(proto int) int {
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 4 + len(p.Data)
|
|
}
|
|
|
|
// Marshal implements the Marshal method of MessageBody interface.
|
|
func (p *Echo) Marshal(proto int) ([]byte, error) {
|
|
b := make([]byte, 4+len(p.Data))
|
|
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
|
binary.BigEndian.PutUint16(b[2:4], uint16(p.Seq))
|
|
copy(b[4:], p.Data)
|
|
return b, nil
|
|
}
|
|
|
|
// parseEcho parses b as an ICMP echo request or reply message body.
|
|
func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
|
|
bodyLen := len(b)
|
|
if bodyLen < 4 {
|
|
return nil, errMessageTooShort
|
|
}
|
|
p := &Echo{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(binary.BigEndian.Uint16(b[2:4]))}
|
|
if bodyLen > 4 {
|
|
p.Data = make([]byte, bodyLen-4)
|
|
copy(p.Data, b[4:])
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// An ExtendedEchoRequest represents an ICMP extended echo request
|
|
// message body.
|
|
type ExtendedEchoRequest struct {
|
|
ID int // identifier
|
|
Seq int // sequence number
|
|
Local bool // must be true when identifying by name or index
|
|
Extensions []Extension // extensions
|
|
}
|
|
|
|
// Len implements the Len method of MessageBody interface.
|
|
func (p *ExtendedEchoRequest) Len(proto int) int {
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
l, _ := multipartMessageBodyDataLen(proto, false, nil, p.Extensions)
|
|
return l
|
|
}
|
|
|
|
// Marshal implements the Marshal method of MessageBody interface.
|
|
func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error) {
|
|
var typ Type
|
|
switch proto {
|
|
case iana.ProtocolICMP:
|
|
typ = ipv4.ICMPTypeExtendedEchoRequest
|
|
case iana.ProtocolIPv6ICMP:
|
|
typ = ipv6.ICMPTypeExtendedEchoRequest
|
|
default:
|
|
return nil, errInvalidProtocol
|
|
}
|
|
if !validExtensions(typ, p.Extensions) {
|
|
return nil, errInvalidExtension
|
|
}
|
|
b, err := marshalMultipartMessageBody(proto, false, nil, p.Extensions)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
|
b[2] = byte(p.Seq)
|
|
if p.Local {
|
|
b[3] |= 0x01
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// parseExtendedEchoRequest parses b as an ICMP extended echo request
|
|
// message body.
|
|
func parseExtendedEchoRequest(proto int, typ Type, b []byte) (MessageBody, error) {
|
|
if len(b) < 4 {
|
|
return nil, errMessageTooShort
|
|
}
|
|
p := &ExtendedEchoRequest{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(b[2])}
|
|
if b[3]&0x01 != 0 {
|
|
p.Local = true
|
|
}
|
|
var err error
|
|
_, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// An ExtendedEchoReply represents an ICMP extended echo reply message
|
|
// body.
|
|
type ExtendedEchoReply struct {
|
|
ID int // identifier
|
|
Seq int // sequence number
|
|
State int // 3-bit state working together with Message.Code
|
|
Active bool // probed interface is active
|
|
IPv4 bool // probed interface runs IPv4
|
|
IPv6 bool // probed interface runs IPv6
|
|
}
|
|
|
|
// Len implements the Len method of MessageBody interface.
|
|
func (p *ExtendedEchoReply) Len(proto int) int {
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 4
|
|
}
|
|
|
|
// Marshal implements the Marshal method of MessageBody interface.
|
|
func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error) {
|
|
b := make([]byte, 4)
|
|
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
|
b[2] = byte(p.Seq)
|
|
b[3] = byte(p.State<<5) & 0xe0
|
|
if p.Active {
|
|
b[3] |= 0x04
|
|
}
|
|
if p.IPv4 {
|
|
b[3] |= 0x02
|
|
}
|
|
if p.IPv6 {
|
|
b[3] |= 0x01
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// parseExtendedEchoReply parses b as an ICMP extended echo reply
|
|
// message body.
|
|
func parseExtendedEchoReply(proto int, _ Type, b []byte) (MessageBody, error) {
|
|
if len(b) < 4 {
|
|
return nil, errMessageTooShort
|
|
}
|
|
p := &ExtendedEchoReply{
|
|
ID: int(binary.BigEndian.Uint16(b[:2])),
|
|
Seq: int(b[2]),
|
|
State: int(b[3]) >> 5,
|
|
}
|
|
if b[3]&0x04 != 0 {
|
|
p.Active = true
|
|
}
|
|
if b[3]&0x02 != 0 {
|
|
p.IPv4 = true
|
|
}
|
|
if b[3]&0x01 != 0 {
|
|
p.IPv6 = true
|
|
}
|
|
return p, nil
|
|
}
|