2020-06-04 22:42:44 +00:00
|
|
|
// Copyright (c) 2020 Tailscale Inc & 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 packet
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
type ICMP4Type uint8
|
2020-06-04 22:42:44 +00:00
|
|
|
|
|
|
|
const (
|
2020-11-09 23:34:03 +00:00
|
|
|
ICMP4EchoReply ICMP4Type = 0x00
|
|
|
|
ICMP4EchoRequest ICMP4Type = 0x08
|
|
|
|
ICMP4Unreachable ICMP4Type = 0x03
|
|
|
|
ICMP4TimeExceeded ICMP4Type = 0x0b
|
2020-06-04 22:42:44 +00:00
|
|
|
)
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
func (t ICMP4Type) String() string {
|
2020-06-04 22:42:44 +00:00
|
|
|
switch t {
|
2020-11-09 23:34:03 +00:00
|
|
|
case ICMP4EchoReply:
|
2020-06-04 22:42:44 +00:00
|
|
|
return "EchoReply"
|
2020-11-09 23:34:03 +00:00
|
|
|
case ICMP4EchoRequest:
|
2020-06-04 22:42:44 +00:00
|
|
|
return "EchoRequest"
|
2020-11-09 23:34:03 +00:00
|
|
|
case ICMP4Unreachable:
|
2020-06-04 22:42:44 +00:00
|
|
|
return "Unreachable"
|
2020-11-09 23:34:03 +00:00
|
|
|
case ICMP4TimeExceeded:
|
2020-06-04 22:42:44 +00:00
|
|
|
return "TimeExceeded"
|
|
|
|
default:
|
|
|
|
return "Unknown"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
type ICMP4Code uint8
|
2020-06-04 22:42:44 +00:00
|
|
|
|
|
|
|
const (
|
2020-11-09 23:34:03 +00:00
|
|
|
ICMP4NoCode ICMP4Code = 0
|
2020-06-04 22:42:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ICMPHeader represents an ICMP packet header.
|
2020-11-09 23:34:03 +00:00
|
|
|
type ICMP4Header struct {
|
|
|
|
IP4Header
|
|
|
|
Type ICMP4Type
|
|
|
|
Code ICMP4Code
|
2020-06-04 22:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
icmpHeaderLength = 4
|
|
|
|
// icmpTotalHeaderLength is the length of all headers in a ICMP packet.
|
|
|
|
icmpAllHeadersLength = ipHeaderLength + icmpHeaderLength
|
|
|
|
)
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
func (ICMP4Header) Len() int {
|
2020-06-04 22:42:44 +00:00
|
|
|
return icmpAllHeadersLength
|
|
|
|
}
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
func (h ICMP4Header) Marshal(buf []byte) error {
|
2020-06-04 22:42:44 +00:00
|
|
|
if len(buf) < icmpAllHeadersLength {
|
|
|
|
return errSmallBuffer
|
|
|
|
}
|
|
|
|
if len(buf) > maxPacketLength {
|
|
|
|
return errLargePacket
|
|
|
|
}
|
|
|
|
// The caller does not need to set this.
|
|
|
|
h.IPProto = ICMP
|
|
|
|
|
|
|
|
buf[20] = uint8(h.Type)
|
|
|
|
buf[21] = uint8(h.Code)
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
h.IP4Header.Marshal(buf)
|
2020-06-04 22:42:44 +00:00
|
|
|
|
|
|
|
put16(buf[22:24], ipChecksum(buf))
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-09 23:34:03 +00:00
|
|
|
func (h *ICMP4Header) ToResponse() {
|
|
|
|
// TODO: this doesn't implement ToResponse correctly, as it
|
|
|
|
// assumes the ICMP request type.
|
|
|
|
h.Type = ICMP4EchoReply
|
|
|
|
h.Code = ICMP4NoCode
|
|
|
|
h.IP4Header.ToResponse()
|
2020-06-04 22:42:44 +00:00
|
|
|
}
|