     [file version.texi not included]

Copyright © 2020 Julien Lepiller

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

guile-netlink
*************

This document describes guile-netlink version VERSION, a guile implementation of the netlink protocol.

Introduction
************

Netlink is an inter-process communication protocol that can be used for communication between processes, or with the kernel.  It is implemented by Linux.

Many protocols exist on top of Netlink.  The most famous are used to configure network-related functions in the kernel, such as firewall, route table or IP addresses of interfaces.

This library implements the low-level bits of the code by providing data structures that are close to their C counterpart, and basic procedures to initiate communication.

API Reference
*************

Common API
==========

Guile-netlink implements a common API for expressing other protocols.  This section describes how to use this API to augment guile-netlink with additional protocols.

Data Types
----------

Guile-netlink defines data types that are used in the various Netlink protocols. We need to be able to serialize and deserialize data that guile-netlink understands, but we also want to let users of guile-netlink extend this process easily.  This need has lead to the creating of the following data structure, defined in (netlink data).

 -- Datatype: nl-data

     data
          The data that is held by this record.

     size-proc
          A procedure that takes a data (of the same type as the data recorded in the data field) and returns the size of its serialization.

     serialization-proc
          A procedure that takes a data (of the same type as the data recorded in the data field), the position at which to start serializing, and a bytevector in which to serialize.  This procedure should modify the bytevector and its return value is ignored.

The module also defines the following function, that takes a nl-data structure and provides its serialization in a bytevector:

 -- Scheme Procedure: serialize DATA POS BV
     Takes a nl-data structure as DATA, a position POS in the bytevector BV, and returns an unspecified value.

     This function updates the bytevector and adds the serialization of DATA into BV at POS.

By providing a nl-data structure, we defer the knowledge of how to serialize the data to the structure itself, instead of the serialize function.  This allows for more flexibility and extensibility, as the user of the procedure can pass any kind of data, even if it is not yet supported by guile-netlink.

Similarly, we need to be able to deserialize netlink answers into a data structure.  To do so, we also defer the knowledge of the datastructure to deserialize to, to a decoder structure that is passed to the deserialization procedure.  (netlink data) also defines the following procedures to deserialize data:

 -- Scheme Procedure: deserialize TYPE DECODER BV POS
     Takes a bytevector BV and starts deserializing the data starting at position POS.  To do so, it uses the TYPE variable as the lookup key in the DECODER.  TYPE is a symbol that represents the type of data to deserialize to.

     The decoder is a structure that associates each known type to its deserializer (a function that takes a decoder, a bytevector and a position and returns some data) and an alist that associates a type (an integer, as returned by the protocol in use) to the proper decoder of that type.

 -- Scheme Procedure: get-current-deserialize DECODER CURRENT-TYPE
     Takes a decoder and a type, and returns the deserialization procedure associated with the type (a symbol) in DECODER.

 -- Scheme Procedure: get-next-deserialize DECODER CURRENT-TYPE
     TARGET-TYPE
     Takes a decoder, a type (a symbol that represents the type of data being deserialized) and another type (an integer as returned by the protocol), and returns the deserialization procedure needed to continue decoding the data associated with the currently being deserialized data.

     For example, when decoding an answer in the netlink protocol, we first deserialize the header into a message structure.  That header contains a type field that contains an integer constant representing the type of data of the body. Similarly, when deserializing a routing attribute in the rtnetlink protocol, we first find a header of the attribute that defines an integer constant corresponding to the type of attribute in the body.

     By knowing the context in which the type is declared, this procedure can return the correct deserializing procedure.  For instance, when deserializing a message, type 16 means RTM_NEWLINK in the rtnetlink protocol, whereas it means IFLA_OPERSTATE when deserializing a route-attribute.

guile-netlink provides the following default decoder for the rtnetlink protocol in (netlink deserialize):

 -- Scheme Variable: %default-route-decoder
     Contains the default decoder for the NETLINK_ROUTE protocol.

For convenience, guile-netlink defines the following structures that can be used to create a custom decoder.

 -- Scheme Variable: %default-message-decoder
     Contains the default association list for the common message types of netlink, associating each of them to a deserialization procedure.

 -- Scheme Procedure: default-route-attr-decoder DESERIALIZE-ADDR
     Creates the default association list for a route protocol, given the specified address deserializer.  This is useful because the IFA_ADDRESS, IFA_BROADCAST, etc, contain a different type of address depending on the message type or its header.  This is defined an (netlink route attrs) and used by the following variables:

 -- Scheme Variable: %default-route-link-attr-decoder
     Contains the default association list for the known types of routing attributes for link messages.  This list is defined in (netlink route attrs).

Constants
---------

Guile-netlink defines constants used by the Netlink protocols in the (netlink constant) module.  The constants are the ones present in the kernel and are too numerous to list here.  Please see the source for the complete list.

The module also defines the following macro:

 -- Scheme Macro: define-enum INTEGER->SYMBOL NAME-SPEC ...
     This macros defines an enumeration.  INTEGER->SYMBOL is the name of a procedure that is publicly defined, that takes an integer and returns the associated symbol in the enumeration.

     The macro also publicly defines variables whose names are in NAME-SPEC to an integer.

     A NAME-SPEC is either a single name, and the associated value is 0 for the first NAME-SPEC, or one more than the previous NAME-SPEC. It can also be a pair of a name and an integer, in which case the associated value is that integer.  For instance:

          (define-enum get-foo FOO0 FOO1 (FOO10 10) FOO11 FOO12)
          (get-foo 9) -> #<unspecified>
          (get-foo 0) -> FOO0
          FOO11 -> 11

Netlink Connections
-------------------

The (netlink connection) module defines the following procedures, used to connect and communicate with another process or the kernel using a netlink socket.

 -- Scheme Procedure: get-addr FAMILY PID GROUPS
     Return a bytevector that represents a netlink address.  FAMILY should be AF_NETLINK, PID is the PID of the process with which to communicate or 0 for the kernel. GROUPS is an integer representing the set of broadcast groups to which the connection subscribes.

 -- Scheme Procedure: connect PROTO ADDR
     Creates a netlink socket for PROTO and binds it to ADDR.

     PROTO is the integer representing the protocol.  For instance, rtnetlink can be selected by usin NETLINK_ROUTE (defined in (netlink constant)).

     ADDR is a bytevector, as returned by get-addr.

 -- Scheme Procedure: connect-route [#:groups 0]
     This procedure is a wrapper for connect that creates a socket for the rtnetlink protocol, binds it to the kernel and returns it.  By passing the optional GROUPS keyword, you can select broadcast groups to subscribe to.

 -- Scheme Procedure: close-socket SOCKET
     Closes a netlink socket.  The socket cannot be used afterwards.

 -- Scheme Procedure: send-msg MSG SOCK [#:ADDR]
     Send MSG (it must be of type message, see Netlink Headers) to ADDR using SOCK.  If not passed, ADDR is the address of the kernel.

 -- Scheme Procedure: receive-msg SOCK [#:ADDR]
     Receives a message from SOCK from ADDR.  This procedure is blocking. If not passed, ADDR defaults to the address of the kernel.  This procedure returns the message as a bytevector, that you can deserialize with deserialize (see Data Types)

 -- Scheme Procedure: receive-and-decode-msg SOCK DECODER
     [#:ADDR]
     Receives one or more messages from SOCK from ADDR.  this procedure is blocking.  If not passed, ADDR defaults to the address of the kernel. This procedure returns a list of messages that were decoded using DECODER.

     When the answer has the NLM_F_MULTI flag, this procedure decodes the next message, until it receives a NLMSG_DONE message.  It returns the list of every netlink messages it received, including the NLMSG_DONE.

Netlink API
===========

This section introduces the data structures used for all the netlink protocols. First, we introduce the structure of a netlink message, then we present the standard types of netlink messages, that can be used with every protocol.

Netlink Headers
---------------

The (netlink message) module defines the message structure that contains a netlink message.  It is composed of a header and a body, and is the data structure to pass to send-msg (see Netlink Connections).

This module defines the following data structure:

 -- Datatype: message

     type
          The type of data in the body of the message.  For instance, RTM_GETLINK.

     flags
          The set of flags that are set in the header.  For instance, (logior NLM_F_REQUEST NLM_F_DUMP).

     seq
          The sequence number of the message.  If this message is an answer to a request, it must keep the same sequence number.  Otherwise, you must generate a new and unique sequence number, to track the answers.

     pid
          The PID of the receiving process, or 0 for the kernel.

     data
          The actual body, as an nl-data structure.

Standard Message Types
----------------------

The (netlink standard) module defines the set of standard message types and their data type.

 -- Datatype: error-message

     err
          The error code, as a negative number.

     hdr
          The message on which this error applies.

      -- Scheme Variable: no-data
          This variable defines the absence of data.  This is useful when a structure is expecting a body part, but the protocol specifically defines that it should not take any data in some cases.  For instance, a NLMSG_NOOP message takes no data, so the data field of the message will contain this no-data value.

Rtnetlink API
=============

This section describes the support for rtnetlink in guile-netlink.  Rtnetlink is the protocol responsible for everything related to network routing.  It allows you to manage links, addresses, routing tables, neighbor chaces, routing rules, queueing disciplines, traffic classes, traffic filters and more.

Routing Attributes
------------------

The (netlink route attrs) module defines the following data types:

 -- Datatype: route-attr
     This defines a header structure for the attribute, as well as its body.

     type
          This is the type of the attribute, for instance IFLA_ADDRESS.

     data
          This is the body of the attribute, ie. its value.

The module also defines additional data types that are not represented as a record, but by a simple type.  For each of the following types, there is a make-*-route-attr procedure to produce a nl-data value for this type.  There is also deserialize-route-attr-data-* procedure to deserialize a value of this type.

u8
     A one-byte unsigned integer

u16
     A two-bytes unsigned integer

u32
     A four-bytes unsigned integer

s32
     A four-bytes signed integer

string
     A string

ethernet
     An ethernet address.  Its value is a string that represents that address, for instnace "01:23:45:67:89:ab"

ipv4
     An IPv4 address.  Its value is a string that represents that address, for instnace "192.0.2.152"

ipv6
     An IPv6 address.  Its value is a string that represents that address, for instnace "2001:db8::0123:4567:89ab:cdef"

bv
     A bytevector.  This is used by default when the type is not supported.

Link Messages
-------------

The (netlink route link) package defines the following data type:

 -- Datatype: link-message
     This datatype represents a link message with its routing attributes.  This type of message is expected when using the RTM_*LINK message types.

     family
          The network family, defined as AF_UNSPEC in the rtnetlink documentation, although it holds different values in practice.

     type
          The device type.

     index
          The index of the device.  This is used to select a specific device by its index, or 0 to not filter by device index.

     flags
          The device flags.  See man 7 netdevices for a list.

     attrs
          A list of attributes.  This field must contain a list of nl-data structures, not a structure by itself.

Address Messages
----------------

The (netlink route addr) package defines the following data type:

 -- Datatype: addr-message
     This datatype represents an address message with its routing attributes.  This type of message is expected when using the RTM_*ADDR message types.

     family
          The network family, either AF_INET for IPv4 addresses, or AF_INET6 for IPv6 addresses.

     prefix-len
          The prefix length, i.e. the length of the prefix mask, in bits, if defined for the address family.

     flags
          Address flags.  This can be a flag word of IFA_F_SECONDARY for secondary address (old alias interface), IFA_F_PERMANENT for a permanent address set by the user and other undocumented flags.

     scope
          The address scope.

     index
          The index of the device this address is for.

     attrs
          A list of attributes.  This field must contain a list of nl-data structures, not a structure by itself.

IP Library
**********

This library comes with higher-level procedures that let you access and modify the state of network on your computer.

Link
====

The (ip link) module introduces procedures to access and modify the network links on your machine.  They are equivalent to the ip link family of commands, from iproute2.

 -- Scheme Procedure: link-set DEVICE [#:up #f]
     [#:down #f] [#:type #f] [#:arp-on #f]
     [#:arp-off #f] [#:dynamic-on #f] [#:dynamic-off #f]
     [#:multicast-on #f] [#:multicast-off #f]
     [#:allmulticast-on #f] [#:allmulticast-off #f]
     [#:promisc-on #f] [#:promisc-off #f] [#:trailers-on #f]
     [#:trailers-off #f] [#:carrier-on #f] [#:carrier-off #f]
     [#:txqueuelen #f] [#:name #f] [#:address #f]
     [#:broadcast #f] [#:mtu #f] [#:netns #f]
     Modify an existing link and set its flags and attributes to the ones specified by the various keywords.  When a keyword is omited, the corresponding attribute is not changed.

     DEVICE can be a device index (as a number) or a device name (as a string).

     Do not set #:up and #:down at the same time.  Do not set *-on and *-off at the same time.

 -- Scheme Procedure: link-show [#:device #f] [#:group #f]
     [#:up #f] [#:master #f] [#:vrf #f] [#:type #f]
     Print the set of devices on standard output.  Setting any of the keyword to a non-false value will filter the results to only show results that match the corresponding value.  You may set more than one keyword.

 -- Scheme Procedure: link-add NAME TYPE [#:type-args '()]
     Add a new link with given name and type.  Additional arguments can be passed to control the state of the link at creation. TYPE-ARGS is an association list containing additional values for the given type.

     When TYPE is "vlan", TYPE-ARGS can contain a number associated with 'id: the VLAN id to be created.

     When TYPE is "veth", TYPE-ARGS can contain a string associated with 'peer: the name of the peer.

     The following is an example in which we create a new veth (virtual ethernet) pair and give them a name:

          ;; same as "ip l add v0p0 type veth peer v0p1"
          (link-add "v0p0" "veth" #:type-args '((peer . "v0p1")))

 -- Scheme Procedure: link-del DEVICE
     Delete a link.  DEVICE can contain the name of the link, as a string, or its index, as a number.