freebsd-dev/sys/netlink/route/route.h
Alexander V. Chernikov 7e5bf68495 netlink: add netlink support
Netlinks is a communication protocol currently used in Linux kernel to modify,
 read and subscribe for nearly all networking state. Interfaces, addresses, routes,
 firewall, fibs, vnets, etc are controlled via netlink.
It is async, TLV-based protocol, providing 1-1 and 1-many communications.

The current implementation supports the subset of NETLINK_ROUTE
family. To be more specific, the following is supported:
* Dumps:
 - routes
 - nexthops / nexthop groups
 - interfaces
 - interface addresses
 - neighbors (arp/ndp)
* Notifications:
 - interface arrival/departure
 - interface address arrival/departure
 - route addition/deletion
* Modifications:
 - adding/deleting routes
 - adding/deleting nexthops/nexthops groups
 - adding/deleting neghbors
 - adding/deleting interfaces (basic support only)
* Rtsock interaction
 - route events are bridged both ways

The implementation also supports the NETLINK_GENERIC family framework.

Implementation notes:
Netlink is implemented via loadable/unloadable kernel module,
 not touching many kernel parts.
Each netlink socket uses dedicated taskqueue to support async operations
 that can sleep, such as interface creation. All message processing is
 performed within these taskqueues.

Compatibility:
Most of the Netlink data models specified above maps to FreeBSD concepts
 nicely. Unmodified ip(8) binary correctly works with
interfaces, addresses, routes, nexthops and nexthop groups. Some
software such as net/bird require header-only modifications to compile
and work with FreeBSD netlink.

Reviewed by:	imp
Differential Revision: https://reviews.freebsd.org/D36002
MFC after:	2 months
2022-10-01 14:15:35 +00:00

367 lines
13 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Route-related (RTM_<NEW|DEL|GET>ROUTE) message header and attributes.
*/
#ifndef _NETLINK_ROUTE_ROUTE_H_
#define _NETLINK_ROUTE_ROUTE_H_
/* Base header for all of the relevant messages */
struct rtmsg {
unsigned char rtm_family; /* address family */
unsigned char rtm_dst_len; /* Prefix length */
unsigned char rtm_src_len; /* Source prefix length (not used) */
unsigned char rtm_tos; /* Type of service (not used) */
unsigned char rtm_table; /* rtable id */
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 (RTM_F_) */
};
/*
* RFC 3549, 3.1.1, route type (rtm_type field).
*/
enum {
RTN_UNSPEC,
RTN_UNICAST, /* Unicast route */
RTN_LOCAL, /* Accept locally (not supported) */
RTN_BROADCAST, /* Accept locally as broadcast, send as broadcast */
RTN_ANYCAST, /* Accept locally as broadcast, but send as unicast */
RTN_MULTICAST, /* Multicast route */
RTN_BLACKHOLE, /* Drop traffic towards destination */
RTN_UNREACHABLE, /* Destination is unreachable */
RTN_PROHIBIT, /* Administratively prohibited */
RTN_THROW, /* Not in this table (not supported) */
RTN_NAT, /* Translate this address (not supported) */
RTN_XRESOLVE, /* Use external resolver (not supported) */
__RTN_MAX,
};
#define RTN_MAX (__RTN_MAX - 1)
/*
* RFC 3549, 3.1.1, protocol (Identifies what/who added the route).
* Values larger than RTPROT_STATIC(4) are not interpreted by the
* kernel, they are just for user information.
*/
#define RTPROT_UNSPEC 0
#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirect */
#define RTPROT_KERNEL 2 /* Route installed by kernel */
#define RTPROT_BOOT 3 /* Route installed during boot */
#define RTPROT_STATIC 4 /* Route installed by administrator */
#define RTPROT_GATED 8
#define RTPROT_RA 9
#define RTPROT_MRT 1
#define RTPROT_ZEBRA 11
#define RTPROT_BIRD 12
#define RTPROT_DNROUTED 13
#define RTPROT_XORP 14
#define RTPROT_NTK 15
#define RTPROT_DHCP 16
#define RTPROT_MROUTED 17
#define RTPROT_KEEPALIVED 18
#define RTPROT_BABEL 42
#define RTPROT_OPENR 99
#define RTPROT_BGP 186
#define RTPROT_ISIS 187
#define RTPROT_OSPF 188
#define RTPROT_RIP 189
#define RTPROT_EIGRP 192
/*
* RFC 3549 3.1.1 Route scope (valid distance to destination).
*
* The values between RT_SCOPE_UNIVERSE(0) and RT_SCOPE_SITE(200)
* are available to the user.
*/
enum rt_scope_t {
RT_SCOPE_UNIVERSE = 0,
/* User defined values */
RT_SCOPE_SITE = 200,
RT_SCOPE_LINK = 253,
RT_SCOPE_HOST = 254,
RT_SCOPE_NOWHERE = 255
};
/*
* RFC 3549 3.1.1 Route flags (rtm_flags).
* Is a composition of RTNH_F flags (0x1..0x40 range), RTM_F flags (below)
* and per-protocol (IPv4/IPv6) flags.
*/
#define RTM_F_NOTIFY 0x00000100 /* not supported */
#define RTM_F_CLONED 0x00000200 /* not supported */
#define RTM_F_EQUALIZE 0x00000400 /* not supported */
#define RTM_F_PREFIX 0x00000800 /* not supported */
#define RTM_F_LOOKUP_TABLE 0x00001000 /* not supported */
#define RTM_F_FIB_MATCH 0x00002000 /* not supported */
#define RTM_F_OFFLOAD 0x00004000 /* not supported */
#define RTM_F_TRAP 0x00008000 /* not supported */
#define RTM_F_OFFLOAD_FAILED 0x20000000 /* not supported */
/* Compatibility handling helpers */
#ifndef _KERNEL
#define NL_RTM_HDRLEN ((int)sizeof(struct rtmsg))
#define RTM_RTA(_rtm) ((struct rtattr *)((char *)(_rtm) + NL_RTM_HDRLEN))
#define RTM_PAYLOAD(_hdr) NLMSG_PAYLOAD((_hdr), NL_RTM_HDRLEN)
#endif
/*
* Routing table identifiers.
* FreeBSD route table numbering starts from 0, where 0 is a valid default routing table.
* Indicating "all tables" via netlink can be done by not including RTA_TABLE attribute
* and keeping rtm_table=0 (compatibility) or setting RTA_TABLE value to RT_TABLE_UNSPEC.
*/
#define RT_TABLE_MAIN 0 /* RT_DEFAULT_FIB */
#define RT_TABLE_UNSPEC 0xFFFFFFFF /* RT_ALL_FIBS */
enum rtattr_type_t {
NL_RTA_UNSPEC,
NL_RTA_DST = 1, /* binary, IPv4/IPv6 destination */
NL_RTA_SRC = 2, /* binary, preferred source address */
NL_RTA_IIF = 3, /* not supported */
NL_RTA_OIF = 4, /* u32, transmit ifindex */
NL_RTA_GATEWAY = 5, /* binary: IPv4/IPv6 gateway */
NL_RTA_PRIORITY = 6, /* not supported */
NL_RTA_PREFSRC = 7, /* not supported */
NL_RTA_METRICS = 8, /* nested, list of NL_RTAX* attrs */
NL_RTA_MULTIPATH = 9, /* binary, array of struct rtnexthop */
NL_RTA_PROTOINFO = 10, /* not supported / deprecated */
NL_RTA_KNH_ID = 10, /* u32, FreeBSD specific, kernel nexthop index */
NL_RTA_FLOW = 11, /* not supported */
NL_RTA_CACHEINFO = 12, /* not supported */
NL_RTA_SESSION = 13, /* not supported / deprecated */
NL_RTA_MP_ALGO = 14, /* not supported / deprecated */
NL_RTA_RTFLAGS = 14, /* u32, FreeBSD specific, */
NL_RTA_TABLE = 15, /* u32, fibnum */
NL_RTA_MARK = 16, /* not supported */
NL_RTA_MFC_STATS = 17, /* not supported */
NL_RTA_VIA = 18, /* binary, struct rtvia */
NL_RTA_NEWDST = 19, /* not supported */
NL_RTA_PREF = 20, /* not supported */
NL_RTA_ENCAP_TYPE = 21, /* not supported */
NL_RTA_ENCAP = 22, /* not supported */
NL_RTA_EXPIRES = 23, /* u32, seconds till expiration */
NL_RTA_PAD = 24, /* not supported */
NL_RTA_UID = 25, /* not supported */
NL_RTA_TTL_PROPAGATE = 26, /* not supported */
NL_RTA_IP_PROTO = 27, /* not supported */
NL_RTA_SPORT = 28, /* not supported */
NL_RTA_DPORT = 29, /* not supported */
NL_RTA_NH_ID = 30, /* u32, nexthop/nexthop group index */
__RTA_MAX
};
#define NL_RTA_MAX (__RTA_MAX - 1)
/*
* Attributes that can be used as filters:
*
*/
#ifndef _KERNEL
/*
* RTA_* space has clashes with rtsock namespace.
* Use NL_RTA_ prefix in the kernel and map to
* RTA_ for userland.
*/
#define RTA_UNSPEC NL_RTA_UNSPEC
#define RTA_DST NL_RTA_DST
#define RTA_SRC NL_RTA_SRC
#define RTA_IIF NL_RTA_IIF
#define RTA_OIF NL_RTA_OIF
#define RTA_GATEWAY NL_RTA_GATEWAY
#define RTA_PRIORITY NL_RTA_PRIORITY
#define RTA_PREFSRC NL_RTA_PREFSRC
#define RTA_METRICS NL_RTA_METRICS
#define RTA_MULTIPATH NL_RTA_MULTIPATH
#define RTA_PROTOINFO NL_RTA_PROTOINFO
#define RTA_KNH_ID NL_RTA_KNH_ID
#define RTA_FLOW NL_RTA_FLOW
#define RTA_CACHEINFO NL_RTA_CACHEINFO
#define RTA_SESSION NL_RTA_SESSION
#define RTA_MP_ALGO NL_RTA_MP_ALGO
#define RTA_TABLE NL_RTA_TABLE
#define RTA_MARK NL_RTA_MARK
#define RTA_MFC_STATS NL_RTA_MFC_STATS
#define RTA_VIA NL_RTA_VIA
#define RTA_NEWDST NL_RTA_NEWDST
#define RTA_PREF NL_RTA_PREF
#define RTA_ENCAP_TYPE NL_RTA_ENCAP_TYPE
#define RTA_ENCAP NL_RTA_ENCAP
#define RTA_EXPIRES NL_RTA_EXPIRES
#define RTA_PAD NL_RTA_PAD
#define RTA_UID NL_RTA_UID
#define RTA_TTL_PROPAGATE NL_RTA_TTL_PROPAGATE
#define RTA_IP_PROTO NL_RTA_IP_PROTO
#define RTA_SPORT NL_RTA_SPORT
#define RTA_DPORT NL_RTA_DPORT
#define RTA_NH_ID NL_RTA_NH_ID
#define RTA_MAX NL_RTA_MAX
#endif
/* route attribute header */
struct rtattr {
unsigned short rta_len;
unsigned short rta_type;
};
#define NL_RTA_ALIGN_SIZE NL_ITEM_ALIGN_SIZE
#define NL_RTA_ALIGN NL_ITEM_ALIGN
#define NL_RTA_HDRLEN ((int)sizeof(struct rtattr))
#define NL_RTA_DATA_LEN(_rta) ((int)((_rta)->rta_len - NL_RTA_HDRLEN))
#define NL_RTA_DATA(_rta) NL_ITEM_DATA(_rta, NL_RTA_HDRLEN)
#define NL_RTA_DATA_CONST(_rta) NL_ITEM_DATA_CONST(_rta, NL_RTA_HDRLEN)
/* Compatibility attribute handling helpers */
#ifndef _KERNEL
#define RTA_ALIGNTO NL_RTA_ALIGN_SIZE
#define RTA_ALIGN(_len) NL_RTA_ALIGN(_len)
#define _RTA_LEN(_rta) ((int)(_rta)->rta_len)
#define _RTA_ALIGNED_LEN(_rta) RTA_ALIGN(_RTA_LEN(_rta))
#define RTA_OK(_rta, _len) NL_ITEM_OK(_rta, _len, NL_RTA_HDRLEN, _RTA_LEN)
#define RTA_NEXT(_rta, _len) NL_ITEM_ITER(_rta, _len, _RTA_ALIGNED_LEN)
#define RTA_LENGTH(_len) (NL_RTA_HDRLEN + (_len))
#define RTA_SPACE(_len) RTA_ALIGN(RTA_LENGTH(_len))
#define RTA_DATA(_rta) NL_RTA_DATA(_rta)
#define RTA_PAYLOAD(_rta) ((int)(_RTA_LEN(_rta) - NL_RTA_HDRLEN))
#endif
/* RTA attribute headers */
/* RTA_VIA */
struct rtvia {
sa_family_t rtvia_family;
uint8_t rtvia_addr[0];
};
/*
* RTA_METRICS is a nested attribute, consisting of a list of
* TLVs with types defined below.
*/
enum {
NL_RTAX_UNSPEC,
NL_RTAX_LOCK = 1, /* not supported */
NL_RTAX_MTU = 2, /* desired path MTU */
NL_RTAX_WINDOW = 3, /* not supported */
NL_RTAX_RTT = 4, /* not supported */
NL_RTAX_RTTVAR = 5, /* not supported */
NL_RTAX_SSTHRESH = 6, /* not supported */
NL_RTAX_CWND = 7, /* not supported */
NL_RTAX_ADVMSS = 8, /* not supported */
NL_RTAX_REORDERING = 9, /* not supported */
NL_RTAX_HOPLIMIT = 10, /* not supported */
NL_RTAX_INITCWND = 11, /* not supporrted */
NL_RTAX_FEATURES = 12, /* not supported */
NL_RTAX_RTO_MIN = 13, /* not supported */
NL_RTAX_INITRWND = 14, /* not supported */
NL_RTAX_QUICKACK = 15, /* not supported */
NL_RTAX_CC_ALGO = 15, /* not supported */
NL_RTAX_FASTOPEN_NO_COOKIE = 16, /* not supported */
__NL_RTAX_MAX
};
#define NL_RTAX_MAX (__NL_RTAX_MAX - 1)
#define RTAX_FEATURE_ECN (1 << 0)
#define RTAX_FEATURE_SACK (1 << 1)
#define RTAX_FEATURE_TIMESTAMP (1 << 2)
#define RTAX_FEATURE_ALLFRAG (1 << 3)
#define RTAX_FEATURE_MASK \
(RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | RTAX_FEATURE_TIMESTAMP | \
RTAX_FEATURE_ALLFRAG)
#ifndef _KERNEL
/*
* RTAX_* space clashes with rtsock namespace.
* Use NL_RTAX_ prefix in the kernel and map to
* RTAX_ for userland.
*/
#define RTAX_UNSPEC NL_RTAX_UNSPEC
#define RTAX_LOCK NL_RTAX_LOCK
#define RTAX_MTU NL_RTAX_MTU
#define RTAX_WINDOW NL_RTAX_WINDOW
#define RTAX_RTT NL_RTAX_RTT
#define RTAX_RTTVAR NL_RTAX_RTTVAR
#define RTAX_SSTHRESH NL_RTAX_SSTHRESH
#define RTAX_CWND NL_RTAX_CWND
#define RTAX_ADVMSS NL_RTAX_ADVMSS
#define RTAX_REORDERING NL_RTAX_REORDERING
#define RTAX_HOPLIMIT NL_RTAX_HOPLIMIT
#define RTAX_INITCWND NL_RTAX_INITCWND
#define RTAX_FEATURES NL_RTAX_FEATURES
#define RTAX_RTO_MIN NL_RTAX_RTO_MIN
#define RTAX_INITRWND NL_RTAX_INITRWND
#define RTAX_QUICKACK NL_RTAX_QUICKACK
#define RTAX_CC_ALGO NL_RTAX_CC_ALGO
#define RTAX_FASTOPEN_NO_COOKIE NL_RTAX_FASTOPEN_NO_COOKIE
#endif
/*
* RTA_MULTIPATH consists of an array of rtnexthop structures.
* Each rtnexthop structure contains RTA_GATEWAY or RTA_VIA
* attribute following the header.
*/
struct rtnexthop {
unsigned short rtnh_len;
unsigned char rtnh_flags;
unsigned char rtnh_hops; /* nexthop weight */
int rtnh_ifindex;
};
/* rtnh_flags */
#define RTNH_F_DEAD 0x01 /* not supported */
#define RTNH_F_PERVASIVE 0x02 /* not supported */
#define RTNH_F_ONLINK 0x04 /* not supported */
#define RTNH_F_OFFLOAD 0x08 /* not supported */
#define RTNH_F_LINKDOWN 0x10 /* not supported */
#define RTNH_F_UNRESOLVED 0x20 /* not supported */
#define RTNH_F_TRAP 0x40 /* not supported */
#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | \
RTNH_F_OFFLOAD | RTNH_F_TRAP)
/* Macros to handle hexthops */
#define RTNH_ALIGNTO NL_ITEM_ALIGN_SIZE
#define RTNH_ALIGN(_len) NL_ITEM_ALIGN(_len)
#define RTNH_HDRLEN ((int)sizeof(struct rtnexthop))
#define _RTNH_LEN(_nh) ((int)(_nh)->rtnh_len)
#define _RTNH_ALIGNED_LEN(_nh) RTNH_ALIGN(_RTNH_LEN(_nh))
#define RTNH_OK(_nh, _len) NL_ITEM_OK(_nh, _len, RTNH_HDRLEN, _RTNH_LEN)
#define RTNH_NEXT(_nh) ((struct rtnexthop *)((char *)(_nh) + _RTNH_ALIGNED_LEN(_nh)))
#define RTNH_LENGTH(_len) (RTNH_HDRLEN + (_len))
#define RTNH_SPACE(_len) RTNH_ALIGN(RTNH_LENGTH(_len))
#define RTNH_DATA(_nh) ((struct rtattr *)NL_ITEM_DATA(_nh, RTNH_HDRLEN))
struct rtgenmsg {
unsigned char rtgen_family;
};
#endif