From 0606a04f450f90d4f63df9217c3d0ccadcf18087 Mon Sep 17 00:00:00 2001 From: soypat Date: Tue, 18 Feb 2025 18:48:55 -0300 Subject: [PATCH] arp working over network --- arp/definitions.go | 2 +- arp/frame.go | 28 +++- arp/stringers.go | 25 ++++ examples/stack/main.go | 92 ++++++++++-- ipv4/definitions.go | 38 +++++ ipv4/frame.go | 209 +++++++++++++++++++++++++++ ipv6/definitions.go | 9 ++ ipv6/frame.go | 101 ++++++++++++++ lneto2/stringers.go | 310 +++++++++++++++++++++++++++++++++++++++++ lneto2/validation.go | 2 +- stringers.go | 4 +- 11 files changed, 800 insertions(+), 20 deletions(-) create mode 100644 arp/stringers.go create mode 100644 ipv4/definitions.go create mode 100644 ipv4/frame.go create mode 100644 ipv6/definitions.go create mode 100644 ipv6/frame.go create mode 100644 lneto2/stringers.go diff --git a/arp/definitions.go b/arp/definitions.go index 7406bc0..da82f16 100644 --- a/arp/definitions.go +++ b/arp/definitions.go @@ -17,7 +17,7 @@ var ( ) // Operation represents the type of ARP packet, either request or reply/response. -type Operation uint8 +type Operation uint16 const ( OpRequest Operation = 1 // request diff --git a/arp/frame.go b/arp/frame.go index b830a70..21c01ec 100644 --- a/arp/frame.go +++ b/arp/frame.go @@ -3,6 +3,9 @@ package arp import ( "encoding/binary" "errors" + "fmt" + "net" + "net/netip" "github.com/soypat/lneto/lneto2" ) @@ -61,10 +64,10 @@ func (afrm Frame) SetProtocol(Type lneto2.EtherType, length uint8) { } // Operation returns the ARP header operation field. See [Operation]. -func (afrm Frame) Operation() Operation { return Operation(afrm.buf[6]) } +func (afrm Frame) Operation() Operation { return Operation(binary.BigEndian.Uint16(afrm.buf[6:8])) } // SetOperation sets the ARP header operation field. See [Operation]. -func (afrm Frame) SetOperation(b Operation) { afrm.buf[6] = uint8(b) } +func (afrm Frame) SetOperation(op Operation) { binary.BigEndian.PutUint16(afrm.buf[6:8], uint16(op)) } // Sender returns the hardware (MAC) and protocol addresses of sender of ARP packet. // In an ARP request MAC address is used to indicate @@ -139,3 +142,24 @@ func (afrm Frame) ValidateSize(v *lneto2.Validator) { v.AddError(errShortARP) } } + +func (afrm Frame) String() string { + opstr := afrm.Operation().String() + hwt, _ := afrm.Hardware() + ptt, _ := afrm.Protocol() + sndhw, sndpt := afrm.Sender() + tgthw, tgtpt := afrm.Target() + var sndstr, tgtstr string + if ptt == lneto2.EtherTypeIPv4 || ptt == lneto2.EtherTypeIPv6 { + sender, _ := netip.AddrFromSlice(sndpt) + target, _ := netip.AddrFromSlice(tgtpt) + sndstr = sender.String() + tgtstr = target.String() + } else { + sndstr = net.HardwareAddr(sndpt).String() + tgtstr = net.HardwareAddr(tgtpt).String() + } + return fmt.Sprintf("ARP %s HW=(%d,SENDER=%s,TARGET=%s) PROTO=(%s,SENDER=%s,TARGET=%s)", + opstr, hwt, net.HardwareAddr(sndhw).String(), net.HardwareAddr(tgthw).String(), + ptt.String(), sndstr, tgtstr) +} diff --git a/arp/stringers.go b/arp/stringers.go new file mode 100644 index 0000000..cd8d0c7 --- /dev/null +++ b/arp/stringers.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=Operation -linecomment -output stringers.go ."; DO NOT EDIT. + +package arp + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[OpRequest-1] + _ = x[OpReply-2] +} + +const _Operation_name = "requestreply" + +var _Operation_index = [...]uint8{0, 7, 12} + +func (i Operation) String() string { + i -= 1 + if i >= Operation(len(_Operation_index)-1) { + return "Operation(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _Operation_name[_Operation_index[i]:_Operation_index[i+1]] +} diff --git a/examples/stack/main.go b/examples/stack/main.go index ac2fcf2..b16452f 100644 --- a/examples/stack/main.go +++ b/examples/stack/main.go @@ -2,30 +2,42 @@ package main import ( "errors" + "fmt" "io" "log" "log/slog" - "math/rand" + "net" "net/netip" "github.com/soypat/lneto" + "github.com/soypat/lneto/arp" "github.com/soypat/lneto/internal" - "github.com/soypat/lneto/internal/ltesto" + "github.com/soypat/lneto/lneto2" "github.com/soypat/lneto/tcp" ) -const mtu = 2048 +const ( + mtu = 2048 + iface = "192.168.10.1/24" + stackIP = "192.168.10.2" + stackPort = 80 +) + +var stackHWAddr = [6]byte{0xc0, 0xff, 0xee, 0x00, 0xde, 0xad} func main() { - rng := rand.New(rand.NewSource(1)) - var gen ltesto.PacketGen - gen.RandomizeAddrs(rng) + ip := netip.MustParseAddr(stackIP) + iface := netip.MustParsePrefix(iface) + if !iface.Contains(ip) { + log.Fatal("interface does not contain stack address") + } + addrPort := netip.AddrPortFrom(ip, stackPort) slogger := logger{slog.Default()} - lStack, handler, err := NewEthernetTCPStack(gen.DstMAC, netip.AddrPortFrom(netip.AddrFrom4(gen.DstIPv4), gen.DstTCP), slogger) + lStack, handler, err := NewEthernetTCPStack(stackHWAddr, addrPort, slogger) if err != nil { log.Fatal(err) } - iface := netip.MustParsePrefix("192.168.10.1/24") + tap, err := internal.NewTap("tap0", iface) if err != nil { log.Fatal(err) @@ -80,10 +92,29 @@ func NewEthernetTCPStack(mac [6]byte, ip netip.AddrPort, slogger logger) (*LinkS tcpPortStack := &TCPPort{ handler: tcp.Handler{}, } + proto := lneto2.EtherTypeIPv4 + if ip.Addr().Is6() { + proto = lneto2.EtherTypeIPv6 + } + arphandler, err := arp.NewHandler(arp.HandlerConfig{ + HardwareAddr: mac[:], + ProtocolAddr: ip.Addr().AsSlice(), + MaxQueries: 1, + MaxPending: 1, + HardwareType: 1, + ProtocolType: proto, + }) + if err != nil { + return nil, nil, err + } + arpStack := ARPStack{ + handler: *arphandler, + } + port := ip.Port() txbuf := make([]byte, mtu) rxbuf := make([]byte, mtu) - err := tcpPortStack.handler.SetBuffers(txbuf, rxbuf, 3) + err = tcpPortStack.handler.SetBuffers(txbuf, rxbuf, 3) if err != nil { return nil, nil, err } @@ -91,7 +122,11 @@ func NewEthernetTCPStack(mac [6]byte, ip netip.AddrPort, slogger logger) (*LinkS if err != nil { return nil, nil, err } - err = lStack.Register(ipStack, [6]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) + err = lStack.Register(ipStack, mac) + if err != nil { + return nil, nil, err + } + err = lStack.Register(&arpStack, [6]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) if err != nil { return nil, nil, err } @@ -146,21 +181,24 @@ func (ls *LinkStack) RecvEth(ethFrame []byte) (err error) { if err != nil { return err } - if !efrm.IsBroadcast() && ls.mac != *efrm.DestinationHardwareAddr() { - return errors.New("packet MAC mismatch") + etype := efrm.EtherTypeOrSize() + dstaddr := efrm.DestinationHardwareAddr() + if !efrm.IsBroadcast() && ls.mac != *dstaddr { + return fmt.Errorf("incoming %s mismatch hwaddr %s", etype.String(), net.HardwareAddr(dstaddr[:]).String()) } var vld lneto.Validator efrm.ValidateSize(&vld) if err := vld.Err(); err != nil { return err } - etype := efrm.EtherTypeOrSize() + for i := range ls.handlers { h := &ls.handlers[i] if h.proto == uint32(etype) { return h.recv(efrm.Payload(), 0) } } + return nil } @@ -181,6 +219,7 @@ func (ls *LinkStack) HandleEth(dst []byte) (n int, err error) { copy(efrm.DestinationHardwareAddr()[:], h.raddr) *efrm.SourceHardwareAddr() = ls.mac efrm.SetEtherType(lneto.EtherType(h.proto)) + return n + 14, nil } } @@ -389,7 +428,32 @@ func (ts *TCPStack) Handle(ipFrame []byte, tcpOff int) (n int, err error) { crc = tfrm.CalculateIPv6CRC(ifrm) } tfrm.SetCRC(crc) - return tcpOff + n, nil + return n, nil +} + +type ARPStack struct { + handler arp.Handler +} + +func (as *ARPStack) Protocol() uint32 { return uint32(lneto.EtherTypeARP) } + +func (as *ARPStack) Recv(EtherFrame []byte, arpOff int) error { + afrm, _ := arp.NewFrame(EtherFrame[arpOff:]) + slog.Info("recv", slog.String("in", afrm.String())) + return as.handler.Recv(EtherFrame[arpOff:]) +} + +func (as *ARPStack) Handle(EtherFrame []byte, arpOff int) (int, error) { + n, err := as.handler.Send(EtherFrame[arpOff:]) + if err != nil || n == 0 { + return 0, err + } + afrm, _ := arp.NewFrame(EtherFrame[arpOff:]) + hwaddr, _ := afrm.Target() + efrm, _ := lneto.NewEthFrame(EtherFrame) + copy(efrm.DestinationHardwareAddr()[:], hwaddr) + slog.Info("handle", slog.String("out", afrm.String())) + return n, err } type TCPPort struct { diff --git a/ipv4/definitions.go b/ipv4/definitions.go new file mode 100644 index 0000000..14c45ee --- /dev/null +++ b/ipv4/definitions.go @@ -0,0 +1,38 @@ +package ipv4 + +const ( + sizeHeader = 20 +) + +// ToS represents the Traffic Class (a.k.a Type of Service). +type ToS uint8 + +// DS returns the top 6 bits of the IPv4 ToS holding the Differentiated Services field +// which is used to classify packets. +func (tos ToS) DS() uint8 { return uint8(tos) >> 2 } + +// ECN is the Explicit Congestion Notification which provides congestion control and non-congestion control traffic. +func (tos ToS) ECN() uint8 { return uint8(tos & 0b11) } + +// Flags holds fragmentation field data of an IPv4 header. +type Flags uint16 + +// IsEvil returns true if evil bit set as per [RFC3514]. +// +// [RFC3514]: https://datatracker.ietf.org/doc/html/rfc3514 +func (f Flags) IsEvil() bool { return f&2000 != 0 } + +// DontFragment specifies whether the datagram can not be fragmented. +// This can be used when sending packets to a host that does not have resources to perform reassembly of fragments. +// If the DontFragment(DF) flag is set, and fragmentation is required to route the packet, then the packet is dropped. +func (f Flags) DontFragment() bool { return f&0x4000 != 0 } + +// MoreFragments is cleared for unfragmented packets. +// For fragmented packets, all fragments except the last have the MF flag set. +// The last fragment has a non-zero Fragment Offset field, so it can still be differentiated from an unfragmented packet. +func (f Flags) MoreFragments() bool { return f&0x8000 != 0 } + +// FragmentOffset specifies the offset of a particular fragment relative to the beginning of the original unfragmented IP datagram. +// Fragments are specified in units of 8 bytes, which is why fragment lengths are always a multiple of 8; except the last, which may be smaller. +// The fragmentation offset value for the first fragment is always 0. +func (f Flags) FragmentOffset() uint16 { return uint16(f) & 0x1fff } diff --git a/ipv4/frame.go b/ipv4/frame.go new file mode 100644 index 0000000..4062389 --- /dev/null +++ b/ipv4/frame.go @@ -0,0 +1,209 @@ +package ipv4 + +import ( + "encoding/binary" + "errors" + + "github.com/soypat/lneto/lneto2" +) + +// Frame encapsulates the raw data of an IPv4 packet +// and provides methods for manipulating, validating and +// retreiving fields and payload data. See [RFC791]. +// +// [RFC791]: https://tools.ietf.org/html/rfc791 +type Frame struct { + buf []byte +} + +// RawData returns the underlying slice with which the frame was created. +func (ifrm Frame) RawData() []byte { return ifrm.buf } + +// HeaderLength returns the length of the IPv4 header as calculated using IHL. It includes IP options. +func (ifrm Frame) HeaderLength() int { + return int(ifrm.ihl()) * 4 +} + +func (ifrm Frame) ihl() uint8 { return ifrm.buf[0] & 0xf } +func (ifrm Frame) version() uint8 { return ifrm.buf[0] >> 4 } + +// VersionAndIHL returns the version and IHL fields in the IPv4 header. Version should always be 4. +func (ifrm Frame) VersionAndIHL() (version, IHL uint8) { + v := ifrm.buf[0] + return v >> 4, v & 0xf +} + +// SetVersionAndIHL sets the version and IHL fields in the IPv4 header. Version should always be 4. +func (ifrm Frame) SetVersionAndIHL(version, IHL uint8) { ifrm.buf[0] = version<<4 | IHL&0xf } + +// ToS (Type of Service) contains Differential Services Code Point (DSCP) and +// Explicit Congestion Notification (ECN) union data. +// +// DSCP originally defined as the type of service (ToS), this field specifies +// differentiated services (DiffServ) per RFC 2474. Real-time data streaming +// makes use of the DSCP field. An example is Voice over IP (VoIP), which is +// used for interactive voice services. +// +// ECN is defined in RFC 3168 and allows end-to-end notification of +// network congestion without dropping packets. ECN is an optional feature available +// when both endpoints support it and effective when also supported by the underlying network. +func (ifrm Frame) ToS() ToS { + return ToS(ifrm.buf[1]) +} + +// SetToS sets ToS field. See [Frame.ToS]. +func (ifrm Frame) SetToS(tos ToS) { ifrm.buf[1] = byte(tos) } + +// TotalLength defines the entire packet size in bytes, including IP header and data. +// The minimum size is 20 bytes (IPv4 header without data) and the maximum is 65,535 bytes. +// All hosts are required to be able to reassemble datagrams of size up to 576 bytes, +// but most modern hosts handle much larger packets. +// +// Links may impose further restrictions on the packet size, in which case datagrams +// must be fragmented. Fragmentation in IPv4 is performed in either the +// sending host or in routers. Reassembly is performed at the receiving host. +func (ifrm Frame) TotalLength() uint16 { + return binary.BigEndian.Uint16(ifrm.buf[2:4]) +} + +// SetTotalLength sets TotalLength field. See [Frame.TotalLength]. +func (ifrm Frame) SetTotalLength(tl uint16) { binary.BigEndian.PutUint16(ifrm.buf[2:4], tl) } + +// ID is an identification field and is primarily used for uniquely +// identifying the group of fragments of a single IP datagram. +func (ifrm Frame) ID() uint16 { + return binary.BigEndian.Uint16(ifrm.buf[4:6]) +} + +// SetID sets ID field. See [Frame.ID]. +func (ifrm Frame) SetID(id uint16) { binary.BigEndian.PutUint16(ifrm.buf[4:6], id) } + +// Flags returns the [Flags] of the IP packet. +func (ifrm Frame) Flags() Flags { + return Flags(binary.BigEndian.Uint16(ifrm.buf[6:8])) +} + +// SetFlags sets the IPv4 flags field. See [Flags]. +func (ifrm Frame) SetFlags(flags Flags) { + binary.BigEndian.PutUint16(ifrm.buf[6:8], uint16(flags)) +} + +// TTL is an eight-bit time to live field limits a datagram's lifetime to prevent +// network failure in the event of a routing loop. In practice, the field +// is used as a hop count—when the datagram arrives at a router, +// the router decrements the TTL field by one. When the TTL field hits zero, +// the router discards the packet and typically sends an ICMP time exceeded message to the sender. +func (ifrm Frame) TTL() uint8 { return ifrm.buf[8] } + +// SetTTL sets the IP frame's TTL field. See [Frame.TTL]. +func (ifrm Frame) SetTTL(ttl uint8) { ifrm.buf[8] = ttl } + +// Protocol field defines the protocol used in the data portion of the IP datagram. TCP is 6, UDP is 17. +// See [IPProto]. +func (ifrm Frame) Protocol() lneto2.IPProto { return lneto2.IPProto(ifrm.buf[9]) } + +// SetProtocol sets protocol field. See [Frame.Protocol] and [lneto2.IPProto]. +func (ifrm Frame) SetProtocol(proto lneto2.IPProto) { ifrm.buf[9] = uint8(proto) } + +// CRC returns the cyclic-redundancy-check (checksum) field of the IPv4 header. +func (ifrm Frame) CRC() uint16 { + return binary.BigEndian.Uint16(ifrm.buf[10:12]) +} + +// SetCRC sets the CRC field of the IP packet. See [Frame.CRC]. +func (ifrm Frame) SetCRC(cs uint16) { + binary.BigEndian.PutUint16(ifrm.buf[10:12], cs) +} + +// CalculateHeaderCRC calculates the CRC for this IPv4 frame. +func (ifrm Frame) CalculateHeaderCRC() uint16 { + var crc lneto2.CRC791 + crc.Write(ifrm.buf[0:10]) + crc.Write(ifrm.buf[12:20]) + return crc.Sum16() +} + +func (ifrm Frame) crcWriteTCPPseudo(crc *lneto2.CRC791) { + crc.Write(ifrm.SourceAddr()[:]) + crc.Write(ifrm.DestinationAddr()[:]) + crc.AddUint16(ifrm.TotalLength() - 4*uint16(ifrm.ihl())) + crc.AddUint16(uint16(ifrm.Protocol())) +} + +func (ifrm Frame) crcWriteUDPPseudo(crc *lneto2.CRC791) { + crc.Write(ifrm.SourceAddr()[:]) + crc.Write(ifrm.DestinationAddr()[:]) + crc.AddUint16(uint16(ifrm.Protocol())) +} + +// SourceAddr returns pointer to the source IPv4 address in the IP header. +func (ifrm Frame) SourceAddr() *[4]byte { + return (*[4]byte)(ifrm.buf[12:16]) +} + +// DestinationAddr returns pointer to the destination IPv4 address in the IP header. +func (ifrm Frame) DestinationAddr() *[4]byte { + return (*[4]byte)(ifrm.buf[16:20]) +} + +// Payload returns the contents of the IPv4 packet, which may be zero sized. +// Be sure to call [Frame.ValidateSize] beforehand to avoid panic. +func (ifrm Frame) Payload() []byte { + off := ifrm.HeaderLength() + l := ifrm.TotalLength() + return ifrm.buf[off:l] +} + +// Options returns the options portion of the IPv4 header. May be zero lengthed. +// Be sure to call [Frame.ValidateSize] beforehand to avoid panic. +func (ifrm Frame) Options() []byte { + off := ifrm.HeaderLength() + return ifrm.buf[sizeHeader:off] +} + +// ClearHeader zeros out the fixed(non-variable) header contents. +func (ifrm Frame) ClearHeader() { + for i := range ifrm.buf[:sizeHeader] { + ifrm.buf[i] = 0 + } +} + +// +// Validation API. +// + +var ( + errBadTL = errors.New("ipv4: bad total length") + errShort = errors.New("ipv4: short data") + errBadIHL = errors.New("ipv4: bad IHL") + errBadVersion = errors.New("ipv4: bad version") + errEvil = errors.New("ipv4: evil packet") +) + +// ValidateSize checks the frame's size fields and compares with the actual buffer +// the frame. It returns a non-nil error on finding an inconsistency. +func (ifrm Frame) ValidateSize(v *lneto2.Validator) { + ihl := ifrm.ihl() + tl := ifrm.TotalLength() + if tl < sizeHeader { + v.AddError(errBadTL) + } + if int(tl) > len(ifrm.RawData()) { + v.AddError(errShort) + } + if ihl < 5 { + v.AddError(errBadIHL) + } +} + +// ValidateExceptCRC checks for invalid frame values but does not check CRC. +func (ifrm Frame) ValidateExceptCRC(v *lneto2.Validator) { + ifrm.ValidateSize(v) + flags := ifrm.Flags() + if ifrm.version() != 4 { + v.AddError(errBadVersion) + } + if v.Flags()&lneto2.ValidateEvilBit != 0 && flags.IsEvil() { + v.AddError(errEvil) + } +} diff --git a/ipv6/definitions.go b/ipv6/definitions.go new file mode 100644 index 0000000..84655f3 --- /dev/null +++ b/ipv6/definitions.go @@ -0,0 +1,9 @@ +package ipv6 + +import "github.com/soypat/lneto/ipv4" + +const ( + sizeHeader = 40 +) + +type ToS = ipv4.ToS diff --git a/ipv6/frame.go b/ipv6/frame.go new file mode 100644 index 0000000..caabc23 --- /dev/null +++ b/ipv6/frame.go @@ -0,0 +1,101 @@ +package ipv6 + +import ( + "encoding/binary" + + "github.com/soypat/lneto/lneto2" +) + +// Frame encapsulates the raw data of an IPv6 packet +// and provides methods for manipulating, validating and +// retrieving fields and payload data. See [RFC8200]. +// +// [RFC8200]: https://tools.ietf.org/html/rfc8200 +type Frame struct { + buf []byte +} + +// RawData returns the underlying slice with which the frame was created. +func (i6frm Frame) RawData() []byte { return i6frm.buf } + +// Payload returns the contents of the IPv6 packet, which may be zero sized. +// Be sure to call [Frame.ValidateSize] beforehand to avoid panic. +func (i6frm Frame) Payload() []byte { + pl := i6frm.PayloadLength() + return i6frm.buf[sizeHeader : sizeHeader+pl] +} + +// VersionTrafficAndFlow returns the version, Traffic and Flow label fields of the IPv6 header. +// See [ToS] Traffic Class. Version should be 6 for IPv6. +func (i6frm Frame) VersionTrafficAndFlow() (version uint8, tos ToS, flow uint32) { + v := binary.BigEndian.Uint32(i6frm.buf[0:4]) + version = uint8(v >> (32 - 4)) + tos = ToS(v >> (32 - 12)) + flow = v & 0x000f_ffff + return version, tos, flow +} + +// SetVersionTrafficAndFlow sets the version, ToS and Flow label in the IPv6 header. Version must be equal to 6. +// See [Frame.VersionTrafficAndFlow]. +func (i6frm Frame) SetVersionTrafficAndFlow(version uint8, tos ToS, flow uint32) { + v := flow | uint32(tos)<<(32-12) | uint32(version)<<(32-4) + binary.BigEndian.PutUint32(i6frm.buf[0:4], v) +} + +// PayloadLength returns the size of payload in octets(bytes) including any extension headers. +// The length is set to zero when a Hop-by-Hop extension header carries a Jumbo Payload option. +func (i6frm Frame) PayloadLength() uint16 { + return binary.BigEndian.Uint16(i6frm.buf[4:6]) +} + +// SetPayloadLength sets the payload length field of the IPv6 header. See [Frame.PayloadLength]. +func (i6frm Frame) SetPayloadLength(pl uint16) { + binary.BigEndian.PutUint16(i6frm.buf[4:6], pl) +} + +// NextHeader returns the Next Header field of the IPv6 header which usually specifies the transport layer +// protocol used by packet's payload. +func (i6frm Frame) NextHeader() lneto2.IPProto { + return lneto2.IPProto(i6frm.buf[6]) +} + +// SetNextHeader sets the Next Header (protocol) field of the IPv6 header. See [Frame.NextHeader]. +func (i6frm Frame) SetNextHeader(proto lneto2.IPProto) { + i6frm.buf[6] = uint8(proto) +} + +// HopLimit returns the Hop Limit of the IPv6 header. +// This value is decremented by one at each forwarding node and the packet is discarded if it becomes 0. +// However, the destination node should process the packet normally even if received with a hop limit of 0. +func (i6frm Frame) HopLimit() uint8 { + return i6frm.buf[7] +} + +// SetHopLimit sets the Hop Limit field of the IPv6 header. See [Frame.HopLimiy]. +func (i6frm Frame) SetHopLimit(hop uint8) { + i6frm.buf[7] = hop +} + +// SourceAddr returns pointer to the sending node unicast IPv6 address in the IP header. +func (i6frm Frame) SourceAddr() *[16]byte { + return (*[16]byte)(i6frm.buf[8:24]) +} + +// DestinationAddr returns pointer to the destination node unicast or multicast IPv6 address in the IP header. +func (i6frm Frame) DestinationAddr() *[16]byte { + return (*[16]byte)(i6frm.buf[24:40]) +} + +func (i6frm Frame) crcWritePseudo(crc *lneto2.CRC791) { + crc.Write(i6frm.SourceAddr()[:]) + crc.Write(i6frm.DestinationAddr()[:]) + crc.AddUint32(uint32(i6frm.PayloadLength())) + crc.AddUint32(uint32(i6frm.NextHeader())) +} + +// ClearHeader zeros out the header contents. +func (i6frm Frame) ClearHeader() { + for i := range i6frm.buf[:sizeHeader] { + i6frm.buf[i] = 0 + } +} diff --git a/lneto2/stringers.go b/lneto2/stringers.go new file mode 100644 index 0000000..5f23c76 --- /dev/null +++ b/lneto2/stringers.go @@ -0,0 +1,310 @@ +// Code generated by "stringer -type=EtherType,IPProto,ARPOp -linecomment -output stringers.go ."; DO NOT EDIT. + +package lneto2 + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[EtherTypeIPv4-2048] + _ = x[EtherTypeARP-2054] + _ = x[EtherTypeWakeOnLAN-2114] + _ = x[EtherTypeTRILL-8947] + _ = x[EtherTypeDECnetPhase4-24579] + _ = x[EtherTypeRARP-32821] + _ = x[EtherTypeAppleTalk-32923] + _ = x[EtherTypeAARP-33011] + _ = x[EtherTypeIPX1-33079] + _ = x[EtherTypeIPX2-33080] + _ = x[EtherTypeQNXQnet-33284] + _ = x[EtherTypeIPv6-34525] + _ = x[EtherTypeEthernetFlowControl-34824] + _ = x[EtherTypeIEEE802_3-34825] + _ = x[EtherTypeCobraNet-34841] + _ = x[EtherTypeMPLSUnicast-34887] + _ = x[EtherTypeMPLSMulticast-34888] + _ = x[EtherTypePPPoEDiscovery-34915] + _ = x[EtherTypePPPoESession-34916] + _ = x[EtherTypeJumboFrames-34928] + _ = x[EtherTypeHomePlug1_0MME-34939] + _ = x[EtherTypeIEEE802_1X-34958] + _ = x[EtherTypePROFINET-34962] + _ = x[EtherTypeHyperSCSI-34970] + _ = x[EtherTypeAoE-34978] + _ = x[EtherTypeEtherCAT-34980] + _ = x[EtherTypeEthernetPowerlink-34987] + _ = x[EtherTypeLLDP-35020] + _ = x[EtherTypeSERCOS3-35021] + _ = x[EtherTypeHomePlugAVMME-35041] + _ = x[EtherTypeMRP-35043] + _ = x[EtherTypeIEEE802_1AE-35045] + _ = x[EtherTypeIEEE1588-35063] + _ = x[EtherTypeIEEE802_1ag-35074] + _ = x[EtherTypeFCoE-35078] + _ = x[EtherTypeFCoEInit-35092] + _ = x[EtherTypeRoCE-35093] + _ = x[EtherTypeCTP-36864] + _ = x[EtherTypeVeritasLLT-51966] + _ = x[EtherTypeVLAN-33024] + _ = x[EtherTypeServiceVLAN-34984] +} + +const _EtherType_name = "IPv4ARPwake on LANTRILLDECnetPhase4RARPAppleTalkAARPVLANIPx1IPx2QNXQnetIPv6EthernetFlowCtlIEEE802.3CobraNetMPLS UnicastMPLS MulticastPPPoE discoveryPPPoE sessionjumbo frameshome plug 1 0mmeIEEE 802.1xprofinethyper SCSIAoEEtherCATservice VLANEthernet powerlinkLLDPSERCOS3home plug AVMMEMRPIEEE 802.1aeIEEE 1588IEEE 802.1agFCoEFCoE initRoCECTPVeritas LLT" + +var _EtherType_map = map[EtherType]string{ + 2048: _EtherType_name[0:4], + 2054: _EtherType_name[4:7], + 2114: _EtherType_name[7:18], + 8947: _EtherType_name[18:23], + 24579: _EtherType_name[23:35], + 32821: _EtherType_name[35:39], + 32923: _EtherType_name[39:48], + 33011: _EtherType_name[48:52], + 33024: _EtherType_name[52:56], + 33079: _EtherType_name[56:60], + 33080: _EtherType_name[60:64], + 33284: _EtherType_name[64:71], + 34525: _EtherType_name[71:75], + 34824: _EtherType_name[75:90], + 34825: _EtherType_name[90:99], + 34841: _EtherType_name[99:107], + 34887: _EtherType_name[107:119], + 34888: _EtherType_name[119:133], + 34915: _EtherType_name[133:148], + 34916: _EtherType_name[148:161], + 34928: _EtherType_name[161:173], + 34939: _EtherType_name[173:189], + 34958: _EtherType_name[189:200], + 34962: _EtherType_name[200:208], + 34970: _EtherType_name[208:218], + 34978: _EtherType_name[218:221], + 34980: _EtherType_name[221:229], + 34984: _EtherType_name[229:241], + 34987: _EtherType_name[241:259], + 35020: _EtherType_name[259:263], + 35021: _EtherType_name[263:270], + 35041: _EtherType_name[270:285], + 35043: _EtherType_name[285:288], + 35045: _EtherType_name[288:300], + 35063: _EtherType_name[300:309], + 35074: _EtherType_name[309:321], + 35078: _EtherType_name[321:325], + 35092: _EtherType_name[325:334], + 35093: _EtherType_name[334:338], + 36864: _EtherType_name[338:341], + 51966: _EtherType_name[341:352], +} + +func (i EtherType) String() string { + if str, ok := _EtherType_map[i]; ok { + return str + } + return "EtherType(" + strconv.FormatInt(int64(i), 10) + ")" +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[IPProtoHopByHop-0] + _ = x[IPProtoICMP-1] + _ = x[IPProtoIGMP-2] + _ = x[IPProtoGGP-3] + _ = x[IPProtoIPv4-4] + _ = x[IPProtoST-5] + _ = x[IPProtoTCP-6] + _ = x[IPProtoCBT-7] + _ = x[IPProtoEGP-8] + _ = x[IPProtoIGP-9] + _ = x[IPProtoBBNRCCMON-10] + _ = x[IPProtoNVP-11] + _ = x[IPProtoPUP-12] + _ = x[IPProtoARGUS-13] + _ = x[IPProtoEMCON-14] + _ = x[IPProtoXNET-15] + _ = x[IPProtoCHAOS-16] + _ = x[IPProtoUDP-17] + _ = x[IPProtoMUX-18] + _ = x[IPProtoDCNMEAS-19] + _ = x[IPProtoHMP-20] + _ = x[IPProtoPRM-21] + _ = x[IPProtoXNSIDP-22] + _ = x[IPProtoTRUNK1-23] + _ = x[IPProtoTRUNK2-24] + _ = x[IPProtoLEAF1-25] + _ = x[IPProtoLEAF2-26] + _ = x[IPProtoRDP-27] + _ = x[IPProtoIRTP-28] + _ = x[IPProtoISO_TP4-29] + _ = x[IPProtoNETBLT-30] + _ = x[IPProtoMFE_NSP-31] + _ = x[IPProtoMERIT_INP-32] + _ = x[IPProtoDCCP-33] + _ = x[IPProto3PC-34] + _ = x[IPProtoIDPR-35] + _ = x[IPProtoXTP-36] + _ = x[IPProtoDDP-37] + _ = x[IPProtoIDPRCMTP-38] + _ = x[IPProtoTPPLUSPLUS-39] + _ = x[IPProtoIL-40] + _ = x[IPProtoIPv6-41] + _ = x[IPProtoSDRP-42] + _ = x[IPProtoIPv6Route-43] + _ = x[IPProtoIPv6Frag-44] + _ = x[IPProtoIDRP-45] + _ = x[IPProtoRSVP-46] + _ = x[IPProtoGRE-47] + _ = x[IPProtoDSR-48] + _ = x[IPProtoBNA-49] + _ = x[IPProtoESP-50] + _ = x[IPProtoAH-51] + _ = x[IPProtoINLSP-52] + _ = x[IPProtoSWIPE-53] + _ = x[IPProtoNARP-54] + _ = x[IPProtoMOBILE-55] + _ = x[IPProtoTLSP-56] + _ = x[IPProtoSKIP-57] + _ = x[IPProtoIPv6ICMP-58] + _ = x[IPProtoIPv6NoNxt-59] + _ = x[IPProtoIPv6Opts-60] + _ = x[IPProtoCFTP-62] + _ = x[IPProtoSATEXPAK-64] + _ = x[IPProtoKRYPTOLAN-65] + _ = x[IPProtoRVD-66] + _ = x[IPProtoIPPC-67] + _ = x[IPProtoSATMON-69] + _ = x[IPProtoVISA-70] + _ = x[IPProtoIPCV-71] + _ = x[IPProtoCPNX-72] + _ = x[IPProtoCPHB-73] + _ = x[IPProtoWSN-74] + _ = x[IPProtoPVP-75] + _ = x[IPProtoBRSATMON-76] + _ = x[IPProtoSUNND-77] + _ = x[IPProtoWBMON-78] + _ = x[IPProtoWBEXPAK-79] + _ = x[IPProtoISOIP-80] + _ = x[IPProtoVMTP-81] + _ = x[IPProtoSECUREVMTP-82] + _ = x[IPProtoVINES-83] + _ = x[IPProtoTTP-84] + _ = x[IPProtoNSFNETIGP-85] + _ = x[IPProtoDGP-86] + _ = x[IPProtoTCF-87] + _ = x[IPProtoEIGRP-88] + _ = x[IPProtoOSPFIGP-89] + _ = x[IPProtoSpriteRPC-90] + _ = x[IPProtoLARP-91] + _ = x[IPProtoMTP-92] + _ = x[IPProtoAX25-93] + _ = x[IPProtoIPIP-94] + _ = x[IPProtoMICP-95] + _ = x[IPProtoSCCSP-96] + _ = x[IPProtoETHERIP-97] + _ = x[IPProtoENCAP-98] + _ = x[IPProtoGMTP-100] + _ = x[IPProtoIFMP-101] + _ = x[IPProtoPNNI-102] + _ = x[IPProtoPIM-103] + _ = x[IPProtoARIS-104] + _ = x[IPProtoSCPS-105] + _ = x[IPProtoQNX-106] + _ = x[IPProtoAN-107] + _ = x[IPProtoIPComp-108] + _ = x[IPProtoSNP-109] + _ = x[IPProtoCompaqPeer-110] + _ = x[IPProtoIPXInIP-111] + _ = x[IPProtoVRRP-112] + _ = x[IPProtoPGM-113] + _ = x[IPProtoL2TP-115] + _ = x[IPProtoDDX-116] + _ = x[IPProtoIATP-117] + _ = x[IPProtoSTP-118] + _ = x[IPProtoSRP-119] + _ = x[IPProtoUTI-120] + _ = x[IPProtoSMP-121] + _ = x[IPProtoSM-122] + _ = x[IPProtoPTP-123] + _ = x[IPProtoISIS-124] + _ = x[IPProtoFIRE-125] + _ = x[IPProtoCRTP-126] + _ = x[IPProtoCRUDP-127] + _ = x[IPProtoSSCOPMCE-128] + _ = x[IPProtoIPLT-129] + _ = x[IPProtoSPS-130] + _ = x[IPProtoPIPE-131] + _ = x[IPProtoSCTP-132] + _ = x[IPProtoFC-133] + _ = x[IPProtoRSVP_E2E_IGNORE-134] + _ = x[IPProtoMobilityHeader-135] + _ = x[IPProtoUDPLite-136] + _ = x[IPProtoMPLSInIP-137] + _ = x[IPProtoMANET-138] + _ = x[IPProtoHIP-139] + _ = x[IPProtoShim6-140] + _ = x[IPProtoWESP-141] + _ = x[IPProtoROHC-142] + _ = x[IPProtoEthernet-143] + _ = x[IPProtoAGGFRAG-144] + _ = x[IPProtoNSH-145] +} + +const ( + _IPProto_name_0 = "IPv6 Hop-by-Hop Option [RFC8200]Internet Control Message [RFC792]Internet Group Management [RFC1112]Gateway-to-Gateway [RFC823]IPv4 encapsulation [RFC2003]Stream [RFC1190, RFC1819]Transmission Control [RFC9293]CBT [Ballardie]Exterior Gateway Protocol [RFC888]any private interior gateway (used by Cisco for their IGRP)BBN RCC MonitoringNetwork Voice Protocol [RFC741]PUPARGUSEMCONCross Net DebuggerChaosUser Datagram [RFC768]MultiplexingDCN Measurement SubsystemsHost Monitoring [RFC869]Packet Radio MeasurementXEROX NS IDPTrunk-1Trunk-2Leaf-1Leaf-2Reliable Data Protocol [RFC908]Internet Reliable Transaction [RFC938]ISO Transport Protocol Class 4 [RFC905]Bulk Data Transfer Protocol [RFC998]MFE Network Services ProtocolMERIT Internodal ProtocolDatagram Congestion Control Protocol [RFC4340]Third Party Connect ProtocolInter-Domain Policy Routing ProtocolXTPDatagram Delivery ProtocolIDPR Control Message Transport ProtoTP++ Transport ProtocolIL Transport ProtocolIPv6 encapsulation [RFC2473]Source Demand Routing ProtocolRouting Header for IPv6 [RFC8200]Fragment Header for IPv6 [RFC8200]Inter-Domain Routing ProtocolReservation Protocol [RFC2205]Generic Routing Encapsulation [RFC2784]Dynamic Source Routing ProtocolBNAEncap Security Payload [RFC4303]Authentication Header [RFC4302]Integrated Net Layer Security TUBAIP with EncryptionNBMA Address Resolution ProtocolIP MobilityTransport Layer Security Protocol using Kryptonet key managementSKIPICMP for IPv6 [RFC8200]No Next Header for IPv6 [RFC8200]Destination Options for IPv6 [RFC8200]" + _IPProto_name_1 = "CFTP" + _IPProto_name_2 = "SATNET and Backroom EXPAKKryptolanMIT Remote Virtual Disk ProtocolInternet Pluribus Packet Core" + _IPProto_name_3 = "SATNET MonitoringVISA ProtocolInternet Packet Core UtilityComputer Protocol Network ExecutiveComputer Protocol Heart BeatWang Span NetworkPacket Video ProtocolBackroom SATNET MonitoringSUN ND PROTOCOL-TemporaryWIDEBAND MonitoringWIDEBAND EXPAKISO Internet ProtocolVMTPSECURE-VMTPVINESTTPNSFNET-IGPDissimilar Gateway ProtocolTCFEIGRPOSPFIGPSprite RPC ProtocolLocus Address Resolution ProtocolMulticast Transport ProtocolAX.25 FramesIP-within-IP Encapsulation ProtocolMobile Internetworking Control Pro.Semaphore Communications Sec. Pro.Ethernet-within-IP EncapsulationEncapsulation Header" + _IPProto_name_4 = "GMTPIpsilon Flow Management ProtocolPNNI over IPProtocol Independent MulticastARISSCPSQNXActive NetworksIP Payload Compression ProtocolSitara Networks ProtocolCompaq Peer ProtocolIPX in IPVirtual Router Redundancy ProtocolPGM Reliable Transport Protocol" + _IPProto_name_5 = "Layer Two Tunneling Protocol v3D-II Data Exchange (DDX)Interactive Agent Transfer ProtocolSchedule Transfer ProtocolSpectraLink Radio ProtocolUTISimple Message ProtocolSMPerformance Transparency ProtocolISIS over IPv4FIRECombat Radio Transport ProtocolCombat Radio User DatagramSSCOPMCEIPLTSecure Packet ShieldPrivate IP Encapsulation within IPStream Control Transmission ProtocolFibre ChannelRSVP-E2E-IGNOREMobility HeaderUDPLiteMPLS-in-IPMANET ProtocolsHost Identity ProtocolShim6 ProtocolWrapped Encapsulating Security PayloadRobust Header CompressionEthernetAGGFRAG Encapsulation payload for ESPNetwork Service Header" +) + +var ( + _IPProto_index_0 = [...]uint16{0, 32, 65, 100, 127, 155, 180, 210, 225, 259, 318, 336, 367, 370, 375, 380, 398, 403, 425, 437, 463, 487, 511, 523, 530, 537, 543, 549, 580, 618, 657, 693, 722, 747, 793, 821, 857, 860, 886, 922, 945, 966, 994, 1024, 1057, 1091, 1120, 1150, 1189, 1220, 1223, 1255, 1286, 1320, 1338, 1370, 1381, 1445, 1449, 1472, 1505, 1543} + _IPProto_index_2 = [...]uint8{0, 25, 34, 66, 95} + _IPProto_index_3 = [...]uint16{0, 17, 30, 58, 93, 121, 138, 159, 185, 210, 229, 243, 264, 268, 279, 284, 287, 297, 324, 327, 332, 339, 358, 391, 419, 431, 466, 501, 535, 567, 587} + _IPProto_index_4 = [...]uint8{0, 4, 36, 48, 78, 82, 86, 89, 104, 135, 159, 179, 188, 222, 253} + _IPProto_index_5 = [...]uint16{0, 31, 55, 90, 116, 142, 145, 168, 170, 203, 217, 221, 252, 278, 286, 290, 310, 344, 380, 393, 408, 423, 430, 440, 455, 477, 491, 529, 554, 562, 599, 621} +) + +func (i IPProto) String() string { + switch { + case i <= 60: + return _IPProto_name_0[_IPProto_index_0[i]:_IPProto_index_0[i+1]] + case i == 62: + return _IPProto_name_1 + case 64 <= i && i <= 67: + i -= 64 + return _IPProto_name_2[_IPProto_index_2[i]:_IPProto_index_2[i+1]] + case 69 <= i && i <= 98: + i -= 69 + return _IPProto_name_3[_IPProto_index_3[i]:_IPProto_index_3[i+1]] + case 100 <= i && i <= 113: + i -= 100 + return _IPProto_name_4[_IPProto_index_4[i]:_IPProto_index_4[i+1]] + case 115 <= i && i <= 145: + i -= 115 + return _IPProto_name_5[_IPProto_index_5[i]:_IPProto_index_5[i+1]] + default: + return "IPProto(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ARPRequest-1] + _ = x[ARPReply-2] +} + +const _ARPOp_name = "requestreply" + +var _ARPOp_index = [...]uint8{0, 7, 12} + +func (i ARPOp) String() string { + i -= 1 + if i >= ARPOp(len(_ARPOp_index)-1) { + return "ARPOp(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _ARPOp_name[_ARPOp_index[i]:_ARPOp_index[i+1]] +} diff --git a/lneto2/validation.go b/lneto2/validation.go index 4dfba8f..50db57a 100644 --- a/lneto2/validation.go +++ b/lneto2/validation.go @@ -9,7 +9,7 @@ type ValidateFlags uint64 const ( validateReserved ValidateFlags = 1 << iota - validateEvilBit + ValidateEvilBit validateAllowMultiErrors ) diff --git a/stringers.go b/stringers.go index e8a7c6f..330339c 100644 --- a/stringers.go +++ b/stringers.go @@ -251,7 +251,7 @@ func _() { } const ( - _IPProto_name_0 = "IPv6 Hop-by-Hop Option [RFC8200]Internet Control Message [RFC792]Internet Group Management [RFC1112]Gateway-to-Gateway [RFC823]IPv4 encapsulation [RFC2003]Stream [RFC1190, RFC1819]Transmission Control [RFC793]CBT [Ballardie]Exterior Gateway Protocol [RFC888]any private interior gateway (used by Cisco for their IGRP)BBN RCC MonitoringNetwork Voice Protocol [RFC741]PUPARGUSEMCONCross Net DebuggerChaosUser Datagram [RFC768]MultiplexingDCN Measurement SubsystemsHost Monitoring [RFC869]Packet Radio MeasurementXEROX NS IDPTrunk-1Trunk-2Leaf-1Leaf-2Reliable Data Protocol [RFC908]Internet Reliable Transaction [RFC938]ISO Transport Protocol Class 4 [RFC905]Bulk Data Transfer Protocol [RFC998]MFE Network Services ProtocolMERIT Internodal ProtocolDatagram Congestion Control Protocol [RFC4340]Third Party Connect ProtocolInter-Domain Policy Routing ProtocolXTPDatagram Delivery ProtocolIDPR Control Message Transport ProtoTP++ Transport ProtocolIL Transport ProtocolIPv6 encapsulation [RFC2473]Source Demand Routing ProtocolRouting Header for IPv6 [RFC8200]Fragment Header for IPv6 [RFC8200]Inter-Domain Routing ProtocolReservation Protocol [RFC2205]Generic Routing Encapsulation [RFC2784]Dynamic Source Routing ProtocolBNAEncap Security Payload [RFC4303]Authentication Header [RFC4302]Integrated Net Layer Security TUBAIP with EncryptionNBMA Address Resolution ProtocolIP MobilityTransport Layer Security Protocol using Kryptonet key managementSKIPICMP for IPv6 [RFC8200]No Next Header for IPv6 [RFC8200]Destination Options for IPv6 [RFC8200]" + _IPProto_name_0 = "IPv6 Hop-by-Hop Option [RFC8200]Internet Control Message [RFC792]Internet Group Management [RFC1112]Gateway-to-Gateway [RFC823]IPv4 encapsulation [RFC2003]Stream [RFC1190, RFC1819]Transmission Control [RFC9293]CBT [Ballardie]Exterior Gateway Protocol [RFC888]any private interior gateway (used by Cisco for their IGRP)BBN RCC MonitoringNetwork Voice Protocol [RFC741]PUPARGUSEMCONCross Net DebuggerChaosUser Datagram [RFC768]MultiplexingDCN Measurement SubsystemsHost Monitoring [RFC869]Packet Radio MeasurementXEROX NS IDPTrunk-1Trunk-2Leaf-1Leaf-2Reliable Data Protocol [RFC908]Internet Reliable Transaction [RFC938]ISO Transport Protocol Class 4 [RFC905]Bulk Data Transfer Protocol [RFC998]MFE Network Services ProtocolMERIT Internodal ProtocolDatagram Congestion Control Protocol [RFC4340]Third Party Connect ProtocolInter-Domain Policy Routing ProtocolXTPDatagram Delivery ProtocolIDPR Control Message Transport ProtoTP++ Transport ProtocolIL Transport ProtocolIPv6 encapsulation [RFC2473]Source Demand Routing ProtocolRouting Header for IPv6 [RFC8200]Fragment Header for IPv6 [RFC8200]Inter-Domain Routing ProtocolReservation Protocol [RFC2205]Generic Routing Encapsulation [RFC2784]Dynamic Source Routing ProtocolBNAEncap Security Payload [RFC4303]Authentication Header [RFC4302]Integrated Net Layer Security TUBAIP with EncryptionNBMA Address Resolution ProtocolIP MobilityTransport Layer Security Protocol using Kryptonet key managementSKIPICMP for IPv6 [RFC8200]No Next Header for IPv6 [RFC8200]Destination Options for IPv6 [RFC8200]" _IPProto_name_1 = "CFTP" _IPProto_name_2 = "SATNET and Backroom EXPAKKryptolanMIT Remote Virtual Disk ProtocolInternet Pluribus Packet Core" _IPProto_name_3 = "SATNET MonitoringVISA ProtocolInternet Packet Core UtilityComputer Protocol Network ExecutiveComputer Protocol Heart BeatWang Span NetworkPacket Video ProtocolBackroom SATNET MonitoringSUN ND PROTOCOL-TemporaryWIDEBAND MonitoringWIDEBAND EXPAKISO Internet ProtocolVMTPSECURE-VMTPVINESTTPNSFNET-IGPDissimilar Gateway ProtocolTCFEIGRPOSPFIGPSprite RPC ProtocolLocus Address Resolution ProtocolMulticast Transport ProtocolAX.25 FramesIP-within-IP Encapsulation ProtocolMobile Internetworking Control Pro.Semaphore Communications Sec. Pro.Ethernet-within-IP EncapsulationEncapsulation Header" @@ -260,7 +260,7 @@ const ( ) var ( - _IPProto_index_0 = [...]uint16{0, 32, 65, 100, 127, 155, 180, 209, 224, 258, 317, 335, 366, 369, 374, 379, 397, 402, 424, 436, 462, 486, 510, 522, 529, 536, 542, 548, 579, 617, 656, 692, 721, 746, 792, 820, 856, 859, 885, 921, 944, 965, 993, 1023, 1056, 1090, 1119, 1149, 1188, 1219, 1222, 1254, 1285, 1319, 1337, 1369, 1380, 1444, 1448, 1471, 1504, 1542} + _IPProto_index_0 = [...]uint16{0, 32, 65, 100, 127, 155, 180, 210, 225, 259, 318, 336, 367, 370, 375, 380, 398, 403, 425, 437, 463, 487, 511, 523, 530, 537, 543, 549, 580, 618, 657, 693, 722, 747, 793, 821, 857, 860, 886, 922, 945, 966, 994, 1024, 1057, 1091, 1120, 1150, 1189, 1220, 1223, 1255, 1286, 1320, 1338, 1370, 1381, 1445, 1449, 1472, 1505, 1543} _IPProto_index_2 = [...]uint8{0, 25, 34, 66, 95} _IPProto_index_3 = [...]uint16{0, 17, 30, 58, 93, 121, 138, 159, 185, 210, 229, 243, 264, 268, 279, 284, 287, 297, 324, 327, 332, 339, 358, 391, 419, 431, 466, 501, 535, 567, 587} _IPProto_index_4 = [...]uint8{0, 4, 36, 48, 78, 82, 86, 89, 104, 135, 159, 179, 188, 222, 253}