rawnet

package module
v0.0.0-...-bc21ded Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2025 License: MIT Imports: 13 Imported by: 0

README

Go Reference

RawNet

RawNet is a Go library for low-level network packet manipulation. It provides tools for parsing, inspecting, and creating raw network packets at layers 2, 3, and 4 of the OSI model.

Features

  • Parse and create Ethernet frames (Layer 2)
  • Support for IPv4 and IPv6 packets (Layer 3)
  • Support for TCP, UDP, ICMP, and IGMP protocols (Layer 4)
  • Virtual network circuit simulation
  • Checksum calculation and validation
  • VLAN tagging support
  • Easy packet field manipulation

Installation

go get github.com/KarpelesLab/rawnet

Usage

Creating a Virtual Network Circuit
// Create a new virtual network circuit
circuit := rawnet.NewCircuit()

// Bridge a device to the circuit
circuit.BridgeDevice(myNetworkDevice)

// Enable debug logging
circuit.SetDebug(true)
Working with L2 Packets
// Handle an L2 packet
func (d *MyDevice) HandleL2Packet(src rawnet.L2Device, pkt rawnet.L2Packet) error {
    // Get source and destination MAC addresses
    srcMac := pkt.GetSourceMac()
    dstMac := pkt.GetDestinationMac()
    
    // Get ethertype and VLAN info
    ethertype, vlan, l3p := pkt.GetL3Packet()
    
    // Process based on packet type
    // ...
}
Working with L3 Packets
// Access IP addresses
srcIP := l3p.GetSourceIP()
dstIP := l3p.GetDestinationIP()

// Create a new L3 packet with modified source
newPacket := l3p.WithNewSource(myIP, myPort)

// Create a new L3 packet with modified destination
newPacket := l3p.WithNewDst(targetIP, targetPort)

Build and Test

make all    # Build the library
make deps   # Install dependencies
make test   # Run tests

License

See the LICENSE file for details.

Documentation

Overview

Package rawnet provides tools for low-level network packet manipulation at layers 2, 3, and 4 of the OSI model.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewHardwareAddr

func NewHardwareAddr() (net.HardwareAddr, error)

NewHardwareAddr() will generate a new hardware address suitable for private use

func Writev

func Writev(f *os.File, in [][]byte) (nw int, err error)

Writev calls writev() syscall, but first convert a [][]byte to []sycall.Iovec, return number of bytes written and an error

func WritevRaw

func WritevRaw(fd uintptr, iovec []syscall.Iovec) (nw int, err error)

WritevRaw calls writev() syscall like Writev, but expects a slice of syscall.Iovec

Types

type ARP

type ARP struct {
	HType      uint16
	PType      Protocol
	HLen, PLen uint8
	Oper       uint16

	SenderHW   net.HardwareAddr
	SenderAddr net.IP

	TargetHW   net.HardwareAddr
	TargetAddr net.IP
}

func (*ARP) MarshalBinary

func (f *ARP) MarshalBinary() ([]byte, error)

func (*ARP) String

func (f *ARP) String() string

func (*ARP) Swap

func (f *ARP) Swap()

type BaseL3

type BaseL3 struct {
	// contains filtered or unexported fields
}

BaseL3 provides a basic implementation for Layer 3 devices. It contains a MAC address for the virtual L3 device.

func NewBaseL3

func NewBaseL3(d L2Device) (*BaseL3, error)

NewBaseL3 creates a new BaseL3 instance with a randomly generated MAC address. It can be used as a foundation for implementing L3Device interfaces.

func (*BaseL3) HandleL2Packet

func (b *BaseL3) HandleL2Packet(p L3Packet) error

HandleL2Packet implements a basic packet handler for L3 devices. This is a sample implementation that logs the packet size.

type Circuit

type Circuit interface {
	L2Device
	BridgeDevice(dev L2Device) error
}

Circuit represents a virtual network circuit that can connect multiple devices. It acts as a virtual switch or hub that can bridge Layer 2 devices together.

type Ethernet

type Ethernet struct {
	Dst net.HardwareAddr
	Src net.HardwareAddr

	EtherType Protocol
	VLan      uint16

	Len int

	Inner Frame
}

func (*Ethernet) MarshalBinary

func (e *Ethernet) MarshalBinary() ([]byte, error)

func (*Ethernet) String

func (e *Ethernet) String() string

type Frame

type Frame interface {
	// String returns a human-readable representation of the frame
	String() string

	// MarshalBinary converts the frame to its binary representation
	MarshalBinary() ([]byte, error)
	// contains filtered or unexported methods
}

Frame represents a network protocol data unit at any layer. It's the core interface for all packet types in the rawnet library, providing methods for string representation and binary serialization.

func MakeUDPIP

func MakeUDPIP(src, dst net.IP, srcPort, dstPort uint16, data []byte) (Frame, error)

func ParseARP

func ParseARP(data []byte) (Frame, error)

func ParseICMP

func ParseICMP(data []byte) (Frame, error)

func ParseICMP6

func ParseICMP6(data []byte) (Frame, error)

func ParseIGMP

func ParseIGMP(data []byte) (Frame, error)

func ParseLayer3

func ParseLayer3(t Protocol, data []byte) (Frame, error)

ParseLayer3 parses a Layer 3 packet based on its protocol identifier. It returns the appropriate Frame implementation for the given protocol. If the protocol is not supported, it returns an InvalidFrame.

func ParseLayer4

func ParseLayer4(t L4Proto, data []byte) (Frame, error)

ParseLayer4 parses a Layer 4 packet based on its protocol identifier. It returns the appropriate Frame implementation for the given protocol. If the protocol is not supported, it returns an InvalidFrame.

func ParseTCP

func ParseTCP(data []byte) (Frame, error)

func ParseUDP

func ParseUDP(data []byte) (Frame, error)

type HardwareAddr

type HardwareAddr [6]byte

type ICMP

type ICMP struct {
	Type     uint8
	Code     uint8
	Checksum uint16
	Body     uint32

	Payload []byte
}

func (*ICMP) MarshalBinary

func (f *ICMP) MarshalBinary() ([]byte, error)

func (*ICMP) Message

func (f *ICMP) Message() string

func (*ICMP) String

func (f *ICMP) String() string

type ICMP6

type ICMP6 struct {
	Type     uint8
	Code     uint8
	Checksum uint16
	Body     uint32

	Payload []byte
}

func (*ICMP6) MarshalBinary

func (f *ICMP6) MarshalBinary() ([]byte, error)

func (*ICMP6) Message

func (f *ICMP6) Message() string

func (*ICMP6) String

func (f *ICMP6) String() string

type IGMP

type IGMP struct {
	Type        uint8
	MaxRespTime uint8
	Checksum    uint16
	GroupAddr   uint32

	Payload []byte
}

func (*IGMP) MarshalBinary

func (f *IGMP) MarshalBinary() ([]byte, error)

func (*IGMP) String

func (f *IGMP) String() string

type IPFrame

type IPFrame interface {
	Frame

	// GetInner returns the encapsulated Frame (e.g., TCP, UDP) contained in this IP packet
	GetInner() Frame
}

IPFrame extends the Frame interface with methods specific to IP packets. It represents both IPv4 and IPv6 frames and provides access to encapsulated protocols.

func ParseIP

func ParseIP(data []byte) (IPFrame, error)

ParseIP examines an IP packet and determines whether it's IPv4 or IPv6. It then delegates to the appropriate protocol-specific parser. The function returns an error if the IP version is not recognized (not 4 or 6).

type IPv4

type IPv4 struct {
	Version  uint8
	Len      uint8 // 4=20bytes
	TOS      uint8
	TotalLen uint16
	ID       uint16
	Flags    uint16
	FragOff  uint16 // max 0x1fff
	TTL      uint8
	Protocol L4Proto
	Checksum uint16
	Src      net.IP
	Dst      net.IP
	Options  []byte

	Inner Frame
}

func ParseIPv4

func ParseIPv4(data []byte) (*IPv4, error)

func (*IPv4) GetInner

func (i *IPv4) GetInner() Frame

func (*IPv4) MarshalBinary

func (i *IPv4) MarshalBinary() ([]byte, error)

func (*IPv4) String

func (i *IPv4) String() string

type IPv6

type IPv6 struct {
	Version    uint8
	Class      uint8
	FlowLabel  uint32 // actually 20 bytes
	PayloadLen uint16
	NextHeader L4Proto
	HopLimit   uint8 // TTL
	Src        net.IP
	Dst        net.IP

	Inner Frame
}

func ParseIPv6

func ParseIPv6(data []byte) (*IPv6, error)

func (*IPv6) GetInner

func (i *IPv6) GetInner() Frame

func (*IPv6) MarshalBinary

func (i *IPv6) MarshalBinary() ([]byte, error)

func (*IPv6) String

func (i *IPv6) String() string

type InvalidFrame

type InvalidFrame []byte

func (InvalidFrame) MarshalBinary

func (i InvalidFrame) MarshalBinary() ([]byte, error)

func (InvalidFrame) String

func (i InvalidFrame) String() string

type L2Device

type L2Device interface {
	HandleL2Packet(src L2Device, pkt L2Packet) error
}

L2Device represents a Layer 2 network device that can handle Ethernet frames. This interface is implemented by any device that operates at the data link layer.

type L2Packet

type L2Packet []byte

L2Packet represents a Layer 2 network packet (Ethernet frame). It's a byte slice that starts with an Ethernet header and provides methods for easily accessing and manipulating Ethernet header fields.

func (L2Packet) GetDestinationMac

func (p L2Packet) GetDestinationMac() net.HardwareAddr

GetDestinationMac returns the destination MAC address from the Ethernet header. This is the first 6 bytes of the frame.

func (L2Packet) GetEthertype

func (p L2Packet) GetEthertype() Protocol

GetEthertype returns the EtherType value from the Ethernet header. This indicates the protocol of the encapsulated data.

func (L2Packet) GetL3Packet

func (p L2Packet) GetL3Packet() (Protocol, uint16, L3Packet)

GetL3Packet extracts the Layer 3 packet from this Ethernet frame. It returns the EtherType, VLAN ID (if present), and the Layer 3 packet data. For VLAN-tagged frames, it properly skips the 802.1Q header.

func (L2Packet) GetPacketLayer

func (p L2Packet) GetPacketLayer() int

GetPacketLayer implements the Packet interface for L2Packet. Always returns 2 as Ethernet operates at OSI layer 2 (data link layer).

func (L2Packet) GetSourceMac

func (p L2Packet) GetSourceMac() net.HardwareAddr

GetSourceMac returns the source MAC address from the Ethernet header. This is bytes 6-12 of the frame.

func (L2Packet) GetVLan

func (p L2Packet) GetVLan() uint16

GetVLan extracts the VLAN ID from the frame if it has 802.1Q tagging. Returns 0 if there is no VLAN tag.

type L3Device

type L3Device interface {
	HandleL3Packet(Protocol, L3Packet) error
}

L3Device represents a Layer 3 network device that can handle IP packets. This interface is implemented by routers and other devices that operate at the network layer.

type L3Packet

type L3Packet []byte

L3Packet represents a Layer 3 network packet (IP packet). It's a byte slice that starts with an IP header and provides methods for easily accessing and manipulating IP header fields.

func (L3Packet) ComputeChecksums

func (p L3Packet) ComputeChecksums()

func (L3Packet) Dup

func (p L3Packet) Dup() L3Packet

Dup creates a deep copy of the packet. This is useful when you need to modify a packet without affecting the original.

func (L3Packet) GetDestinationIP

func (p L3Packet) GetDestinationIP() net.IP

GetDestinationIP returns the destination IP address from the packet. Works with both IPv4 and IPv6 packets, returning the appropriate net.IP type.

func (L3Packet) GetEthertype

func (p L3Packet) GetEthertype() Protocol

GetEthertype returns the protocol identifier for this IP packet. Returns ProtoIPv4 or ProtoIPv6 based on the IP version in the packet.

func (L3Packet) GetNatInfo

func (p L3Packet) GetNatInfo() ([]byte, []byte)

GetNatInfo returns information about source & dest without performing any memory copy GetNatInfo returns information about source & destination addresses without performing any memory copy. This is useful for NAT implementations that need to access and potentially modify this information. The first return value contains IP address information, and the second contains protocol-specific information.

func (L3Packet) GetPacketLayer

func (p L3Packet) GetPacketLayer() int

GetPacketLayer implements the Packet interface for L3Packet. Always returns 3 as IP operates at OSI layer 3 (network layer).

func (L3Packet) GetProtocol

func (p L3Packet) GetProtocol() L4Proto

GetProtocol returns the Layer 4 protocol identifier from the IP header. For IPv4, this is the Protocol field (byte 9). For IPv6, this is the Next Header field (byte 6).

func (L3Packet) GetSourceIP

func (p L3Packet) GetSourceIP() net.IP

GetSourceIP returns the source IP address from the packet. Works with both IPv4 and IPv6 packets, returning the appropriate net.IP type.

func (L3Packet) GetSourcePort

func (p L3Packet) GetSourcePort() uint16

GetSourcePort extracts the source port from TCP or UDP packets. Returns 0 if the packet is not TCP or UDP, or if the IP version is unknown. Works with both IPv4 and IPv6 packets by correctly calculating header sizes.

func (L3Packet) GetSrcDst

func (p L3Packet) GetSrcDst(src, dst []byte) Protocol

GetSrcDst extracts both source and destination addresses (IP and ports) into provided buffers. For IPv4, src/dst buffers should be at least 6 bytes (4 for IP, 2 for port). For IPv6, src/dst buffers should be at least 18 bytes (16 for IP, 2 for port). Returns the protocol type (TCP, UDP, etc.) if available.

func (L3Packet) MarshalBinary

func (p L3Packet) MarshalBinary() ([]byte, error)

MarshalBinary implements the encoding.BinaryMarshaler interface. For L3Packet, this simply returns the packet data as a byte slice.

func (L3Packet) String

func (p L3Packet) String() string

String returns a human-readable representation of the packet, showing the protocol, source IP, and destination IP.

func (L3Packet) WithNewDst

func (p L3Packet) WithNewDst(dst net.IP, port uint16) L3Packet

WithNewDst creates a copy of the packet with a new destination IP address and port. It properly handles both IPv4 and IPv6 packets and recalculates checksums. Returns nil if the operation is not supported for the given protocol or IP version.

func (L3Packet) WithNewSource

func (p L3Packet) WithNewSource(src net.IP, port uint16) L3Packet

WithNewSource creates a copy of the packet with a new source IP address and port. It properly handles both IPv4 and IPv6 packets and recalculates checksums. Returns nil if the operation is not supported for the given protocol or IP version.

type L4Proto

type L4Proto uint8

L4Proto represents an IP protocol number identifying transport layer protocols. These values are used in IP headers to indicate the type of the transport protocol. Reference: https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers

const (
	L4ICMP L4Proto = 0x01 // Internet Control Message Protocol (IPv4)
	L4TCP  L4Proto = 0x06 // Transmission Control Protocol
	L4UDP  L4Proto = 0x11 // User Datagram Protocol
)

Standard IP protocol numbers for common Layer 4 protocols

type Packet

type Packet interface {
	// GetPacketLayer returns the OSI model layer number that this packet operates at.
	// For example, Ethernet is layer 2, IP is layer 3, TCP is layer 4.
	GetPacketLayer() int
}

Packet is an interface for any network packet type. It provides a method to determine the OSI layer at which this packet operates.

type Protocol

type Protocol uint16

Protocol represents an EtherType value identifying network layer protocols. These values are used in Ethernet frames to indicate the type of the encapsulated protocol.

const (
	ProtoIPv4 Protocol = 0x0800 // IPv4 protocol
	ProtoIPv6 Protocol = 0x86dd // IPv6 protocol
	ProtoARP  Protocol = 0x0806 // Address Resolution Protocol
	ProtoRARP Protocol = 0x8035 // Reverse Address Resolution Protocol
	ProtoXNS  Protocol = 0x0600 // Xerox Network Systems
	ProtoVLAN Protocol = 0x8100 // IEEE 802.1Q VLAN tagging
)

Standard EtherType values for common Layer 3 protocols

func (Protocol) String

func (i Protocol) String() string

type TCP

type TCP struct {
	SrcPort    uint16
	DstPort    uint16
	Seq        uint32
	Ack        uint32
	Flags      uint16
	WindowSize uint16
	Checksum   uint16
	UrgentPtr  uint16

	Options []byte
	Payload []byte
}

func (*TCP) MarshalBinary

func (f *TCP) MarshalBinary() ([]byte, error)

func (*TCP) String

func (f *TCP) String() string

type UDP

type UDP struct {
	SrcPort  uint16
	DstPort  uint16
	Length   uint16
	Checksum uint16

	Payload []byte
}

func (*UDP) MarshalBinary

func (f *UDP) MarshalBinary() ([]byte, error)

func (*UDP) String

func (f *UDP) String() string

type VirtualCircuit

type VirtualCircuit struct {
	// contains filtered or unexported fields
}

VirtualCircuit implements a Layer 2 network that can accept multiple clients (L2 or L3). It acts as a virtual switch or hub, broadcasting packets to all connected devices. L3 clients will be assigned a random MAC address when connected.

func NewCircuit

func NewCircuit() *VirtualCircuit

NewCircuit creates a new VirtualCircuit instance. This circuit can have multiple L2 devices attached to it via BridgeDevice.

func (*VirtualCircuit) BridgeDevice

func (c *VirtualCircuit) BridgeDevice(dev L2Device) error

BridgeDevice connects a Layer 2 device to this circuit. All packets received by the circuit will be forwarded to this device, and all packets sent by this device will be broadcast to other devices.

func (*VirtualCircuit) HandleL2Packet

func (c *VirtualCircuit) HandleL2Packet(src L2Device, pkt L2Packet) error

HandleL2Packet implements the L2Device interface. It broadcasts the received packet to all connected devices except the source. For circuits with more than 16 devices, it uses goroutines for parallel delivery.

func (*VirtualCircuit) SetDebug

func (c *VirtualCircuit) SetDebug(v bool)

SetDebug enables or disables debug logging for this circuit. When enabled, the circuit will log information about packet handling.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL