mirror of
https://github.com/soypat/lneto.git
synced 2026-08-16 12:53:26 +00:00
7d5830d7ab
* begin adding udp.MuxHandler * add udp MuxHandlerSIMO/MIMO * add tcp rx shutdown * icmpv6 client * icmpv6 Client shared NDP/Echo preparation * icmpv6 client ndp/echo split * icmpv6 client ndp/echo split done * icmpv6 adjustments * add dhcpv6 stubs * dhcpv4 preliminary revision * add dns.NextLabel * dns label name tweaks * dns begin work on TCP client * add dnstcp package * apply gofmt changes * add udp mux tests * clean up, remove StackBig for now * remove dnstcp so as to merged confident parts and we continue dnstcp work elsewhere
224 lines
6.2 KiB
Go
224 lines
6.2 KiB
Go
package icmpv6
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"github.com/soypat/lneto"
|
|
)
|
|
|
|
//go:generate stringer -type=Type,CodeDestinationUnreachable,CodeParameterProblem -linecomment -output stringers.go
|
|
|
|
const (
|
|
sizeHeader = 8
|
|
sizeNDPBase = sizeHeader + 16 // 24: ICMPv6 header + 16-byte target address
|
|
sizeNDPOption = 8 // 1 type + 1 len + 6 MAC (Ethernet link-layer option, RFC 4861 §4.6.1)
|
|
sizeNDP = sizeNDPBase + sizeNDPOption
|
|
)
|
|
|
|
type Type uint8
|
|
|
|
const (
|
|
TypeDestinationUnreachable Type = 1 // destination unreachable
|
|
TypePacketTooBig Type = 2 // packet too big
|
|
TypeTimeExceeded Type = 3 // time exceeded
|
|
TypeParameterProblem Type = 4 // parameter problem
|
|
|
|
TypeEchoRequest Type = 128 // echo request
|
|
TypeEchoReply Type = 129 // echo reply
|
|
|
|
TypeRouterSolicitation Type = 133 // router solicitation
|
|
TypeRouterAdvertisement Type = 134 // router advertisement
|
|
TypeNeighborSolicitation Type = 135 // neighbor solicitation
|
|
TypeNeighborAdvertisement Type = 136 // neighbor advertisement
|
|
TypeRedirectMessage Type = 137 // redirect message
|
|
)
|
|
|
|
type CodeTimeExceeded uint8
|
|
|
|
const (
|
|
CodeHopLimitExceeded CodeTimeExceeded = iota // hop limit exceeded in transit
|
|
CodeFragmentReassembly // fragment reassembly time exceeded
|
|
)
|
|
|
|
type CodeDestinationUnreachable uint8
|
|
|
|
const (
|
|
CodeNoRoute CodeDestinationUnreachable = iota // no route to destination
|
|
CodeAdminProhibited // communication administratively prohibited
|
|
CodeBeyondScope // beyond scope of source address
|
|
CodeAddressUnreachable // address unreachable
|
|
CodePortUnreachable // port unreachable
|
|
CodeIngressEgressPolicy // source address failed ingress/egress policy
|
|
CodeRejectRoute // reject route to destination
|
|
)
|
|
|
|
type CodeParameterProblem uint8
|
|
|
|
const (
|
|
CodeErroneousHeaderField CodeParameterProblem = iota // erroneous header field encountered
|
|
CodeUnrecognizedNextHeader // unrecognized next header type encountered
|
|
CodeUnrecognizedIPv6Option // unrecognized IPv6 option encountered
|
|
)
|
|
|
|
func NewFrame(buf []byte) (Frame, error) {
|
|
if len(buf) < sizeHeader {
|
|
return Frame{}, lneto.ErrTruncatedFrame
|
|
}
|
|
return Frame{buf: buf}, nil
|
|
}
|
|
|
|
type Frame struct {
|
|
buf []byte
|
|
}
|
|
|
|
func (frm Frame) Type() Type { return Type(frm.buf[0]) }
|
|
|
|
func (frm Frame) SetType(t Type) { frm.buf[0] = uint8(t) }
|
|
|
|
func (frm Frame) Code() uint8 { return frm.buf[1] }
|
|
|
|
func (frm Frame) SetCode(code uint8) { frm.buf[1] = code }
|
|
|
|
// CRC returns the checksum field of the frame.
|
|
func (frm Frame) CRC() uint16 {
|
|
return binary.BigEndian.Uint16(frm.buf[2:4])
|
|
}
|
|
|
|
// SetCRC sets the checksum field of the frame.
|
|
func (frm Frame) SetCRC(crc uint16) {
|
|
binary.BigEndian.PutUint16(frm.buf[2:4], crc)
|
|
}
|
|
|
|
func (frm Frame) payload() []byte {
|
|
return frm.buf[4:]
|
|
}
|
|
|
|
type FrameDestinationUnreachable struct {
|
|
Frame
|
|
}
|
|
|
|
func (frm FrameDestinationUnreachable) Code() CodeDestinationUnreachable {
|
|
return CodeDestinationUnreachable(frm.Frame.Code())
|
|
}
|
|
|
|
func (frm FrameDestinationUnreachable) SetCode(code CodeDestinationUnreachable) {
|
|
frm.Frame.SetCode(uint8(code))
|
|
}
|
|
|
|
type FramePacketTooBig struct {
|
|
Frame
|
|
}
|
|
|
|
func (frm FramePacketTooBig) MTU() uint32 {
|
|
return binary.BigEndian.Uint32(frm.buf[4:8])
|
|
}
|
|
|
|
func (frm FramePacketTooBig) SetMTU(mtu uint32) {
|
|
binary.BigEndian.PutUint32(frm.buf[4:8], mtu)
|
|
}
|
|
|
|
type FrameParameterProblem struct {
|
|
Frame
|
|
}
|
|
|
|
func (frm FrameParameterProblem) Code() CodeParameterProblem {
|
|
return CodeParameterProblem(frm.Frame.Code())
|
|
}
|
|
|
|
func (frm FrameParameterProblem) SetCode(code CodeParameterProblem) {
|
|
frm.Frame.SetCode(uint8(code))
|
|
}
|
|
|
|
// Pointer identifies the octet offset within the invoking packet where the error was detected.
|
|
func (frm FrameParameterProblem) Pointer() uint32 {
|
|
return binary.BigEndian.Uint32(frm.buf[4:8])
|
|
}
|
|
|
|
func (frm FrameParameterProblem) SetPointer(ptr uint32) {
|
|
binary.BigEndian.PutUint32(frm.buf[4:8], ptr)
|
|
}
|
|
|
|
type FrameEcho struct {
|
|
Frame
|
|
}
|
|
|
|
func (frm FrameEcho) Identifier() uint16 {
|
|
return binary.BigEndian.Uint16(frm.buf[4:6])
|
|
}
|
|
|
|
func (frm FrameEcho) SetIdentifier(id uint16) {
|
|
binary.BigEndian.PutUint16(frm.buf[4:6], id)
|
|
}
|
|
|
|
func (frm FrameEcho) SequenceNumber() uint16 {
|
|
return binary.BigEndian.Uint16(frm.buf[6:8])
|
|
}
|
|
|
|
func (frm FrameEcho) SetSequenceNumber(seq uint16) {
|
|
binary.BigEndian.PutUint16(frm.buf[6:8], seq)
|
|
}
|
|
|
|
func (frm FrameEcho) Data() []byte {
|
|
return frm.buf[8:]
|
|
}
|
|
|
|
func (frm FrameEcho) RawData() []byte {
|
|
return frm.buf
|
|
}
|
|
|
|
// FrameNeighborSolicitation accesses a Neighbor Solicitation message (RFC 4861 §4.3).
|
|
// Layout after ICMPv6 base header: Reserved(4B) | TargetAddr(16B) | Options.
|
|
type FrameNeighborSolicitation struct {
|
|
Frame
|
|
}
|
|
|
|
// TargetAddr returns the IPv6 address being queried.
|
|
func (frm FrameNeighborSolicitation) TargetAddr() *[16]byte {
|
|
return (*[16]byte)(frm.buf[8:24])
|
|
}
|
|
|
|
// Options returns the bytes following the fixed header for parsing NDP options.
|
|
func (frm FrameNeighborSolicitation) Options() []byte {
|
|
return frm.buf[24:]
|
|
}
|
|
|
|
// FrameNeighborAdvertisement accesses a Neighbor Advertisement message (RFC 4861 §4.4).
|
|
// Layout after ICMPv6 base header: R|S|O|Reserved(4B) | TargetAddr(16B) | Options.
|
|
type FrameNeighborAdvertisement struct {
|
|
Frame
|
|
}
|
|
|
|
// Flags returns the R (router), S (solicited), O (override) flag bits.
|
|
func (frm FrameNeighborAdvertisement) Flags() (router, solicited, override bool) {
|
|
b := frm.buf[4]
|
|
return b&0x80 != 0, b&0x40 != 0, b&0x20 != 0
|
|
}
|
|
|
|
// SetFlags sets the R, S, O flags and zeroes the reserved bits.
|
|
func (frm FrameNeighborAdvertisement) SetFlags(router, solicited, override bool) {
|
|
var b byte
|
|
if router {
|
|
b |= 0x80
|
|
}
|
|
if solicited {
|
|
b |= 0x40
|
|
}
|
|
if override {
|
|
b |= 0x20
|
|
}
|
|
frm.buf[4] = b
|
|
frm.buf[5] = 0
|
|
frm.buf[6] = 0
|
|
frm.buf[7] = 0
|
|
}
|
|
|
|
// TargetAddr returns the IPv6 address being announced.
|
|
func (frm FrameNeighborAdvertisement) TargetAddr() *[16]byte {
|
|
return (*[16]byte)(frm.buf[8:24])
|
|
}
|
|
|
|
// Options returns the bytes following the fixed header for parsing NDP options.
|
|
func (frm FrameNeighborAdvertisement) Options() []byte {
|
|
return frm.buf[24:]
|
|
}
|