Documentation
¶
Overview ¶
Package rtnetlink allows the kernel's routing tables to be read and altered. Network routes, IP addresses, Link parameters, Neighbor setups, Queueing disciplines, Traffic classes and Packet classifiers may all be controlled. It is based on netlink messages.
A convenient, high-level API wrapper is available using package rtnl: https://godoc.org/github.com/jsimonetti/rtnetlink/rtnl.
The base rtnetlink library xplicitly only exposes a limited low-level API to rtnetlink. It is not the intention (nor wish) to create an iproute2 replacement.
When in doubt about your message structure it can always be useful to look at the message send by iproute2 using 'strace -f -esendmsg' or similar.
Another (and possibly even more flexible) way would be using 'nlmon' and wireshark. nlmod is a special kernel module which allows you to capture all (not just rtnetlink) netlink traffic inside the kernel. Be aware that this might be overwhelming on a system with a lot of netlink traffic.
# modprobe nlmon # ip link add type nlmon # ip link set nlmon0 up
At this point use wireshark or tcpdump on the nlmon0 interface to view all netlink traffic.
Have a look at the examples for common uses of rtnetlink.
Example (AddAddress) ¶
Add IP address '127.0.0.2/8' to an interface 'lo'
package main import ( "encoding/binary" "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("lo") // Get an ip address to add to the interface addr, cidr, _ := net.ParseCIDR("127.0.0.2/8") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Test for the right address family for addr family := unix.AF_INET6 to4 := cidr.IP.To4() if to4 != nil { family = unix.AF_INET } // Calculate the prefix length ones, _ := cidr.Mask.Size() // Calculate the broadcast IP // Only used when family is AF_INET var brd net.IP if to4 != nil { brd = make(net.IP, len(to4)) binary.BigEndian.PutUint32(brd, binary.BigEndian.Uint32(to4)|^binary.BigEndian.Uint32(net.IP(cidr.Mask).To4())) } // Send the message using the rtnetlink.Conn err = conn.Address.New(&rtnetlink.AddressMessage{ Family: uint8(family), PrefixLength: uint8(ones), Scope: unix.RT_SCOPE_UNIVERSE, Index: uint32(iface.Index), Attributes: &rtnetlink.AddressAttributes{ Address: addr, Local: addr, Broadcast: brd, }, }) log.Fatal(err) }
Output:
Example (AddRoute) ¶
Add a route
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("lo") // Get a route to add _, dst, _ := net.ParseCIDR("192.168.0.0/16") // Get a gw to use gw := net.ParseIP("127.0.0.1") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() attr := rtnetlink.RouteAttributes{ Dst: dst.IP, OutIface: uint32(iface.Index), } if gw == nil { attr.Gateway = gw } ones, _ := dst.Mask.Size() err = conn.Route.Add(&rtnetlink.RouteMessage{ Family: unix.AF_INET, Table: unix.RT_TABLE_MAIN, Protocol: unix.RTPROT_BOOT, Scope: unix.RT_SCOPE_LINK, Type: unix.RTN_UNICAST, DstLength: uint8(ones), Attributes: attr, }) log.Fatal(err) }
Output:
Example (DeleteAddress) ¶
Delete IP address '127.0.0.2/8' from interface 'lo'
package main import ( "encoding/binary" "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("lo") // Get an ip address to delete from the interface addr, cidr, _ := net.ParseCIDR("127.0.0.2/8") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Test for the right address family for addr family := unix.AF_INET6 to4 := cidr.IP.To4() if to4 != nil { family = unix.AF_INET } // Calculate the prefix length ones, _ := cidr.Mask.Size() // Calculate the broadcast IP // Only used when family is AF_INET var brd net.IP if to4 != nil { brd = make(net.IP, len(to4)) binary.BigEndian.PutUint32(brd, binary.BigEndian.Uint32(to4)|^binary.BigEndian.Uint32(net.IP(cidr.Mask).To4())) } // Send the message using the rtnetlink.Conn err = conn.Address.Delete(&rtnetlink.AddressMessage{ Family: uint8(family), PrefixLength: uint8(ones), Index: uint32(iface.Index), Attributes: &rtnetlink.AddressAttributes{ Address: addr, Broadcast: brd, }, }) log.Fatal(err) }
Output:
Example (ListAddress) ¶
List all IPv4 addresses configured on interface 'lo'
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("lo") // Get an ip address to add to the interface family := uint8(unix.AF_INET) // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request a list of addresses msg, err := conn.Address.List() if err != nil { log.Fatal(err) } // Filter out the wanted messages and put them in the 'addr' slice. var addr []rtnetlink.AddressMessage for _, v := range msg { add := true if iface != nil && v.Index != uint32(iface.Index) { add = false } if family != 0 && v.Family != family { add = false } if add { addr = append(addr, v) } } log.Printf("%#v", addr) }
Output:
Example (ListLink) ¶
List all interfaces
package main import ( "log" "github.com/jsimonetti/rtnetlink" ) func main() { // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request a list of interfaces msg, err := conn.Link.List() if err != nil { log.Fatal(err) } log.Printf("%#v", msg) }
Output:
Example (ListNeighbors) ¶
List all neighbors on interface 'lo'
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("lo") // Get an ip address to add to the interface family := uint8(unix.AF_INET) // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request all neighbors msg, err := conn.Neigh.List() if err != nil { log.Fatal(err) } // Filter neighbors by family and interface index var neigh []rtnetlink.NeighMessage for _, v := range msg { add := true if iface != nil && v.Index != uint32(iface.Index) { add = false } if family != 0 && v.Family != uint16(family) { add = false } if add { neigh = append(neigh, v) } } log.Printf("%#v", neigh) }
Output:
Example (SetLinkDown) ¶
Set the operational state an interface to Down
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("dummy0") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request the details of the interface msg, err := conn.Link.Get(uint32(iface.Index)) if err != nil { log.Fatal(err) } state := msg.Attributes.OperationalState // If the link is already down, return immediately if state == rtnetlink.OperStateDown { return } // Set the interface operationally Down err = conn.Link.Set(&rtnetlink.LinkMessage{ Family: msg.Family, Type: msg.Type, Index: uint32(iface.Index), Flags: 0x0, Change: 0x1, }) log.Fatal(err) }
Output:
Example (SetLinkHWAddr) ¶
Set the hw address of an interface
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("dummy0") // Get a hw addr to set the interface to hwAddr, _ := net.ParseMAC("ce:9c:5b:98:55:9c") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request the details of the interface msg, err := conn.Link.Get(uint32(iface.Index)) if err != nil { log.Fatal(err) } // Set the hw address of the interfaces err = conn.Link.Set(&rtnetlink.LinkMessage{ Family: msg.Family, Type: msg.Type, Index: uint32(iface.Index), Flags: msg.Flags, Change: msg.Change, Attributes: &rtnetlink.LinkAttributes{ Address: hwAddr, }, }) log.Fatal(err) }
Output:
Example (SetLinkUp) ¶
Set the operational state an interface to Up
package main import ( "log" "net" "github.com/jsimonetti/rtnetlink" "golang.org/x/sys/unix" ) func main() { // Gather the interface Index iface, _ := net.InterfaceByName("dummy0") // Dial a connection to the rtnetlink socket conn, err := rtnetlink.Dial(nil) if err != nil { log.Fatal(err) } defer conn.Close() // Request the details of the interface msg, err := conn.Link.Get(uint32(iface.Index)) if err != nil { log.Fatal(err) } state := msg.Attributes.OperationalState // If the link is already up, return immediately if state == rtnetlink.OperStateUp || state == rtnetlink.OperStateUnknown { return } // Set the interface operationally UP err = conn.Link.Set(&rtnetlink.LinkMessage{ Family: msg.Family, Type: msg.Type, Index: uint32(iface.Index), Flags: unix.IFF_UP, Change: unix.IFF_UP, }) log.Fatal(err) }
Output:
Index ¶
- type AddressAttributes
- type AddressMessage
- type AddressService
- type CacheInfo
- type Conn
- func (c *Conn) Close() error
- func (c *Conn) Execute(m Message, family uint16, flags netlink.HeaderFlags) ([]Message, error)
- func (c *Conn) Receive() ([]Message, []netlink.Message, error)
- func (c *Conn) Send(m Message, family uint16, flags netlink.HeaderFlags) (netlink.Message, error)
- func (c *Conn) SetOption(option netlink.ConnOption, enable bool) error
- func (c *Conn) SetReadDeadline(t time.Time) error
- type LinkAttributes
- type LinkInfo
- type LinkMessage
- type LinkService
- func (l *LinkService) Delete(index uint32) error
- func (l *LinkService) Get(index uint32) (LinkMessage, error)
- func (l *LinkService) List() ([]LinkMessage, error)
- func (l *LinkService) ListByKind(kind string) ([]LinkMessage, error)
- func (l *LinkService) New(req *LinkMessage) error
- func (l *LinkService) Set(req *LinkMessage) error
- type LinkStats
- type LinkStats64
- type LinkXDP
- type MPLSNextHop
- type Message
- type NeighAttributes
- type NeighCacheInfo
- type NeighMessage
- type NeighService
- type NextHop
- type OperationalState
- type RTNextHop
- type RouteAttributes
- type RouteMessage
- type RouteMetrics
- type RouteService
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AddressAttributes ¶
type AddressAttributes struct { Address net.IP // Interface Ip address Local net.IP // Local Ip address Label string Broadcast net.IP // Broadcast Ip address Anycast net.IP // Anycast Ip address CacheInfo CacheInfo // Address information Multicast net.IP // Multicast Ip address Flags uint32 // Address flags }
AddressAttributes contains all attributes for an interface.
type AddressMessage ¶
type AddressMessage struct { // Address family (current unix.AF_INET or unix.AF_INET6) Family uint8 // Prefix length PrefixLength uint8 // Contains address flags Flags uint8 // Address Scope Scope uint8 // Interface index Index uint32 // Optional attributes which are appended when not nil. Attributes *AddressAttributes }
A AddressMessage is a route netlink address message.
func (*AddressMessage) MarshalBinary ¶
func (m *AddressMessage) MarshalBinary() ([]byte, error)
MarshalBinary marshals a AddressMessage into a byte slice.
func (*AddressMessage) UnmarshalBinary ¶
func (m *AddressMessage) UnmarshalBinary(b []byte) error
UnmarshalBinary unmarshals the contents of a byte slice into a AddressMessage.
type AddressService ¶
type AddressService struct {
// contains filtered or unexported fields
}
AddressService is used to retrieve rtnetlink family information.
func (*AddressService) Delete ¶
func (a *AddressService) Delete(req *AddressMessage) error
Delete removes an address using the AddressMessage information.
func (*AddressService) List ¶
func (a *AddressService) List() ([]AddressMessage, error)
List retrieves all addresses.
func (*AddressService) New ¶
func (a *AddressService) New(req *AddressMessage) error
New creates a new address using the AddressMessage information.
type Conn ¶
type Conn struct { Link *LinkService Address *AddressService Route *RouteService Neigh *NeighService // contains filtered or unexported fields }
A Conn is a route netlink connection. A Conn can be used to send and receive route netlink messages to and from netlink.
func Dial ¶
Dial dials a route netlink connection. Config specifies optional configuration for the underlying netlink connection. If config is nil, a default configuration will be used.
func (*Conn) Execute ¶
Execute sends a single Message to netlink using Send, receives one or more replies using Receive, and then checks the validity of the replies against the request using netlink.Validate.
Execute acquires a lock for the duration of the function call which blocks concurrent calls to Send and Receive, in order to ensure consistency between generic netlink request/reply messages.
See the documentation of Send, Receive, and netlink.Validate for details about each function.
func (*Conn) Receive ¶
Receive receives one or more Messages from netlink. The netlink.Messages used to wrap each Message are available for later validation.
func (*Conn) Send ¶
Send sends a single Message to netlink, wrapping it in a netlink.Message using the specified generic netlink family and flags. On success, Send returns a copy of the netlink.Message with all parameters populated, for later validation.
type LinkAttributes ¶
type LinkAttributes struct { Address net.HardwareAddr // Interface L2 address Broadcast net.HardwareAddr // L2 broadcast address Name string // Device name MTU uint32 // MTU of the device Type uint32 // Link type QueueDisc string // Queueing discipline Master *uint32 // Master device index (0 value un-enslaves) OperationalState OperationalState // Interface operation state Stats *LinkStats // Interface Statistics Stats64 *LinkStats64 // Interface Statistics (64 bits version) Info *LinkInfo // Detailed Interface Information XDP *LinkXDP // Express Data Patch Information }
LinkAttributes contains all attributes for an interface.
type LinkInfo ¶
type LinkInfo struct { Kind string // Driver name Data []byte // Driver specific configuration stored as nested Netlink messages SlaveKind string // Slave driver name SlaveData []byte // Slave driver specific configuration }
LinkInfo contains data for specific network types
type LinkMessage ¶
type LinkMessage struct { // Always set to AF_UNSPEC (0) Family uint16 // Device Type Type uint16 // Unique interface index, using a nonzero value with // NewLink will instruct the kernel to create a // device with the given index (kernel 3.7+ required) Index uint32 // Contains device flags, see netdevice(7) Flags uint32 // Change Flags, specifies which flags will be affected by the Flags field Change uint32 // Attributes List Attributes *LinkAttributes }
A LinkMessage is a route netlink link message.
func (*LinkMessage) MarshalBinary ¶
func (m *LinkMessage) MarshalBinary() ([]byte, error)
MarshalBinary marshals a LinkMessage into a byte slice.
func (*LinkMessage) UnmarshalBinary ¶
func (m *LinkMessage) UnmarshalBinary(b []byte) error
UnmarshalBinary unmarshals the contents of a byte slice into a LinkMessage.
type LinkService ¶
type LinkService struct {
// contains filtered or unexported fields
}
LinkService is used to retrieve rtnetlink family information.
func (*LinkService) Delete ¶
func (l *LinkService) Delete(index uint32) error
Delete removes an interface by index.
func (*LinkService) Get ¶
func (l *LinkService) Get(index uint32) (LinkMessage, error)
Get retrieves interface information by index.
func (*LinkService) List ¶
func (l *LinkService) List() ([]LinkMessage, error)
List retrieves all interfaces.
func (*LinkService) ListByKind ¶
func (l *LinkService) ListByKind(kind string) ([]LinkMessage, error)
ListByKind retrieves all interfaces of a specific kind.
func (*LinkService) New ¶
func (l *LinkService) New(req *LinkMessage) error
New creates a new interface using the LinkMessage information.
func (*LinkService) Set ¶
func (l *LinkService) Set(req *LinkMessage) error
Set sets interface attributes according to the LinkMessage information.
ref: https://lwn.net/Articles/236919/ We explicitly use RTM_NEWLINK to set link attributes instead of RTM_SETLINK because:
- using RTM_SETLINK is actually an old rtnetlink API, not supporting most attributes common today
- using RTM_NEWLINK is the prefered way to create AND update links
- RTM_NEWLINK is backward compatible to RTM_SETLINK
type LinkStats ¶
type LinkStats struct { RXPackets uint32 // total packets received TXPackets uint32 // total packets transmitted RXBytes uint32 // total bytes received TXBytes uint32 // total bytes transmitted RXErrors uint32 // bad packets received TXErrors uint32 // packet transmit problems RXDropped uint32 // no space in linux buffers TXDropped uint32 // no space available in linux Multicast uint32 // multicast packets received Collisions uint32 // detailed rx_errors: RXLengthErrors uint32 RXOverErrors uint32 // receiver ring buff overflow RXCRCErrors uint32 // recved pkt with crc error RXFrameErrors uint32 // recv'd frame alignment error RXFIFOErrors uint32 // recv'r fifo overrun RXMissedErrors uint32 // receiver missed packet // detailed tx_errors TXAbortedErrors uint32 TXCarrierErrors uint32 TXFIFOErrors uint32 TXHeartbeatErrors uint32 TXWindowErrors uint32 // for cslip etc RXCompressed uint32 TXCompressed uint32 RXNoHandler uint32 // dropped, no handler found }
LinkStats contains packet statistics
type LinkStats64 ¶
type LinkStats64 struct { RXPackets uint64 // total packets received TXPackets uint64 // total packets transmitted RXBytes uint64 // total bytes received TXBytes uint64 // total bytes transmitted RXErrors uint64 // bad packets received TXErrors uint64 // packet transmit problems RXDropped uint64 // no space in linux buffers TXDropped uint64 // no space available in linux Multicast uint64 // multicast packets received Collisions uint64 // detailed rx_errors: RXLengthErrors uint64 RXOverErrors uint64 // receiver ring buff overflow RXCRCErrors uint64 // recved pkt with crc error RXFrameErrors uint64 // recv'd frame alignment error RXFIFOErrors uint64 // recv'r fifo overrun RXMissedErrors uint64 // receiver missed packet // detailed tx_errors TXAbortedErrors uint64 TXCarrierErrors uint64 TXFIFOErrors uint64 TXHeartbeatErrors uint64 TXWindowErrors uint64 // for cslip etc RXCompressed uint64 TXCompressed uint64 RXNoHandler uint64 // dropped, no handler found }
LinkStats64 contains packet statistics
type MPLSNextHop ¶
An MPLSNextHop is a route next hop using MPLS encapsulation.
type Message ¶
type Message interface { encoding.BinaryMarshaler encoding.BinaryUnmarshaler // contains filtered or unexported methods }
Message is the interface used for passing around different kinds of rtnetlink messages
type NeighAttributes ¶
type NeighAttributes struct { Address net.IP // a neighbor cache n/w layer destination address LLAddress net.HardwareAddr // a neighbor cache link layer address CacheInfo *NeighCacheInfo // cache statistics IfIndex uint32 }
NeighAttributes contains all attributes for a neighbor.
type NeighCacheInfo ¶
NeighCacheInfo contains neigh information
type NeighMessage ¶
type NeighMessage struct { // Always set to AF_UNSPEC (0) Family uint16 // Unique interface index Index uint32 // Neighbor State is a bitmask of neighbor states (see rtnetlink(7)) State uint16 // Neighbor flags Flags uint8 // Neighbor type Type uint8 // Attributes List Attributes *NeighAttributes }
A NeighMessage is a route netlink neighbor message.
func (*NeighMessage) MarshalBinary ¶
func (m *NeighMessage) MarshalBinary() ([]byte, error)
MarshalBinary marshals a NeighMessage into a byte slice.
func (*NeighMessage) UnmarshalBinary ¶
func (m *NeighMessage) UnmarshalBinary(b []byte) error
UnmarshalBinary unmarshals the contents of a byte slice into a NeighMessage.
type NeighService ¶
type NeighService struct {
// contains filtered or unexported fields
}
NeighService is used to retrieve rtnetlink family information.
func (*NeighService) Delete ¶
func (l *NeighService) Delete(index uint32) error
Delete removes an neighbor entry by index.
func (*NeighService) List ¶
func (l *NeighService) List() ([]NeighMessage, error)
List retrieves all neighbors.
func (*NeighService) New ¶
func (l *NeighService) New(req *NeighMessage) error
New creates a new interface using the LinkMessage information.
type NextHop ¶
type NextHop struct { Hop RTNextHop // a rtnexthop struct Gateway net.IP // that struct's nested Gateway attribute MPLS []MPLSNextHop // Any MPLS next hops for a route. }
NextHop wraps struct rtnexthop to provide access to nested attributes
type OperationalState ¶
type OperationalState uint8
OperationalState represents an interface's operational state.
const ( OperStateUnknown OperationalState = iota // status could not be determined OperStateNotPresent // down, due to some missing component (typically hardware) OperStateDown // down, either administratively or due to a fault OperStateLowerLayerDown // down, due to lower-layer interfaces OperStateTesting // operationally down, in some test mode OperStateDormant // down, waiting for some external event OperStateUp // interface is in a state to send and receive packets )
Constants that represent operational state of an interface
Adapted from https://elixir.bootlin.com/linux/v4.19.2/source/include/uapi/linux/if.h#L166
type RTNextHop ¶
type RTNextHop struct { Length uint16 // length of this hop including nested values Flags uint8 // flags defined in rtnetlink.h line 311 Hops uint8 IfIndex uint32 // the interface index number }
RTNextHop represents the netlink rtnexthop struct (not an attribute)
type RouteAttributes ¶
type RouteMessage ¶
type RouteMessage struct { Family uint8 // Address family (current unix.AF_INET or unix.AF_INET6) DstLength uint8 // Length of destination prefix SrcLength uint8 // Length of source prefix Tos uint8 // TOS filter Table uint8 // Routing table ID Protocol uint8 // Routing protocol Scope uint8 // Distance to the destination Type uint8 // Route type Flags uint32 Attributes RouteAttributes }
func (*RouteMessage) MarshalBinary ¶
func (m *RouteMessage) MarshalBinary() ([]byte, error)
func (*RouteMessage) UnmarshalBinary ¶
func (m *RouteMessage) UnmarshalBinary(b []byte) error
type RouteMetrics ¶
type RouteMetrics struct { AdvMSS uint32 Features uint32 InitCwnd uint32 InitRwnd uint32 MTU uint32 }
RouteMetrics holds some advanced metrics for a route
type RouteService ¶
type RouteService struct {
// contains filtered or unexported fields
}
func (*RouteService) Delete ¶
func (r *RouteService) Delete(req *RouteMessage) error
Delete existing route
func (*RouteService) Get ¶
func (r *RouteService) Get(req *RouteMessage) ([]RouteMessage, error)
Get Route(s)
func (*RouteService) Replace ¶
func (r *RouteService) Replace(req *RouteMessage) error
Replace or add new route