netlink

package module
v0.0.0-...-00d1c24 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2018 License: MIT Imports: 13 Imported by: 0

README

Package netlink provides low-level access to Linux netlink sockets. MIT Licensed.

For more information about how netlink works, check out my blog series on Linux, Netlink, and Go.

If you're looking for package genetlink, it's been moved to its own repository at github.com/mdlayher/genetlink.

Why?

A number of netlink packages are already available for Go, but I wasn't able to find one that aligned with what I wanted in a netlink package:

  • Simple, idiomatic API
  • Well tested
  • Well documented
  • Makes use of Go best practices
  • Doesn't need root to work

My goal for this package is to use it as a building block for the creation of other netlink family packages.

Documentation

Overview

Package netlink provides low-level access to Linux netlink sockets.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func MarshalAttributes

func MarshalAttributes(attrs []Attribute) ([]byte, error)

MarshalAttributes packs a slice of Attributes into a single byte slice. In most cases, the Length field of each Attribute should be set to 0, so it can be calculated and populated automatically for each Attribute.

func Validate

func Validate(request Message, replies []Message) error

Validate validates one or more reply Messages against a request Message, ensuring that they contain matching sequence numbers and PIDs.

Types

type Attribute

type Attribute struct {
	// Length of an Attribute, including this field and Type.
	Length uint16

	// The type of this Attribute, typically matched to a constant.
	Type uint16

	// An arbitrary payload which is specified by Type.
	Data []byte

	// Whether the attribute's data contains nested attributes.  Note that not
	// all netlink families set this value.  The programmer should consult
	// documentation and inspect an attribute's data to determine if nested
	// attributes are present.
	Nested bool

	// Whether the attribute's data is in network (true) or native (false) byte order.
	NetByteOrder bool
}

An Attribute is a netlink attribute. Attributes are packed and unpacked to and from the Data field of Message for some netlink families.

func UnmarshalAttributes

func UnmarshalAttributes(b []byte) ([]Attribute, error)

UnmarshalAttributes unpacks a slice of Attributes from a single byte slice.

func (Attribute) MarshalBinary

func (a Attribute) MarshalBinary() ([]byte, error)

MarshalBinary marshals an Attribute into a byte slice.

func (*Attribute) UnmarshalBinary

func (a *Attribute) UnmarshalBinary(b []byte) error

UnmarshalBinary unmarshals the contents of a byte slice into an Attribute.

type Config

type Config struct {
	// Groups is a bitmask which specifies multicast groups. If set to 0,
	// no multicast group subscriptions will be made.
	Groups uint32

	// Experimental: do not lock the internal system call handling goroutine
	// to its OS thread.  This may result in a speed-up of system call handling,
	// but may cause unexpected behavior when sending and receiving a large number
	// of messages.
	//
	// This should almost certainly be set to false, but if you come up with a
	// valid reason for using this, please file an issue at
	// https://github.com/mdlayher/netlink to discuss your thoughts.
	NoLockThread bool
}

Config contains options for a Conn.

type Conn

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

A Conn is a connection to netlink. A Conn can be used to send and receives messages to and from netlink.

A Conn is safe for concurrent use, but to avoid contention in high-throughput applications, the caller should almost certainly create a pool of Conns and distribute them among workers.

Example (Execute)

This example demonstrates using a netlink.Conn to execute requests against netlink.

package main

import (
	"log"

	"github.com/mdlayher/netlink"
)

func main() {
	// Speak to generic netlink using netlink
	const familyGeneric = 16

	c, err := netlink.Dial(familyGeneric, nil)
	if err != nil {
		log.Fatalf("failed to dial netlink: %v", err)
	}
	defer c.Close()

	// Ask netlink to send us an acknowledgement, which will contain
	// a copy of the header we sent to it
	req := netlink.Message{
		Header: netlink.Header{
			// Package netlink will automatically set header fields
			// which are set to zero
			Flags: netlink.HeaderFlagsRequest | netlink.HeaderFlagsAcknowledge,
		},
	}

	// Perform a request, receive replies, and validate the replies
	msgs, err := c.Execute(req)
	if err != nil {
		log.Fatalf("failed to execute request: %v", err)
	}

	if c := len(msgs); c != 1 {
		log.Fatalf("expected 1 message, but got: %d", c)
	}

	// Decode the copied request header, starting after 4 bytes
	// indicating "success"
	var res netlink.Message
	if err := (&res).UnmarshalBinary(msgs[0].Data[4:]); err != nil {
		log.Fatalf("failed to unmarshal response: %v", err)
	}

	log.Printf("res: %+v", res)
}
Output:

Example (ListenMulticast)

This example demonstrates using a netlink.Conn to listen for multicast group messages generated by the addition and deletion of network interfaces.

package main

import (
	"log"

	"github.com/mdlayher/netlink"
)

func main() {
	const (
		// Speak to route netlink using netlink
		familyRoute = 0

		// Listen for events triggered by addition or deletion of
		// network interfaces
		rtmGroupLink = 0x1
	)

	c, err := netlink.Dial(familyRoute, &netlink.Config{
		// Groups is a bitmask; more than one group can be specified
		// by OR'ing multiple group values together
		Groups: rtmGroupLink,
	})
	if err != nil {
		log.Fatalf("failed to dial netlink: %v", err)
	}
	defer c.Close()

	for {
		// Listen for netlink messages triggered by multicast groups
		msgs, err := c.Receive()
		if err != nil {
			log.Fatalf("failed to receive messages: %v", err)
		}

		log.Printf("msgs: %+v", msgs)
	}
}
Output:

func Dial

func Dial(family int, config *Config) (*Conn, error)

Dial dials a connection to netlink, using the specified netlink family. Config specifies optional configuration for Conn. If config is nil, a default configuration will be used.

func NewConn

func NewConn(c Socket, pid uint32) *Conn

NewConn creates a Conn using the specified Socket and PID for netlink communications.

NewConn is primarily useful for tests. Most applications should use Dial instead.

func (*Conn) Close

func (c *Conn) Close() error

Close closes the connection.

func (*Conn) Execute

func (c *Conn) Execute(m Message) ([]Message, error)

Execute sends a single Message to netlink using Conn.Send, receives one or more replies using Conn.Receive, and then checks the validity of the replies against the request using Validate.

See the documentation of Conn.Send, Conn.Receive, and Validate for details about each function.

func (*Conn) JoinGroup

func (c *Conn) JoinGroup(group uint32) error

JoinGroup joins a netlink multicast group by its ID.

func (*Conn) LeaveGroup

func (c *Conn) LeaveGroup(group uint32) error

LeaveGroup leaves a netlink multicast group by its ID.

func (*Conn) ReadWriteCloser

func (c *Conn) ReadWriteCloser() (io.ReadWriteCloser, error)

ReadWriteCloser returns a raw io.ReadWriteCloser backed by the connection of the Conn.

ReadWriteCloser is intended for advanced use cases, such as those that do not involve standard netlink message passing.

Once invoked, it is the caller's responsibility to ensure that operations performed using Conn and the raw io.ReadWriteCloser do not conflict with each other. In almost all scenarios, only one of the two should be used.

func (*Conn) Receive

func (c *Conn) Receive() ([]Message, error)

Receive receives one or more messages from netlink. Multi-part messages are handled transparently and returned as a single slice of Messages, with the final empty "multi-part done" message removed.

If any of the messages indicate a netlink error, that error will be returned.

func (*Conn) Send

func (c *Conn) Send(m Message) (Message, error)

Send sends a single Message to netlink. In most cases, m.Header's Length, Sequence, and PID fields should be set to 0, so they can be populated automatically before the Message is sent. On success, Send returns a copy of the Message with all parameters populated, for later validation.

If m.Header.Length is 0, it will be automatically populated using the correct length for the Message, including its payload.

If m.Header.Sequence is 0, it will be automatically populated using the next sequence number for this connection.

If m.Header.PID is 0, it will be automatically populated using a PID assigned by netlink.

func (*Conn) SetBPF

func (c *Conn) SetBPF(filter []bpf.RawInstruction) error

SetBPF attaches an assembled BPF program to a Conn.

type Header struct {
	// Length of a Message, including this Header.
	Length uint32

	// Contents of a Message.
	Type HeaderType

	// Flags which may be used to modify a request or response.
	Flags HeaderFlags

	// The sequence number of a Message.
	Sequence uint32

	// The process ID of the sending process.
	PID uint32
}

A Header is a netlink header. A Header is sent and received with each Message to indicate metadata regarding a Message.

type HeaderFlags

type HeaderFlags uint16

HeaderFlags specify flags which may be present in a Header.

const (

	// HeaderFlagsRequest indicates a request to netlink.
	HeaderFlagsRequest HeaderFlags = 1

	// HeaderFlagsMulti indicates a multi-part message, terminated
	// by HeaderTypeDone on the last message.
	HeaderFlagsMulti HeaderFlags = 2

	// HeaderFlagsAcknowledge requests that netlink reply with
	// an acknowledgement using HeaderTypeError and, if needed,
	// an error code.
	HeaderFlagsAcknowledge HeaderFlags = 4

	// HeaderFlagsEcho requests that netlink echo this request
	// back to the sender.
	HeaderFlagsEcho HeaderFlags = 8

	// HeaderFlagsDumpInterrupted indicates that a dump was
	// inconsistent due to a sequence change.
	HeaderFlagsDumpInterrupted HeaderFlags = 16

	// HeaderFlagsDumpFiltered indicates that a dump was filtered
	// as requested.
	HeaderFlagsDumpFiltered HeaderFlags = 32

	// HeaderFlagsRoot requests that netlink return a complete table instead
	// of a single entry.
	HeaderFlagsRoot HeaderFlags = 0x100

	// HeaderFlagsMatch requests that netlink return a list of all matching
	// entries.
	HeaderFlagsMatch HeaderFlags = 0x200

	// HeaderFlagsAtomic requests that netlink send an atomic snapshot of
	// its entries.  Requires CAP_NET_ADMIN or an effective UID of 0.
	HeaderFlagsAtomic HeaderFlags = 0x400

	// HeaderFlagsDump requests that netlink return a complete list of
	// all entries.
	HeaderFlagsDump HeaderFlags = HeaderFlagsRoot | HeaderFlagsMatch

	// HeaderFlagsReplace indicates request replaces an existing matching object.
	HeaderFlagsReplace HeaderFlags = 0x100

	// HeaderFlagsExcl  indicates request does not replace the object if it already exists.
	HeaderFlagsExcl HeaderFlags = 0x200

	// HeaderFlagsCreate indicates request creates an object if it doesn't already exist.
	HeaderFlagsCreate HeaderFlags = 0x400

	// HeaderFlagsAppend indicates request adds to the end of the object list.
	HeaderFlagsAppend HeaderFlags = 0x800
)

func (HeaderFlags) String

func (f HeaderFlags) String() string

String returns the string representation of a HeaderFlags.

type HeaderType

type HeaderType uint16

HeaderType specifies the type of a Header.

const (
	// HeaderTypeNoop indicates that no action was taken.
	HeaderTypeNoop HeaderType = 0x1

	// HeaderTypeError indicates an error code is present, which is also
	// used to indicate success when the code is 0.
	HeaderTypeError HeaderType = 0x2

	// HeaderTypeDone indicates the end of a multi-part message.
	HeaderTypeDone HeaderType = 0x3

	// HeaderTypeOverrun indicates that data was lost from this message.
	HeaderTypeOverrun HeaderType = 0x4
)

func (HeaderType) String

func (t HeaderType) String() string

String returns the string representation of a HeaderType.

type Message

type Message struct {
	Header Header
	Data   []byte
}

A Message is a netlink message. It contains a Header and an arbitrary byte payload, which may be decoded using information from the Header.

Data is encoded in the native endianness of the host system. For easier of encoding and decoding of integers, use package nlenc.

func (Message) MarshalBinary

func (m Message) MarshalBinary() ([]byte, error)

MarshalBinary marshals a Message into a byte slice.

func (*Message) UnmarshalBinary

func (m *Message) UnmarshalBinary(b []byte) error

UnmarshalBinary unmarshals the contents of a byte slice into a Message.

type Socket

type Socket interface {
	Close() error
	Send(m Message) error
	Receive() ([]Message, error)
}

A Socket is an operating-system specific implementation of netlink sockets used by Conn.

Directories

Path Synopsis
Package nlenc implements encoding and decoding functions for netlink messages and attributes.
Package nlenc implements encoding and decoding functions for netlink messages and attributes.
Package nltest provides utilities for netlink testing.
Package nltest provides utilities for netlink testing.

Jump to

Keyboard shortcuts

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