router

package
v0.0.21 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2025 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AARPMachine

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

AARPMachine maintains both an Address Mapping Table and handles AARP packets (sending and receiving requests, responses, and probes). This process assumes a particular network range rather than using the startup range, since this program is a seed router.

func NewAARPMachine

func NewAARPMachine(logger *slog.Logger, port *EtherTalkPort, myHWAddr ethernet.Addr) *AARPMachine

NewAARPMachine creates a new AARPMachine.

func (*AARPMachine) Address

func (a *AARPMachine) Address() (aarp.AddrPair, bool)

Address returns the address of this node, and reports if the address is valid (i.e. not tentative).

func (*AARPMachine) Assigned

func (a *AARPMachine) Assigned() <-chan struct{}

Assigned returns a channel that is closed when the local address is valid.

func (AARPMachine) Dump

func (t AARPMachine) Dump() map[ddp.Addr]AMTEntry

Dump returns a copy of the table at a point in time.

func (*AARPMachine) Handle

func (a *AARPMachine) Handle(ctx context.Context, pkt *ethertalk.Packet)

Handle handles a packet.

func (*AARPMachine) Run

func (a *AARPMachine) Run(ctx context.Context) error

Run executes the machine.

type AMTEntry

type AMTEntry struct {
	// The hardware address that the entry maps to.
	HWAddr ethernet.Addr

	// The last time this entry was updated.
	LastUpdated time.Time
	// contains filtered or unexported fields
}

AMTEntry is an entry in an address mapping table.

func (AMTEntry) Valid

func (e AMTEntry) Valid() bool

Valid reports if the entry is valid.

type AURPPeer

type AURPPeer struct {
	// AURP-Tr state for producing packets.
	Transport *aurp.Transport

	// Connection to reply to packets on.
	UDPConn *net.UDPConn

	// The string that appeared in the config file / peer list file.
	// May be empty if this peer was not configured (it connected to us, with
	// open_peering enabled).
	ConfiguredAddr string

	// The resolved address of the peer.
	// NOTE: The UDP port is always assumed to be 387.
	RemoteAddr net.IP

	// Incoming packet channel.
	ReceiveCh chan aurp.RoutingPacket

	// Route table (the peer will add/remove/update routes and zones)
	RouteTable *RouteTable
	// contains filtered or unexported fields
}

AURPPeer handles the peering with a peer AURP router.

func (*AURPPeer) BestNetworkChanged added in v0.0.12

func (p *AURPPeer) BestNetworkChanged(oldBest, newBest Route)

BestNetworkChanged implements RouteTableObserver.

func (*AURPPeer) Class added in v0.0.12

func (p *AURPPeer) Class() TargetClass

Class returns TargetClassAURPPeer.

func (*AURPPeer) DumpChatLog added in v0.0.19

func (p *AURPPeer) DumpChatLog() []ChatLogEntry

DumpChatLog returns the "chat log" for this peer: the AURP conversation. It only includes routing packets, and not encapsulated AppleTalk.

func (*AURPPeer) Forward

func (p *AURPPeer) Forward(_ context.Context, ddpkt *ddp.ExtPacket) error

Forward encapsulates the DDP packet in an AURP AppleTalkPacket and sends it to the remote peer router.

func (*AURPPeer) Handle

func (p *AURPPeer) Handle(ctx context.Context, wg *sync.WaitGroup)

Handle handles incoming packets, maintains the connections, and runs periodic tasks for this peer. It is safe to call multiple times concurrently - only one will run.

func (*AURPPeer) LastHeardFrom added in v0.0.14

func (p *AURPPeer) LastHeardFrom() time.Time

LastHeardFromAgo returns the time of the last packet received from this peer.

func (*AURPPeer) LastReconnect added in v0.0.14

func (p *AURPPeer) LastReconnect() time.Time

LastReconnect returns the time of the last reconnect to this peer.

func (*AURPPeer) LastSend added in v0.0.14

func (p *AURPPeer) LastSend() time.Time

LastSendAgo returns the time of the last packet sent to this peer.

func (*AURPPeer) LastUpdate added in v0.0.14

func (p *AURPPeer) LastUpdate() time.Time

LastUpdateAgo returns the time of the last (route) update received from the peer.

func (*AURPPeer) NetworkAdded added in v0.0.12

func (p *AURPPeer) NetworkAdded(newBest Route)

NetworkAdded implements RouteTableObserver.

func (*AURPPeer) NetworkDeleted added in v0.0.12

func (p *AURPPeer) NetworkDeleted(oldBest Route)

NetworkDeleted implements RouteTableObserver.

func (*AURPPeer) ReceiveChLen added in v0.0.19

func (p *AURPPeer) ReceiveChLen() int

ReceiveChLen returns len(p.ReceiveCh).

func (*AURPPeer) ReceiverConnected added in v0.0.21

func (p *AURPPeer) ReceiverConnected() bool

ReceiverConnected returns a simple bool reflecting whether the receiver is connected.

func (*AURPPeer) ReceiverState

func (p *AURPPeer) ReceiverState() ReceiverState

ReceiverState returns the current route-data receiver state.

func (*AURPPeer) RouteTargetKey added in v0.0.9

func (p *AURPPeer) RouteTargetKey() string

RouteTargetKey returns "AURPPeer|peer's IP address".

func (*AURPPeer) Running added in v0.0.14

func (p *AURPPeer) Running() bool

Running reports whether the handler loop is running.

func (*AURPPeer) SendRetries

func (p *AURPPeer) SendRetries() int

SendRetries returns the number of send-retries for the last route update send to this peer.

func (*AURPPeer) SenderConnected added in v0.0.21

func (p *AURPPeer) SenderConnected() bool

SenderConnected returns a simple bool reflecting whether the sender is connected.

func (*AURPPeer) SenderState

func (p *AURPPeer) SenderState() SenderState

SenderState returns the current route-data sender state.

func (*AURPPeer) String added in v0.0.9

func (p *AURPPeer) String() string

type AURPPeerTable added in v0.0.14

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

AURPPeerTable tracks connections to AURP peers.

func NewAURPPeerTable added in v0.0.14

func NewAURPPeerTable(ctx context.Context, logger *slog.Logger) *AURPPeerTable

NewAURPPeerTable creates a new AURP peer table.

func (*AURPPeerTable) Collect added in v0.0.14

func (t *AURPPeerTable) Collect(ch chan<- prometheus.Metric)

func (*AURPPeerTable) Describe added in v0.0.14

func (t *AURPPeerTable) Describe(ch chan<- *prometheus.Desc)

func (*AURPPeerTable) Lookup added in v0.0.14

func (t *AURPPeerTable) Lookup(raddr net.IP) (*AURPPeer, error)

Lookup looks up the peer associated with this IP address. It returns an error if the address is not an IPv4 address.

func (*AURPPeerTable) LookupOrCreate added in v0.0.14

func (t *AURPPeerTable) LookupOrCreate(
	ctx context.Context,
	logger *slog.Logger,
	routes *RouteTable,
	udpConn *net.UDPConn,
	peerAddr string,
	raddr net.IP,
	localDI, remoteDI aurp.DomainIdentifier,
) (*AURPPeer, error)

LookupOrCreate looks up a peer by raddr, or creates a peer if it is not found. It returns an error if raddr is not an IPv4 address.

func (*AURPPeerTable) PeriodicallyAttemptConnections added in v0.0.20

func (t *AURPPeerTable) PeriodicallyAttemptConnections(ctx context.Context, logger *slog.Logger, wg *sync.WaitGroup)

PeriodicallyAttemptConnections scans the peer table every 10 seconds looking for configured peers that are disconnected, and attempts to connect them.

func (*AURPPeerTable) RunAll added in v0.0.18

func (t *AURPPeerTable) RunAll(ctx context.Context, wg *sync.WaitGroup)

RunAll runs all peer handlers in goroutines.

func (*AURPPeerTable) ServeHTTP added in v0.0.19

func (t *AURPPeerTable) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serves diagnostic pages for AURP peers, such as the chatlog.

type ChatLogEntry added in v0.0.19

type ChatLogEntry struct {
	Packet    aurp.RoutingPacket
	Sent      bool // as opposed to Received
	Timestamp time.Time
}

ChatLogEntry is a record of a packet either sent or received and a timestamp. It's used for logging AURP conversations for diagnosis.

type Config

type Config struct {
	// ListenPort is the AURP service port. Optional: default is 387.
	ListenPort uint16 `yaml:"listen_port"`

	// MonitoringAddr is used for hosting /status server and /metrics.
	// Example: ":9459" (listen on port 9459 on all interfaces).
	// Optional: when left empty, the monitoring HTTP server is disabled.
	MonitoringAddr string `yaml:"monitoring_addr"`

	// LocalIP configures the Domain Identifier used by this router.
	// Note: this does not "bind" the IP side of the router to a particular
	// interface; it will listen on all interfaces with IP addresses.
	// Optional: defaults to the first global unicast address on any local
	// network interface.
	LocalIP string `yaml:"local_ip"`

	// EtherTalk is required for routing one or more local EtherTalk networks.
	EtherTalk EtherTalkConfigs `yaml:"ethertalk"`

	// OpenPeering allowsrouters other than those listed under peers.
	OpenPeering bool `yaml:"open_peering"`

	// Peers sets a list of peer routers to connect to and allow connections
	// from.
	Peers []string `yaml:"peers"`

	// PeerListURL sets a URL to fetch a list of peers from (plain text, one
	// peer per line).
	PeerListURL string `yaml:"peerlist_url"`
}

func LoadConfig

func LoadConfig(cfgPath string) (*Config, error)

LoadConfig readand parses a configuration file, and sets some defaults.

type EtherTalkConfig added in v0.0.7

type EtherTalkConfig struct {
	// EthAddr overrides the hardware address used by jrouter. Optional.
	EthAddr string `yaml:"ethernet_addr"`

	// Device is the Ethernet device name (e.g. eth0, enp2s0, en3). Required.
	Device string `yaml:"device"`

	// DefaultZoneName is the AppleTalk zone name for the network on this
	// interface. Required.
	DefaultZoneName string `yaml:"zone_name"`

	// ExtraZones is a list of any additional zone names that are available
	// within this local network. Nodes can choose from the default zone name
	// or any of these additional names.
	ExtraZones []string `yaml:"extra_zones"`

	// NetStart and NetEnd control the network number range for the AppleTalk
	// network on this interface (inclusive). Required.
	NetStart ddp.Network `yaml:"net_start"`
	NetEnd   ddp.Network `yaml:"net_end"`
}

EtherTalkConfig configures EtherTalk for a specific Ethernet interface.

type EtherTalkConfigs added in v0.0.7

type EtherTalkConfigs []*EtherTalkConfig

func (*EtherTalkConfigs) UnmarshalYAML added in v0.0.7

func (cs *EtherTalkConfigs) UnmarshalYAML(n *yaml.Node) error

type EtherTalkPeer

type EtherTalkPeer struct {
	Port     *EtherTalkPort
	PeerAddr ddp.Addr
}

EtherTalkPeer holds data needed to forward packets to another router on the EtherTalk network.

func (*EtherTalkPeer) Class added in v0.0.12

func (p *EtherTalkPeer) Class() TargetClass

Class returns TargetClassAppleTalkPeer.

func (*EtherTalkPeer) Forward

func (p *EtherTalkPeer) Forward(ctx context.Context, pkt *ddp.ExtPacket) error

Forward forwards a DDP packet to the next router.

func (*EtherTalkPeer) RouteTargetKey added in v0.0.9

func (p *EtherTalkPeer) RouteTargetKey() string

RouteTargetKey returns "EtherTalkPeer|device name|peer address".

func (*EtherTalkPeer) String added in v0.0.9

func (p *EtherTalkPeer) String() string

type EtherTalkPort

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

EtherTalkPort is all the data and helpers needed for EtherTalk on one port.

func (*EtherTalkPort) Broadcast

func (port *EtherTalkPort) Broadcast(pkt *ddp.ExtPacket) error

Broadcast broadcasts the DDP packet on this port.

func (*EtherTalkPort) Class added in v0.0.12

func (port *EtherTalkPort) Class() TargetClass

Class returns TargetClassDirect.

func (*EtherTalkPort) Forward added in v0.0.9

func (port *EtherTalkPort) Forward(ctx context.Context, pkt *ddp.ExtPacket) error

Forward is another name for Send. (EtherTalk ports can be used as a route target.)

func (*EtherTalkPort) HandleNBP

func (port *EtherTalkPort) HandleNBP(ctx context.Context, ddpkt *ddp.ExtPacket) error

func (*EtherTalkPort) HandleRTMP

func (port *EtherTalkPort) HandleRTMP(ctx context.Context, pkt *ddp.ExtPacket) error

RTMPMachine implements RTMP on an AppleTalk network attached to the router.

func (*EtherTalkPort) HandleZIP

func (port *EtherTalkPort) HandleZIP(ctx context.Context, ddpkt *ddp.ExtPacket) error

func (*EtherTalkPort) Outbox added in v0.0.16

func (port *EtherTalkPort) Outbox(ctx context.Context, wg *sync.WaitGroup)

Outbox runs a loop that waits for AARP resolutions to complete, and once they are, transmit packets that were buffered.

func (*EtherTalkPort) RouteTargetKey added in v0.0.9

func (port *EtherTalkPort) RouteTargetKey() string

RouteTargetKey returns "EtherTalkPort|device name".

func (*EtherTalkPort) RunAARP added in v0.0.16

func (port *EtherTalkPort) RunAARP(ctx context.Context) (err error)

RunAARP runs the AARP state machine.

func (*EtherTalkPort) RunRTMP

func (port *EtherTalkPort) RunRTMP(ctx context.Context) (err error)

RunRTMP makes periodic RTMP Data broadcasts on this port.

func (*EtherTalkPort) Send

func (port *EtherTalkPort) Send(ctx context.Context, pkt *ddp.ExtPacket) error

Send sends a DDP packet out this port to the destination node. If pkt.DstNode = 0xFF, then the packet is broadcast.

func (*EtherTalkPort) Serve

func (port *EtherTalkPort) Serve(ctx context.Context, wg *sync.WaitGroup)

Serve runs a loop that reads AARP or AppleTalk packets from the network device, and handles them.

func (*EtherTalkPort) StatusCtx added in v0.0.17

func (port *EtherTalkPort) StatusCtx(ctx context.Context) context.Context

StatusCtx returns a context with a new status grouping specifically for this port.

func (*EtherTalkPort) String added in v0.0.9

func (port *EtherTalkPort) String() string

func (*EtherTalkPort) ZoneMulticast

func (port *EtherTalkPort) ZoneMulticast(zone string, pkt *ddp.ExtPacket) error

ZoneMulticast broadcasts the DDP packet to a zone multicast hwaddr. The specific address used is computed from the zone name.

type ReceiverState

type ReceiverState int32
const (
	ReceiverUnconnected ReceiverState = iota
	ReceiverConnected
	ReceiverWaitForOpenRsp
	ReceiverWaitForRIRsp
	ReceiverWaitForTickleAck
)

func (ReceiverState) String

func (rs ReceiverState) String() string

type Route

type Route struct {
	RouteKey // embeds TargetKey and NetStart

	Extended bool
	NetEnd   ddp.Network

	// Target provides a way to forward packets using this route
	Target RouteTarget

	Distance uint8
	LastSeen time.Time
	// contains filtered or unexported fields
}

Route represents a route: a destination network range, a way to send packets towards the destination, and some other data that affects whether the route is used.

func (Route) Valid

func (r Route) Valid() bool

Valid reports whether the route is valid. A valid route has a target, one or more zone names, and if it is learned from an AppleTalk router, the last data update is not too old.

func (Route) Zero added in v0.0.12

func (r Route) Zero() bool

Zero reports whether the route is a zero value for Route (trivially invalid).

func (Route) ZoneNames

func (r Route) ZoneNames() []string

ZoneNames returns the zone names for the network associated with this route.

type RouteKey added in v0.0.9

type RouteKey struct {
	TargetKey string
	NetStart  ddp.Network
}

RouteKey is a comparable struct for identifying a specific route. A route can be specified by the target and the start of the network range.

type RouteTable

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

RouteTable is an in-memory database of routes.

func NewRouteTable

func NewRouteTable(ctx context.Context) *RouteTable

NewRouteTable initialises a new empty route table.

func (*RouteTable) AddObserver

func (rt *RouteTable) AddObserver(obs RouteTableObserver)

AddObserver adds a route table observer.

func (*RouteTable) AddZonesToNetwork

func (rt *RouteTable) AddZonesToNetwork(n ddp.Network, zs ...string) error

AddZonesToRoute adds zone names to the network.

func (*RouteTable) AllZoneNames

func (rt *RouteTable) AllZoneNames() []string

AllZoneNames returns all zone names known to the router having at least one valid route. This is used by the ZIP GetZoneList function.

func (*RouteTable) DeleteRoute added in v0.0.9

func (rt *RouteTable) DeleteRoute(target RouteTarget, netStart ddp.Network) error

DeleteRoute deletes the route specified by the (target, netStart) tuple.

func (*RouteTable) DeleteTarget added in v0.0.9

func (rt *RouteTable) DeleteTarget(target RouteTarget)

DeleteTarget deletes the route target and all its routes.

func (*RouteTable) Dump

func (rt *RouteTable) Dump() (allRoutes []Route)

Dump returns all routes in the table.

func (*RouteTable) Lookup added in v0.0.9

func (rt *RouteTable) Lookup(network ddp.Network) Route

Lookup returns the best valid route for the network number. If there is no valid route, the zero Route is returned (it will have nil Target).

func (*RouteTable) RemoveObserver

func (rt *RouteTable) RemoveObserver(obs RouteTableObserver)

RemoveObserver removes a route table observer.

func (*RouteTable) RoutesForZone

func (rt *RouteTable) RoutesForZone(zone string) []Route

RoutesForZone returns best routes for the zone name. (Zones can span multiple different networks.) This is used for handling NBP BrRq.

func (*RouteTable) UpdateDistance added in v0.0.12

func (rt *RouteTable) UpdateDistance(target RouteTarget, netStart ddp.Network, distance uint8) error

UpdateDistance updates the distance for an existing route.

func (*RouteTable) UpsertRoute added in v0.0.9

func (rt *RouteTable) UpsertRoute(target RouteTarget, extended bool, netStart, netEnd ddp.Network, distance uint8) (Route, error)

UpsertRoute validates and inserts a new route or updates an existing route. It always returns a new Route (new route structs fully replace old ones).

func (*RouteTable) ValidRoutes

func (rt *RouteTable) ValidRoutes(yield func(Route) bool)

ValidRoutes yields all valid routes.

func (*RouteTable) ValidRoutesForClass added in v0.0.12

func (rt *RouteTable) ValidRoutesForClass(class TargetClass) iter.Seq[Route]

ValidRoutesForClass returns an iterator that yields all valid routes for a given target class.

func (*RouteTable) ZonesForNetworks

func (rt *RouteTable) ZonesForNetworks(networks []ddp.Network) map[ddp.Network][]string

ZonesForNetworks returns a map of network numbers to zone names in each. It only considers valid routes.

type RouteTableObserver

type RouteTableObserver interface {
	// NetworkAdded is called when a network becomes routable.
	NetworkAdded(best Route)

	// NetworkDeleted is called when a network becomes _un_routable.
	NetworkDeleted(oldBest Route)

	// BestNetworkChanged is called when the best routing distance
	// or route for a network has changed (from e.g. a direct EtherTalk
	// connection to an AURP peer).
	BestNetworkChanged(from, to Route)
}

RouteTableObserver implementations can receive notifications of route table changes. (TODO, not yet implemented)

type RouteTarget added in v0.0.9

type RouteTarget interface {
	// Forward should send the packet to the route target.
	Forward(context.Context, *ddp.ExtPacket) error

	// Class returns the target class for this target.
	Class() TargetClass

	// RouteTargetKey is used for determining if two targets are the same.
	RouteTargetKey() string
}

RouteTarget implementations can forward packets somewhere.

type Router

type Router struct {
	Logger     *slog.Logger
	Config     *Config
	RouteTable *RouteTable
	Ports      []*EtherTalkPort
	AURPPeers  *AURPPeerTable
}

Router implements the core routing logic.

func (*Router) AURPInput added in v0.0.14

func (r *Router) AURPInput(ctx context.Context, logger *slog.Logger, wg *sync.WaitGroup, cfg *Config, udpConn *net.UDPConn, localDI aurp.DomainIdentifier)

AURPInput is a packet listening loop on a UDP connection for AURP.

func (*Router) Forward

func (rtr *Router) Forward(ctx context.Context, ddpkt *ddp.ExtPacket) error

Forward increments the hop count, then outputs the packet in the direction of the destination.

func (*Router) HandleAEP

func (rtr *Router) HandleAEP(ctx context.Context, ddpkt *ddp.ExtPacket) error

func (*Router) HandleNBPFromAURP

func (rtr *Router) HandleNBPFromAURP(ctx context.Context, ddpkt *ddp.ExtPacket) error

func (*Router) NewEtherTalkPort added in v0.0.16

func (router *Router) NewEtherTalkPort(
	device string,
	ethernetAddr ethernet.Addr,
	netStart ddp.Network,
	netEnd ddp.Network,
	defaultZoneName string,
	availableZones Set[string],
	pcapHandle *pcap.Handle) *EtherTalkPort

NewEtherTalkPort defines a new EtherTalk port for the router.

func (*Router) Output

func (rtr *Router) Output(ctx context.Context, ddpkt *ddp.ExtPacket) error

Output outputs the packet in the direction of the destination. (It does not check or adjust the hop count.)

type SenderState

type SenderState int32
const (
	SenderUnconnected SenderState = iota
	SenderConnected
	SenderWaitForRIRspAck
	SenderWaitForRIUpdAck
	SenderWaitForRDAck
)

func (SenderState) String

func (ss SenderState) String() string

type Set added in v0.0.17

type Set[K comparable] map[K]struct{}

Set is a generic set. Yep, yet another set implementation. Took me 2 minutes to write *shrug*

func MakeSet added in v0.0.17

func MakeSet[K comparable](ss ...K) Set[K]

func (Set[K]) Add added in v0.0.17

func (set Set[K]) Add(t Set[K])

func (Set[K]) Contains added in v0.0.17

func (set Set[K]) Contains(s K) bool

func (Set[K]) Insert added in v0.0.17

func (set Set[K]) Insert(ss ...K)

func (Set[K]) ToSlice added in v0.0.17

func (set Set[K]) ToSlice() []K

type TargetClass added in v0.0.12

type TargetClass int

TargetClass is an enum type for representing the broad classes of route targets.

const (
	TargetClassDirect        TargetClass = iota // directly attached EtherTalk / LocalTalk / etc network
	TargetClassAURPPeer                         // another router over AURP
	TargetClassAppleTalkPeer                    // another router via EtherTalk / LocalTalk / etc
	TargetClassCount                            // how many valid target types there are - insert new classes above.
)

Target class values.

Jump to

Keyboard shortcuts

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