ra

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: May 26, 2024 License: Apache-2.0 Imports: 23 Imported by: 0

README

go-ra

Go Reference

Provides the ra package that implements a router-side functionality of IPv6 Neighbor Discovery mechanism (RFC4861 and related RFCs). It also provides a stand-alone daemon gorad and CLI tool gora to interact with it. While the existing mdlayher/ndp package provides a low-level protocol functionalities (packet encoding, raw-socket wrapper, etc), go-ra implements an unsolicited and solicited advertisement machinery and declarative configuration interface on top of it.

Features

  • Basic RA mechanism defined in RFC4861
  • Router MAC address discovery with Source Link Layer Address option
  • MTU discovery with MTU option
  • Prefix discovery with Prefix Information option
  • DNS configuration discovery with RDNSS/DNSSL option
  • Route advertisement with Route Information option

Installation

  • Library: Use Go Modules as usual
  • Stand-alone Binary: Visit release page and install pre-build binaries
  • Container Image: Visit registry page and pull images

Basic Usage

As a library
// Build a configuration
config := ra.Config{
	  Interfaces: []*ra.InterfaceConfig{
		    {
			      Name: "eth0",
			      // Send unsolicited RA once a second
			      RAIntervalMilliseconds: 1000, // 1sec
		    },	
	  },
}

// Create an RA daemon
daemon, _ := ra.NewDaemon(&config)

// Run it
ctx, cancel := context.WithCancel(context.Background())
go daemon.Run(ctx)

// Get a running status
status := daemon.Status()
for _, iface := range status.Interfaces {
    fmt.Printf("%s: %s (%s)\n", iface.Name, iface.State, iface.Message)
}

// Change configuration and reload
config.Interfaces[0].RAIntervalMilliseconds = 2000 // 2sec
err := daemon.Reload(ctx, &config)
if err != nil {
    panic(err)
}

// Stop it
cancel()
As a stand-alone daemon

Create a configuration file. This configuration will be translated into the Config object and passed to the daemon. Please see the godoc for more details.

interfaces:
- name: eth0
  raIntervalMilliseconds: 1000 # 1sec

Start daemon. You need a root privilege to run it.


$ sudo gorad -f config.yaml

Get status.

$ gora status
Name         Age    TxUnsolicited    TxSolicited    State      Message
eth0         22s    21               1              Running

Modify and reload configuration

$ gora reload -f config.yaml

Motivation

Our original motivation for this project was use it with gobgp library to do BGP Unnumbered (see our integration test) which for us, makes sense to reinvent the RA daemon to not introduce an external non-go dependency.

Documentation

Index

Constants

View Source
const (
	// Running means the router advertisement is running
	Running = "Running"
	// Reloading means the router advertisement is reloading the configuration
	Reloading = "Reloading"
	// Failing means the router advertisement is failing with an error
	Failing = "Failing"
	// Stopped means the router advertisement is stopped
	Stopped = "Stopped"
)

Possible interface status

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Interface-specific configuration parameters. The Name field must be
	// unique within the slice. The slice itself and elements must not be
	// nil.
	Interfaces []*InterfaceConfig `yaml:"interfaces" json:"interfaces" validate:"unique=Name,dive,required" default:"[]"`
}

Config represents the configuration of the daemon

func ParseConfigJSON

func ParseConfigJSON(r io.Reader) (*Config, error)

ParseConfigJSON parses the JSON-encoded configuration from the reader. This function doesn't validate the configuration. The configuration is validated when you pass it to the Daemon.

func ParseConfigYAML

func ParseConfigYAML(r io.Reader) (*Config, error)

ParseConfigYAML parses the YAML-encoded configuration from the reader. This function doesn't validate the configuration. The configuration is validated when you pass it to the Daemon.

func ParseConfigYAMLFile

func ParseConfigYAMLFile(path string) (*Config, error)

ParseConfigYAMLFile parses the YAML-encoded configuration from the file at the given path. This function doesn't validate the configuration. The configuration is validated when you pass it to the Daemon.

type DNSSLConfig added in v0.2.0

type DNSSLConfig struct {
	// Required: The maximum time in seconds over which these DNSSL domain
	// names may be used for name resolution.
	LifetimeSeconds int `yaml:"lifetimeSeconds" json:"lifetimeSeconds" validate:"required,gte=0,lte=4294967295"`

	// Required: The domain names to be used for DNS search list. You must specify at least one domain name.
	DomainNames []string `yaml:"domainNames" json:"domainNames" validate:"required,unique,min=1,dive,domain"`
}

DNSSLConfig represents the DNSSL-specific configuration parameters

type Daemon

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

Daemon is the main struct for the ra daemon

func NewDaemon

func NewDaemon(config *Config, opts ...DaemonOption) (*Daemon, error)

NewDaemon creates a new Daemon instance with the provided configuration and options. It returns ValidationErrors if the configuration is invalid.

func (*Daemon) Reload

func (d *Daemon) Reload(ctx context.Context, newConfig *Config) error

Reload reloads the configuration of the daemon. The context passed to this function is used to cancel the potentially long-running operations during the reload process. Currently, the result of the unsucecssful or cancelled reload is undefined and the daemon may be running with either the old or the new configuration or both. It returns ValidationErrors if the configuration is invalid.

func (*Daemon) Run

func (d *Daemon) Run(ctx context.Context)

Run starts the daemon and blocks until the context is cancelled

func (*Daemon) Status

func (d *Daemon) Status() *Status

Status returns the current status of the daemon

type DaemonOption

type DaemonOption func(*Daemon)

DaemonOption is an optional parameter for the Daemon constructor

func WithLogger

func WithLogger(l *slog.Logger) DaemonOption

WithLogger overrides the default logger with the provided one.

type InterfaceConfig

type InterfaceConfig struct {
	// Required: Network interface name. Must be unique within the configuration.
	Name string `yaml:"name" json:"name" validate:"required"`

	// Required: Interval between sending unsolicited RA. Must be >= 70 and
	// <= 1800000. Default is 600000. The upper bound is chosen to be
	// compliant with RFC4861. The lower bound is intentionally chosen to
	// be lower than RFC4861 for faster convergence. If you don't wish to
	// overwhelm the network, and wish to be compliant with RFC4861, set to
	// higher than 3000 as RFC4861 suggests.
	RAIntervalMilliseconds int `yaml:"raIntervalMilliseconds" json:"raIntervalMilliseconds" validate:"required,gte=70,lte=1800000" default:"600000"`

	// The default value that should be placed in the Hop Count field of
	// the IP header for outgoing IP packets. Must be >= 0 and <= 255.
	// Default is 0. If set to zero, it means the reachable time is
	// unspecified by this router.
	CurrentHopLimit int `yaml:"currentHopLimit" json:"currentHopLimit" validate:"gte=0,lte=255" default:"0"`

	// Set M (Managed address configuration) flag. When set, it indicates
	// that addresses are available via DHCPv6. Default is false.
	Managed bool `yaml:"managed" json:"managed"`

	// Set O (Other configuration) flag. When set, it indicates that other
	// configuration information is available via DHCPv6. Default is false.
	Other bool `yaml:"other" json:"other"`

	// Set Prf (Default Router Preference) field. Must be one of "low",
	// "medium", or "high". If RouterLifetimeSeconds is 0, it must be set
	// to "medium". Default is "medium".
	Preference string `yaml:"preference" json:"preference" validate:"eq_if medium RouterLifetimeSeconds 0,oneof=low medium high" default:"medium"`

	// The lifetime associated with the default router in seconds. Must be
	// >= 0 and <= 65535. Default is 0. The upper bound is chosen to be
	// compliant to the RFC8319. If set to zero, the router is not
	// considered as a default router.
	RouterLifetimeSeconds int `yaml:"routerLifetimeSeconds" json:"routerLifetimeSeconds" validate:"gte=0,lte=65535"`

	// The time, in milliseconds, that a node assumes a neighbor is
	// reachable after having received a reachability confirmation. Must be
	// >= 0 and <= 4294967295. Default is 0. If set to zero, it means the
	// reachable time is unspecified by this router.
	ReachableTimeMilliseconds int `yaml:"reachableTimeMilliseconds" json:"reachableTimeMilliseconds" validate:"gte=0,lte=4294967295"`

	// The time, in milliseconds, between retransmitted Neighbor
	// Solicitation messages. Must be >= 0 and <= 4294967295. Default is 0.
	// If set to zero, it means the retransmission time is unspecified by
	// this router.
	RetransmitTimeMilliseconds int `yaml:"retransmitTimeMilliseconds" json:"retransmitTimeMilliseconds" validate:"gte=0,lte=4294967295"`

	// The maximum transmission unit (MTU) that should be used for outgoing
	// This value specifies the largest packet size, in bytes,
	// If set to zero or not specified, MTU opton will not be advertised
	MTU int `yaml:"mtu" json:"mtu" validate:"gte=0,lte=4294967295"`

	// Prefix-specific configuration parameters. The prefix fields must be
	// non-overlapping with each other. The slice itself and elements must
	// not be nil.
	Prefixes []*PrefixConfig `yaml:"prefixes" json:"prefixes" validate:"non_overlapping_prefix,dive,required" default:"[]"`

	// Route-specific configuration parameters. The prefix fields must not
	// be the same each other. The slice itself and elements must not be nil.
	Routes []*RouteConfig `yaml:"routes" json:"routes" validate:"unique=Prefix,dive,required" default:"[]"`

	// RDNSS-specific configuration parameters.
	RDNSSes []*RDNSSConfig `yaml:"rdnsses" json:"rdnsses" validate:"dive,required" default:"[]"`

	// DNSSL-specific configuration parameters.
	DNSSLs []*DNSSLConfig `yaml:"dnssls" json:"dnssls" validate:"dive,required" default:"[]"`
}

InterfaceConfig represents the interface-specific configuration parameters

type InterfaceStatus

type InterfaceStatus struct {
	// Interface name
	Name string `yaml:"name" json:"name"`

	// Status of the router advertisement on the interface
	State string `yaml:"state" json:"state"`

	// Error message maybe set when the state is Failing or Stopped
	Message string `yaml:"message,omitempty" json:"message,omitempty"`

	// Last configuration update time in Unix time
	LastUpdate int64 `yaml:"lastUpdate" json:"lastUpdate"`

	// Number of sent solicited router advertisements
	TxSolicitedRA int `yaml:"txSolicitedRA" json:"txSolicitedRA"`

	// Number of sent unsolicited router advertisements
	TxUnsolicitedRA int `yaml:"txUnsolicitedRA" json:"txUnsolicitedRA"`
}

InterfaceStatus represents the interface-specific status of the Daemon

type PrefixConfig added in v0.1.0

type PrefixConfig struct {
	// Required: Prefix. Must be a valid IPv6 prefix.
	Prefix string `yaml:"prefix" json:"prefix" validate:"required,cidrv6"`

	// Set L (On-Link) flag. When set, it indicates that this prefix can be
	// used for on-link determination. Default is false.
	OnLink bool `yaml:"onLink" json:"onLink"`

	// Set A (Autonomous address-configuration) flag. When set, it indicates
	// that this prefix can be used for stateless address autoconfiguration.
	// Default is false.
	Autonomous bool `yaml:"autonomous" json:"autonomous"`

	// The valid lifetime of the prefix in seconds. Must be >= 0 and <=
	// 4294967295 and must be >= PreferredLifetimeSeconds. Default is
	// 2592000 (30 days). If set to 4294967295, it indicates infinity.
	ValidLifetimeSeconds *int `yaml:"validLifetimeSeconds" json:"validLifetimeSeconds" validate:"required,gte=0,lte=4294967295" default:"2592000"`

	// The preferred lifetime of the prefix in seconds. Must be >= 0 and <=
	// 4294967295 and must be <= ValidLifetimeSeconds. Default is 604800 (7
	// days). If set to 4294967295, it indicates infinity.
	PreferredLifetimeSeconds *int `` /* 136-byte string literal not displayed */
}

PrefixConfig represents the prefix-specific configuration parameters

type RDNSSConfig added in v0.2.0

type RDNSSConfig struct {
	// Required: The maximum time in seconds over which these RDNSS
	// addresses may be used for name resolution.
	LifetimeSeconds int `yaml:"lifetimeSeconds" json:"lifetimeSeconds" validate:"required,gte=0,lte=4294967295"`

	// Required: The addresses of the RDNSS servers. You must specify at least one address.
	Addresses []string `yaml:"addresses" json:"addresses" validate:"required,unique,min=1,dive,ipv6"`
}

RDNSSConfig represents the RDNSS-specific configuration parameters

type RouteConfig added in v0.2.0

type RouteConfig struct {
	// Required: Prefix. Must be a valid IPv6 prefix.
	Prefix string `yaml:"prefix" json:"prefix" validate:"required,cidrv6"`

	// Required: The valid lifetime of the route in seconds. Must be >= 0
	// and <= 4294967295. If set to 4294967295, it indicates infinity.
	LifetimeSeconds int `yaml:"lifetimeSeconds" json:"lifetimeSeconds" validate:"required,gte=0,lte=4294967295"`

	// Set Prf (Route Preference) field. It indicates whether to prefer the
	// router associated with this prefix over others, when multiple
	// identical prefixes (for different routers) have been received. Must
	// be one of "low", "medium", or "high". Default is "medium".
	Preference string `yaml:"preference" json:"preference" validate:"oneof=low medium high" default:"medium"`
}

RouteConfig represents the route-specific configuration parameters

type Status

type Status struct {
	// Interfaces-specific status
	Interfaces []*InterfaceStatus `yaml:"interfaces" json:"interfaces"`
}

Status is the status of the Daemon

type ValidationErrors

type ValidationErrors = validator.ValidationErrors

ValidationErrors is a type alias for the validator.ValidationErrors

Directories

Path Synopsis
cmd
tools

Jump to

Keyboard shortcuts

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