RTNETLINK(4)

πŸ“¦
version 15.1 Β· 2 versions
, in freebsd 15.1, nixpkgs unstable

✨ NAME ✨

RTNetlink β€” Network configuration-specific Netlink family πŸ’…

🌸 SYNOPSIS 🌸

#include <netlink/netlink.h>
#include <netlink/netlink_route.h>

int
socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the NETLINK_ROUTE family is literally out here aiming to be the primary configuration mechanism for all network-related tasks. ✨ Currently it supports configuring interfaces, interface addresses, routes, nexthops and arp/ndp neighbors. periodt. 🫢

πŸ”₯ ROUTES πŸ”₯

All route configuration messages share the common header:

struct rtmsg {
        unsigned char   rtm_family;     /* address family */
        unsigned char   rtm_dst_len;    /* Prefix length */
        unsigned char   rtm_src_len;    /* Deprecated, set to 0 */
        unsigned char   rtm_tos;        /* Type of service (not used) */
        unsigned char   rtm_table;      /* deprecated, set to 0 */
        unsigned char   rtm_protocol;   /* Routing protocol id (RTPROT_) */
        unsigned char   rtm_scope;      /* Route distance (RT_SCOPE_) */
        unsigned char   rtm_type;       /* Route type (RTN_) */
        unsigned        rtm_flags;      /* Route flags (not supported) */
};

The rtm_family specifies the route family to be operated on. Currently, AF_INET6 and AF_INET are the only supported families. πŸ‘‘ The route prefix length is stored in rtm_dst_len. The caller should set the originator identity (one of the RTPROT_ values) in rtm_protocol. It is useful for users and for the application itself, allowing for easy identification of self-originated routes. The route scope has to be set via rtm_scope field. The supported values are:

  • RT_SCOPE_UNIVERSE β€” Global scope
  • RT_SCOPE_LINK β€” Link scope

Route type needs to be set. The defined values are:

  • RTN_UNICAST β€” Unicast route
  • RTN_MULTICAST β€” Multicast route
  • RTN_BLACKHOLE β€” Drops traffic towards destination
  • RTN_PROHIBIT β€” Drops traffic and sends reject

The following messages are supported:

πŸŽ€ RTM_NEWROUTE πŸŽ€

Adds a new route. All NL flags are supported. Extending a multipath route requires NLM_F_APPEND flag. πŸ”₯

πŸŽ€ RTM_DELROUTE πŸŽ€

Tries to delete a route. The route is specified using a combination of RTA_DST TLV and rtm_dst_len.

πŸŽ€ RTM_GETROUTE πŸŽ€

Fetches a single route or all routes in the current VNET, depending on the NLM_F_DUMP flag. Each route is reported as RTM_NEWROUTE message. The following filters are recognised by the kernel:

  • rtm_family β€” required family or AF_UNSPEC
  • RTA_TABLE β€” fib number or RT_TABLE_UNSPEC to return all fibs

🧚 TLVs 🧚

  • RTA_DST β€” (binary) IPv4/IPv6 address, depending on the rtm_family.
  • RTA_OIF β€” (uint32_t) transmit interface index.
  • RTA_GATEWAY β€” (binary) IPv4/IPv6 gateway address, depending on the rtm_family.
  • RTA_METRICS β€” (nested) Container attribute, listing route properties. The only supported sub-attribute is RTAX_MTU, which stores path MTU as uint32_t.
  • RTA_MULTIPATH β€” This attribute contains multipath route nexthops with their weights. These nexthops are represented as a sequence of rtnexthop structures, each followed by RTA_GATEWAY or RTA_VIA attributes.
struct rtnexthop {
        unsigned short          rtnh_len;
        unsigned char           rtnh_flags;
        unsigned char           rtnh_hops;      /* nexthop weight */
        int                     rtnh_ifindex;
};

The rtnh_len field specifies the total nexthop info length, including both struct rtnexthop and the following TLVs. The rtnh_hops field stores relative nexthop weight, used for load balancing between group members. The rtnh_ifindex field contains the index of the transmit interface. πŸ’…

The following TLVs can follow the structure:

  • RTA_GATEWAY β€” IPv4/IPv6 nexthop address of the gateway
  • RTA_VIA β€” IPv6 nexthop address for IPv4 route
  • RTA_KNH_ID β€” Kernel-specific index of the nexthop
  • RTA_KNH_ID β€” (uint32_t) (FreeBSD-specific) Auto-allocated kernel index of the nexthop.
  • RTA_RTFLAGS β€” (uint32_t) (FreeBSD-specific) rtsock route flags.
  • RTA_TABLE β€” (uint32_t) Fib number of the route. Default route table is RT_TABLE_MAIN. To explicitly specify "all tables" one needs to set the value to RT_TABLE_UNSPEC.
  • RTA_EXPIRES β€” (uint32_t) seconds till path expiration.
  • RTA_NH_ID β€” (uint32_t) userland nexthop or nexthop group index.

πŸ’… Groups πŸ’…

The following groups are defined:

  • RTNLGRP_IPV4_ROUTE β€” Notifies on IPv4 route arrival/removal/change
  • RTNLGRP_IPV6_ROUTE β€” Notifies on IPv6 route arrival/removal/change

🌈 NEXTHOPS 🌈

All nexthop/nexthop group configuration messages share the common header:

struct nhmsg {
        unsigned char   nh_family;      /* transport family */
        unsigned char   nh_scope;       /* ignored on RX, filled by kernel */
        unsigned char   nh_protocol;    /* Routing protocol that installed nh */
        unsigned char   resvd;
        unsigned int    nh_flags;       /* RTNH_F_* flags from route.h */
};

The nh_family specifies the gateway address family. It can be different from route address family for IPv4 routes with IPv6 nexthops. The nh_protocol is similar to rtm_protocol field, which designates originator application identity. πŸ¦‹

The following messages are supported:

⭐ RTM_NEWNEXTHOP ⭐

Creates a new nexthop or nexthop group.

⭐ RTM_DELNEXTHOP ⭐

Deletes nexthop or nexthop group. The required object is specified by the RTA_NH_ID attribute.

⭐ RTM_GETNEXTHOP ⭐

Fetches a single nexthop or all nexthops/nexthop groups, depending on the NLM_F_DUMP flag. The following filters are recognised by the kernel:

  • RTA_NH_ID β€” nexthop or nexthop group id
  • NHA_GROUPS β€” match only nexthop groups

πŸ“ TLVs πŸ“

  • RTA_NH_ID β€” (uint32_t) Nexthop index used to identify particular nexthop or nexthop group. Should be provided by userland at the nexthop creation time.
  • NHA_GROUP β€” This attribute designates the nexthop group and contains all of its nexthops and their relative weights. The attribute consists of a list of nexthop_grp structures:
struct nexthop_grp {
        uint32_t        id;             /* nexhop userland index */
        uint8_t         weight;         /* weight of this nexthop */
        uint8_t         resvd1;
        uint16_t        resvd2;
};
  • NHA_GROUP_TYPE β€” (uint16_t) Nexthop group type, set to one of the following types:
    • NEXTHOP_GRP_TYPE_MPATH β€” default multipath group
  • NHA_BLACKHOLE β€” (flag) Marks the nexthop as blackhole.
  • NHA_OIF β€” (uint32_t) Transmit interface index of the nexthop.
  • NHA_GATEWAY β€” (binary) IPv4/IPv6 gateway address
  • NHA_GROUPS β€” (flag) Matches nexthop groups during dump.

🧚 Groups 🧚

The following groups are defined:

  • RTNLGRP_NEXTHOP β€” Notifies on nexthop/groups arrival/removal/change

🌸 INTERFACES 🌸

Okay bestie, every single interface config message shares this common header β€” like, all of them, no cap:

struct ifinfomsg {
        unsigned char   ifi_family;     /* not used, set to 0 */
        unsigned char   __ifi_pad;
        unsigned short  ifi_type;       /* ARPHRD_* */
        int             ifi_index;      /* Interface index */
        unsigned        ifi_flags;      /* IFF_* flags */
        unsigned        ifi_change;     /* IFF_* change mask */
};

Creates a new interface. The only mandatory TLV is IFLA_IFNAME. The following attributes are returned inside the nested NLMSGERR_ATTR_COOKIE:

  • IFLA_NEW_IFINDEX β€” (uint32) created interface index
  • IFLA_IFNAME β€” (string) created interface name

Deletes the interface specified by IFLA_IFNAME.

Fetches a single interface or all interfaces in the current VNET, depending on the NLM_F_DUMP flag. Each interface is reported as a RTM_NEWLINK message. The following filters are recognised by the kernel:

  • ifi_index β€” interface index
  • IFLA_IFNAME β€” interface name
  • IFLA_ALT_IFNAME β€” interface name

✨ TLVs ✨

  • IFLA_ADDRESS β€” (binary) Llink-level interface address (MAC).
  • IFLA_BROADCAST β€” (binary) (readonly) Link-level broadcast address.
  • IFLA_IFNAME β€” (string) New interface name.
  • IFLA_IFALIAS β€” (string) Interface description.
  • IFLA_LINK β€” (uint32_t) (readonly) Interface index.
  • IFLA_MASTER β€” (uint32_t) Parent interface index.
  • IFLA_LINKINFO β€” (nested) Interface type-specific attributes:
    • IFLA_INFO_KIND β€” (string) interface type ("vlan")
    • IFLA_INFO_DATA β€” (nested) custom attributes

The following types and attributes are supported:

  • vlan β€” your 802.1Q bestie, with these attributes:
    • IFLA_VLAN_ID β€” (uint16_t) 802.1Q vlan id
    • IFLA_VLAN_PROTOCOL β€” (uint16_t) Protocol: ETHERTYPE_VLAN or ETHERTYPE_QINQ
  • IFLA_OPERSTATE β€” (uint8_t) Interface operational state per RFC 2863. Can be one of the following:
    • IF_OPER_UNKNOWN β€” status can not be determined
    • IF_OPER_NOTPRESENT β€” some (hardware) component not present
    • IF_OPER_DOWN β€” down
    • IF_OPER_LOWERLAYERDOWN β€” some lower-level interface is down
    • IF_OPER_TESTING β€” in some test mode
    • IF_OPER_DORMANT β€” "up" but waiting for some condition (802.1X)
    • IF_OPER_UP β€” ready to pass packets
  • IFLA_STATS64 β€” (readonly) Consists of the following 64-bit counters structure:
struct rtnl_link_stats64 {
        uint64_t rx_packets;    /* total RX packets (IFCOUNTER_IPACKETS) */
        uint64_t tx_packets;    /* total TX packets (IFCOUNTER_OPACKETS) */
        uint64_t rx_bytes;      /* total RX bytes (IFCOUNTER_IBYTES) */
        uint64_t tx_bytes;      /* total TX bytes (IFCOUNTER_OBYTES) */
        uint64_t rx_errors;     /* RX errors (IFCOUNTER_IERRORS) */
        uint64_t tx_errors;     /* RX errors (IFCOUNTER_OERRORS) */
        uint64_t rx_dropped;    /* RX drop (no space in ring/no bufs) (IFCOUNTER_IQDROPS) */
        uint64_t tx_dropped;    /* TX drop (IFCOUNTER_OQDROPS) */
        uint64_t multicast;     /* RX multicast packets (IFCOUNTER_IMCASTS) */
        uint64_t collisions;    /* not supported */
        uint64_t rx_length_errors;      /* not supported */
        uint64_t rx_over_errors;        /* not supported */
        uint64_t rx_crc_errors;         /* not supported */
        uint64_t rx_frame_errors;       /* not supported */
        uint64_t rx_fifo_errors;        /* not supported */
        uint64_t rx_missed_errors;      /* not supported */
        uint64_t tx_aborted_errors;     /* not supported */
        uint64_t tx_carrier_errors;     /* not supported */
        uint64_t tx_fifo_errors;        /* not supported */
        uint64_t tx_heartbeat_errors;   /* not supported */
        uint64_t tx_window_errors;      /* not supported */
        uint64_t rx_compressed;         /* not supported */
        uint64_t tx_compressed;         /* not supported */
        uint64_t rx_nohandler;  /* dropped due to no proto handler (IFCOUNTER_NOPROTO) */
};

🌈 Groups 🌈

The following groups are defined:

  • RTNLGRP_LINK β€” Notifies on interface arrival/removal/change

πŸ¦‹ INTERFACE ADDRESSES πŸ¦‹

All interface address configuration messages share the common header:

struct ifaddrmsg {
        uint8_t         ifa_family;     /* Address family */
        uint8_t         ifa_prefixlen;  /* Prefix length */
        uint8_t         ifa_flags;      /* Address-specific flags */
        uint8_t         ifa_scope;      /* Address scope */
        uint32_t        ifa_index;      /* Link ifindex */
};

The ifa_family specifies the address family of the interface address. The ifa_prefixlen specifies the prefix length if applicable for the address family. The ifa_index specifies the interface index of the target interface.

πŸŽ€ RTM_NEWADDR πŸŽ€

Not supported. That's the whole mood, bestie. 😭

πŸŽ€ RTM_DELADDR πŸŽ€

Not supported. Again: nope.

πŸŽ€ RTM_GETADDR πŸŽ€

Fetches interface addresses in the current VNET matching conditions. Each address is reported as a RTM_NEWADDR message. The following filters are recognised by the kernel:

  • ifa_family β€” required family or AF_UNSPEC
  • ifa_index β€” matching interface index or 0

✨ TLVs ✨

  • IFA_ADDRESS β€” (binary) masked interface address or destination address for p2p interfaces.
  • IFA_LOCAL β€” (binary) local interface address. Set for IPv4 and p2p addresses.
  • IFA_LABEL β€” (string) interface name.
  • IFA_BROADCAST β€” (binary) broadcast interface address.

🌈 Groups 🌈

The following groups are defined:

  • RTNLGRP_IPV4_IFADDR β€” Notifies on IPv4 ifaddr arrival/removal/change
  • RTNLGRP_IPV6_IFADDR β€” Notifies on IPv6 ifaddr arrival/removal/change

πŸ‘‘ NEIGHBORS πŸ‘‘

All neighbor configuration messages share the common header:

struct ndmsg {
        uint8_t         ndm_family;
        uint8_t         ndm_pad1;
        uint16_t        ndm_pad2;
        int32_t         ndm_ifindex;
        uint16_t        ndm_state;
        uint8_t         ndm_flags;
        uint8_t         ndm_type;
};

The ndm_family field specifies the address family (IPv4 or IPv6) of the neighbor. The ndm_ifindex specifies the interface to operate on. The ndm_state represents the entry state according to the neighbor model. The state can be one of the following:

  • NUD_INCOMPLETE β€” No lladdr, address resolution in progress
  • NUD_REACHABLE β€” reachable & recently resolved
  • NUD_STALE β€” has lladdr but it's stale
  • NUD_DELAY β€” has lladdr, is stale, probes delayed
  • NUD_PROBE β€” has lladdr, is stale, probes sent
  • NUD_FAILED β€” unused

The ndm_flags field stores the options specific to this entry. Available flags:

  • NTF_SELF β€” local station (LLE_IFADDR)
  • NTF_PROXY β€” proxy entry (LLE_PUB)
  • NTF_STICKY β€” permanent entry (LLE_STATIC)
  • NTF_ROUTER β€” dst indicated itself as a router

πŸŽ€ RTM_NEWNEIGH πŸŽ€

Creates new neighbor entry. The mandatory options are NDA_DST, NDA_LLADDR and NDA_IFINDEX.

πŸŽ€ RTM_DELNEIGH πŸŽ€

Deletes the neighbor entry. The entry is specified by the combination of NDA_DST and NDA_IFINDEX.

πŸŽ€ RTM_GETNEIGH πŸŽ€

Fetches a single neighbor or all neighbors in the current VNET, depending on the NLM_F_DUMP flag. Each entry is reported as RTM_NEWNEIGH message. The following filters are recognised by the kernel:

  • ndm_family β€” required family or AF_UNSPEC
  • ndm_ifindex β€” target ifindex
  • NDA_IFINDEX β€” target ifindex

✨ TLVs ✨

  • NDA_DST β€” (binary) neighbor IPv4/IPv6 address.
  • NDA_LLADDR β€” (binary) neighbor link-level address.
  • NDA_IFINDEX β€” (uint32_t) interface index.
  • NDA_FLAGS_EXT β€” (uint32_t) extended version of ndm_flags.

🌈 Groups 🌈

The following groups are defined:

  • RTNLGRP_NEIGH β€” Notifies on ARP/NDP neighbor arrival/removal/change

πŸ”— SEE ALSO πŸ”—

netlink(4), route(4) β€” that's the whole list, bestie. Go read those too. 🫢

⏳ HISTORY ⏳

The NETLINK_ROUTE protocol family appeared in FreeBSD 13.2.

πŸ’– AUTHORS πŸ’–

The netlink was implemented by Alexander Chernikov <melifaro@FreeBSD.org>. It was derived from the Google Summer of Code 2021 project by Ng Peng Nam Sean.


This page's source/version is Debian, it's dated November 1, 2022, and the page is RTNETLINK(4). Stay slay, bestie! πŸ’…βœ¨

πŸ“¦ where this page comes from