mirror of
https://github.com/soypat/lneto.git
synced 2026-09-14 02:29:33 +00:00
V2 Netbird integration - UDP MIMO/SIMO, ICMPv6, DHCPv6 implementations (#106)
* 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
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
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:]
|
||||
}
|
||||
Reference in New Issue
Block a user