summaryrefslogtreecommitdiffstats
path: root/lib/zclient.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /lib/zclient.h
parentInitial commit. (diff)
downloadfrr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz
frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/zclient.h')
-rw-r--r--lib/zclient.h1329
1 files changed, 1329 insertions, 0 deletions
diff --git a/lib/zclient.h b/lib/zclient.h
new file mode 100644
index 0000000..f18fc05
--- /dev/null
+++ b/lib/zclient.h
@@ -0,0 +1,1329 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Zebra's client header.
+ * Copyright (C) 1999 Kunihiro Ishiguro
+ */
+
+#ifndef _ZEBRA_ZCLIENT_H
+#define _ZEBRA_ZCLIENT_H
+
+struct zclient;
+
+/* For struct zapi_route. */
+#include "prefix.h"
+#include "ipaddr.h"
+
+/* For struct interface and struct connected. */
+#include "if.h"
+
+/* For vrf_bitmap_t. */
+#include "vrf.h"
+
+/* For union g_addr */
+#include "nexthop.h"
+/* For resilience */
+#include "nexthop_group.h"
+
+/* For union pw_protocol_fields */
+#include "pw.h"
+
+#include "mlag.h"
+#include "srte.h"
+#include "srv6.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Zebra types. Used in Zserv message header. */
+typedef uint16_t zebra_size_t;
+
+/* Marker value used in new Zserv, in the byte location corresponding
+ * the command value in the old zserv header. To allow old and new
+ * Zserv headers to be distinguished from each other.
+ */
+#define ZEBRA_HEADER_MARKER 254
+
+/* For input/output buffer to zebra. */
+#define ZEBRA_MAX_PACKET_SIZ 16384U
+#define ZEBRA_SMALL_PACKET_SIZE 200U
+
+/* Zebra header size. */
+#define ZEBRA_HEADER_SIZE 10
+
+/* special socket path name to use TCP
+ * @ is used as first character because that's abstract socket names on Linux
+ */
+#define ZAPI_TCP_PATHNAME "@tcp"
+
+/* IPset size name stands for the name of the ipset entry
+ * that can be created by using some zapi interfaces
+ */
+#define ZEBRA_IPSET_NAME_SIZE 32
+
+/* IPTable action is defined by two values: either
+ * forward or drop
+ */
+#define ZEBRA_IPTABLES_FORWARD 0
+#define ZEBRA_IPTABLES_DROP 1
+
+/* Zebra FEC register command flags. */
+#define ZEBRA_FEC_REGISTER_LABEL 0x1
+#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x2
+
+/* Client capabilities */
+enum zserv_client_capabilities {
+ ZEBRA_CLIENT_GR_CAPABILITIES = 1,
+ ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE = 2,
+ ZEBRA_CLIENT_ROUTE_UPDATE_PENDING = 3,
+ ZEBRA_CLIENT_GR_DISABLE = 4,
+ ZEBRA_CLIENT_RIB_STALE_TIME
+};
+
+/* Macro to check if there GR enabled. */
+#define ZEBRA_CLIENT_GR_ENABLED(X) (X == ZEBRA_CLIENT_GR_CAPABILITIES)
+
+#define ZEBRA_SR_POLICY_NAME_MAX_LENGTH 100
+
+extern struct sockaddr_storage zclient_addr;
+extern socklen_t zclient_addr_len;
+
+/* Zebra message types. Please update the corresponding
+ * command_types array with any changes!
+ */
+typedef enum {
+ ZEBRA_INTERFACE_ADD,
+ ZEBRA_INTERFACE_DELETE,
+ ZEBRA_INTERFACE_ADDRESS_ADD,
+ ZEBRA_INTERFACE_ADDRESS_DELETE,
+ ZEBRA_INTERFACE_UP,
+ ZEBRA_INTERFACE_DOWN,
+ ZEBRA_INTERFACE_SET_MASTER,
+ ZEBRA_INTERFACE_SET_PROTODOWN,
+ ZEBRA_ROUTE_ADD,
+ ZEBRA_ROUTE_DELETE,
+ ZEBRA_ROUTE_NOTIFY_OWNER,
+ ZEBRA_REDISTRIBUTE_ADD,
+ ZEBRA_REDISTRIBUTE_DELETE,
+ ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
+ ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
+ ZEBRA_ROUTER_ID_ADD,
+ ZEBRA_ROUTER_ID_DELETE,
+ ZEBRA_ROUTER_ID_UPDATE,
+ ZEBRA_HELLO,
+ ZEBRA_CAPABILITIES,
+ ZEBRA_NEXTHOP_REGISTER,
+ ZEBRA_NEXTHOP_UNREGISTER,
+ ZEBRA_NEXTHOP_UPDATE,
+ ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
+ ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
+ ZEBRA_INTERFACE_BFD_DEST_UPDATE,
+ ZEBRA_BFD_DEST_REGISTER,
+ ZEBRA_BFD_DEST_DEREGISTER,
+ ZEBRA_BFD_DEST_UPDATE,
+ ZEBRA_BFD_DEST_REPLAY,
+ ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+ ZEBRA_REDISTRIBUTE_ROUTE_DEL,
+ ZEBRA_VRF_UNREGISTER,
+ ZEBRA_VRF_ADD,
+ ZEBRA_VRF_DELETE,
+ ZEBRA_VRF_LABEL,
+ ZEBRA_BFD_CLIENT_REGISTER,
+ ZEBRA_BFD_CLIENT_DEREGISTER,
+ ZEBRA_INTERFACE_ENABLE_RADV,
+ ZEBRA_INTERFACE_DISABLE_RADV,
+ ZEBRA_NEXTHOP_LOOKUP_MRIB,
+ ZEBRA_INTERFACE_LINK_PARAMS,
+ ZEBRA_MPLS_LABELS_ADD,
+ ZEBRA_MPLS_LABELS_DELETE,
+ ZEBRA_MPLS_LABELS_REPLACE,
+ ZEBRA_SR_POLICY_SET,
+ ZEBRA_SR_POLICY_DELETE,
+ ZEBRA_SR_POLICY_NOTIFY_STATUS,
+ ZEBRA_IPMR_ROUTE_STATS,
+ ZEBRA_LABEL_MANAGER_CONNECT,
+ ZEBRA_LABEL_MANAGER_CONNECT_ASYNC,
+ ZEBRA_GET_LABEL_CHUNK,
+ ZEBRA_RELEASE_LABEL_CHUNK,
+ ZEBRA_FEC_REGISTER,
+ ZEBRA_FEC_UNREGISTER,
+ ZEBRA_FEC_UPDATE,
+ ZEBRA_ADVERTISE_DEFAULT_GW,
+ ZEBRA_ADVERTISE_SVI_MACIP,
+ ZEBRA_ADVERTISE_SUBNET,
+ ZEBRA_ADVERTISE_ALL_VNI,
+ ZEBRA_LOCAL_ES_ADD,
+ ZEBRA_LOCAL_ES_DEL,
+ ZEBRA_REMOTE_ES_VTEP_ADD,
+ ZEBRA_REMOTE_ES_VTEP_DEL,
+ ZEBRA_LOCAL_ES_EVI_ADD,
+ ZEBRA_LOCAL_ES_EVI_DEL,
+ ZEBRA_VNI_ADD,
+ ZEBRA_VNI_DEL,
+ ZEBRA_L3VNI_ADD,
+ ZEBRA_L3VNI_DEL,
+ ZEBRA_REMOTE_VTEP_ADD,
+ ZEBRA_REMOTE_VTEP_DEL,
+ ZEBRA_MACIP_ADD,
+ ZEBRA_MACIP_DEL,
+ ZEBRA_IP_PREFIX_ROUTE_ADD,
+ ZEBRA_IP_PREFIX_ROUTE_DEL,
+ ZEBRA_REMOTE_MACIP_ADD,
+ ZEBRA_REMOTE_MACIP_DEL,
+ ZEBRA_DUPLICATE_ADDR_DETECTION,
+ ZEBRA_PW_ADD,
+ ZEBRA_PW_DELETE,
+ ZEBRA_PW_SET,
+ ZEBRA_PW_UNSET,
+ ZEBRA_PW_STATUS_UPDATE,
+ ZEBRA_RULE_ADD,
+ ZEBRA_RULE_DELETE,
+ ZEBRA_RULE_NOTIFY_OWNER,
+ ZEBRA_TABLE_MANAGER_CONNECT,
+ ZEBRA_GET_TABLE_CHUNK,
+ ZEBRA_RELEASE_TABLE_CHUNK,
+ ZEBRA_IPSET_CREATE,
+ ZEBRA_IPSET_DESTROY,
+ ZEBRA_IPSET_ENTRY_ADD,
+ ZEBRA_IPSET_ENTRY_DELETE,
+ ZEBRA_IPSET_NOTIFY_OWNER,
+ ZEBRA_IPSET_ENTRY_NOTIFY_OWNER,
+ ZEBRA_IPTABLE_ADD,
+ ZEBRA_IPTABLE_DELETE,
+ ZEBRA_IPTABLE_NOTIFY_OWNER,
+ ZEBRA_VXLAN_FLOOD_CONTROL,
+ ZEBRA_VXLAN_SG_ADD,
+ ZEBRA_VXLAN_SG_DEL,
+ ZEBRA_VXLAN_SG_REPLAY,
+ ZEBRA_MLAG_PROCESS_UP,
+ ZEBRA_MLAG_PROCESS_DOWN,
+ ZEBRA_MLAG_CLIENT_REGISTER,
+ ZEBRA_MLAG_CLIENT_UNREGISTER,
+ ZEBRA_MLAG_FORWARD_MSG,
+ ZEBRA_NHG_ADD,
+ ZEBRA_NHG_DEL,
+ ZEBRA_NHG_NOTIFY_OWNER,
+ ZEBRA_EVPN_REMOTE_NH_ADD,
+ ZEBRA_EVPN_REMOTE_NH_DEL,
+ ZEBRA_SRV6_LOCATOR_ADD,
+ ZEBRA_SRV6_LOCATOR_DELETE,
+ ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
+ ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
+ ZEBRA_ERROR,
+ ZEBRA_CLIENT_CAPABILITIES,
+ ZEBRA_OPAQUE_MESSAGE,
+ ZEBRA_OPAQUE_REGISTER,
+ ZEBRA_OPAQUE_UNREGISTER,
+ ZEBRA_NEIGH_DISCOVER,
+ ZEBRA_ROUTE_NOTIFY_REQUEST,
+ ZEBRA_CLIENT_CLOSE_NOTIFY,
+ ZEBRA_NHRP_NEIGH_ADDED,
+ ZEBRA_NHRP_NEIGH_REMOVED,
+ ZEBRA_NHRP_NEIGH_GET,
+ ZEBRA_NHRP_NEIGH_REGISTER,
+ ZEBRA_NHRP_NEIGH_UNREGISTER,
+ ZEBRA_NEIGH_IP_ADD,
+ ZEBRA_NEIGH_IP_DEL,
+ ZEBRA_CONFIGURE_ARP,
+ ZEBRA_GRE_GET,
+ ZEBRA_GRE_UPDATE,
+ ZEBRA_GRE_SOURCE_SET,
+ ZEBRA_TC_QDISC_INSTALL,
+ ZEBRA_TC_QDISC_UNINSTALL,
+ ZEBRA_TC_CLASS_ADD,
+ ZEBRA_TC_CLASS_DELETE,
+ ZEBRA_TC_FILTER_ADD,
+ ZEBRA_TC_FILTER_DELETE,
+ ZEBRA_OPAQUE_NOTIFY,
+} zebra_message_types_t;
+/* Zebra message types. Please update the corresponding
+ * command_types array with any changes!
+ */
+
+enum zebra_error_types {
+ ZEBRA_UNKNOWN_ERROR, /* Error of unknown type */
+ ZEBRA_NO_VRF, /* Vrf in header was not found */
+ ZEBRA_INVALID_MSG_TYPE, /* No handler found for msg type */
+};
+
+static inline const char *zebra_error_type2str(enum zebra_error_types type)
+{
+ const char *ret = "UNKNOWN";
+
+ switch (type) {
+ case ZEBRA_UNKNOWN_ERROR:
+ ret = "ZEBRA_UNKNOWN_ERROR";
+ break;
+ case ZEBRA_NO_VRF:
+ ret = "ZEBRA_NO_VRF";
+ break;
+ case ZEBRA_INVALID_MSG_TYPE:
+ ret = "ZEBRA_INVALID_MSG_TYPE";
+ break;
+ }
+
+ return ret;
+}
+
+struct redist_proto {
+ uint8_t enabled;
+ struct list *instances;
+};
+
+struct zclient_capabilities {
+ uint32_t ecmp;
+ bool mpls_enabled;
+ enum mlag_role role;
+ bool v6_with_v4_nexthop;
+};
+
+/* Graceful Restart Capabilities message */
+struct zapi_cap {
+ enum zserv_client_capabilities cap;
+ uint32_t stale_removal_time;
+ afi_t afi;
+ safi_t safi;
+ vrf_id_t vrf_id;
+};
+
+/* clang-format off */
+#define ZAPI_CALLBACK_ARGS \
+ int cmd, struct zclient *zclient, uint16_t length, vrf_id_t vrf_id
+
+/* function-type typedef (pointer not included) */
+typedef int (zclient_handler)(ZAPI_CALLBACK_ARGS);
+/* clang-format on */
+
+/* Structure for the zebra client. */
+struct zclient {
+ /* The thread master we schedule ourselves on */
+ struct event_loop *master;
+
+ /* Privileges to change socket values */
+ struct zebra_privs_t *privs;
+
+ /* Do we care about failure events for route install? */
+ bool receive_notify;
+
+ /* Is this a synchronous client? */
+ bool synchronous;
+
+ /* BFD enabled with bfd_protocol_integration_init() */
+ bool bfd_integration;
+
+ /* Session id (optional) to support clients with multiple sessions */
+ uint32_t session_id;
+
+ /* Socket to zebra daemon. */
+ int sock;
+
+ /* Connection failure count. */
+ int fail;
+
+ /* Input buffer for zebra message. */
+ struct stream *ibuf;
+
+ /* Output buffer for zebra message. */
+ struct stream *obuf;
+
+ /* Buffer of data waiting to be written to zebra. */
+ struct buffer *wb;
+
+ /* Read and connect thread. */
+ struct event *t_read;
+ struct event *t_connect;
+
+ /* Thread to write buffered data to zebra. */
+ struct event *t_write;
+
+ /* Redistribute information. */
+ uint8_t redist_default; /* clients protocol */
+ unsigned short instance;
+ struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX];
+ vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
+
+ /* Redistribute default. */
+ vrf_bitmap_t default_information[AFI_MAX];
+
+ /* Pointer to the callback functions. */
+ void (*zebra_connected)(struct zclient *);
+ void (*zebra_capabilities)(struct zclient_capabilities *cap);
+
+ int (*handle_error)(enum zebra_error_types error);
+
+ /*
+ * When the zclient attempts to write the stream data to
+ * it's named pipe to/from zebra, we may have a situation
+ * where the other daemon has not fully drained the data
+ * from the socket. In this case provide a mechanism
+ * where we will *still* buffer the data to be sent
+ * and also provide a callback mechanism to the appropriate
+ * place where we can signal that we're ready to receive
+ * more data.
+ */
+ void (*zebra_buffer_write_ready)(void);
+
+ zclient_handler *const *handlers;
+ size_t n_handlers;
+};
+
+/* lib handlers added in bfd.c */
+extern int zclient_bfd_session_replay(ZAPI_CALLBACK_ARGS);
+extern int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS);
+
+/* Zebra API message flag. */
+#define ZAPI_MESSAGE_NEXTHOP 0x01
+#define ZAPI_MESSAGE_DISTANCE 0x02
+#define ZAPI_MESSAGE_METRIC 0x04
+#define ZAPI_MESSAGE_TAG 0x08
+#define ZAPI_MESSAGE_MTU 0x10
+#define ZAPI_MESSAGE_SRCPFX 0x20
+/* Backup nexthops are present */
+#define ZAPI_MESSAGE_BACKUP_NEXTHOPS 0x40
+#define ZAPI_MESSAGE_NHG 0x80
+/*
+ * This should only be used by a DAEMON that needs to communicate
+ * the table being used is not in the VRF. You must pass the
+ * default vrf, else this will be ignored.
+ */
+#define ZAPI_MESSAGE_TABLEID 0x0100
+#define ZAPI_MESSAGE_SRTE 0x0200
+#define ZAPI_MESSAGE_OPAQUE 0x0400
+
+#define ZSERV_VERSION 6
+/* Zserv protocol message header */
+struct zmsghdr {
+ uint16_t length;
+ /* Always set to 255 in new zserv */
+ uint8_t marker;
+ uint8_t version;
+ vrf_id_t vrf_id;
+ uint16_t command;
+} __attribute__((packed));
+#define ZAPI_HEADER_CMD_LOCATION offsetof(struct zmsghdr, command)
+
+/*
+ * ZAPI nexthop. Note that these are sorted when associated with ZAPI routes,
+ * and that sorting must be aligned with the sorting of nexthops in
+ * lib/nexthop.c. Any new fields must be accounted for in zapi_nexthop_cmp().
+ */
+struct zapi_nexthop {
+ enum nexthop_types_t type;
+ vrf_id_t vrf_id;
+ ifindex_t ifindex;
+ uint8_t flags;
+ union {
+ union g_addr gate;
+ enum blackhole_type bh_type;
+ };
+
+ /* MPLS labels for BGP-LU or Segment Routing */
+ uint8_t label_num;
+ enum lsp_types_t label_type;
+ mpls_label_t labels[MPLS_MAX_LABELS];
+
+ struct ethaddr rmac;
+
+ uint32_t weight;
+
+ /* Backup nexthops, for IP-FRR, TI-LFA, etc */
+ uint8_t backup_num;
+ uint8_t backup_idx[NEXTHOP_MAX_BACKUPS];
+
+ /* SR-TE color. */
+ uint32_t srte_color;
+
+ /* SRv6 localsid info for Endpoint-behaviour */
+ uint32_t seg6local_action;
+ struct seg6local_context seg6local_ctx;
+
+ /* SRv6 Headend-behaviour */
+ int seg_num;
+ struct in6_addr seg6_segs[SRV6_MAX_SEGS];
+};
+
+/*
+ * ZAPI nexthop flags values - we're encoding a single octet
+ * initially, so ensure that the on-the-wire encoding continues
+ * to match the number of valid flags.
+ */
+
+#define ZAPI_NEXTHOP_FLAG_ONLINK 0x01
+#define ZAPI_NEXTHOP_FLAG_LABEL 0x02
+#define ZAPI_NEXTHOP_FLAG_WEIGHT 0x04
+#define ZAPI_NEXTHOP_FLAG_HAS_BACKUP 0x08 /* Nexthop has a backup */
+#define ZAPI_NEXTHOP_FLAG_SEG6 0x10
+#define ZAPI_NEXTHOP_FLAG_SEG6LOCAL 0x20
+#define ZAPI_NEXTHOP_FLAG_EVPN 0x40
+
+/*
+ * ZAPI Nexthop Group. For use with protocol creation of nexthop groups.
+ */
+struct zapi_nhg {
+ uint16_t proto;
+ uint32_t id;
+
+ struct nhg_resilience resilience;
+
+ uint16_t nexthop_num;
+ struct zapi_nexthop nexthops[MULTIPATH_NUM];
+
+ uint16_t backup_nexthop_num;
+ struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
+};
+
+/*
+ * Some of these data structures do not map easily to
+ * a actual data structure size giving different compilers
+ * and systems. For those data structures we need
+ * to use the smallest available stream_getX/putX functions
+ * to encode/decode.
+ */
+struct zapi_route {
+ uint8_t type;
+ unsigned short instance;
+
+ /* If you add flags, update zclient_dump_route_flags */
+ uint32_t flags;
+/*
+ * Cause Zebra to consider this routes nexthops recursively
+ */
+#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
+/*
+ * This is a route that is read in on startup that was left around
+ * from a previous run of FRR
+ */
+#define ZEBRA_FLAG_SELFROUTE 0x02
+/*
+ * This flag is used to tell Zebra that the BGP route being passed
+ * down is a IBGP route
+ */
+#define ZEBRA_FLAG_IBGP 0x04
+/*
+ * This is a route that has been selected for FIB installation.
+ * This flag is set in zebra and can be passed up to routing daemons
+ */
+#define ZEBRA_FLAG_SELECTED 0x08
+/*
+ * This is a route that we are telling Zebra that this route *must*
+ * win and will be installed even over ZEBRA_FLAG_SELECTED
+ */
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
+/*
+ * This flag tells Zebra that the route is a EVPN route and should
+ * be treated specially
+ */
+#define ZEBRA_FLAG_EVPN_ROUTE 0x20
+/*
+ * This flag tells Zebra that it should treat the distance passed
+ * down as an additional discriminator for route selection of the
+ * route entry. This mainly is used for backup static routes.
+ */
+#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
+/*
+ * This flag tells everyone that the route was intentionally
+ * not offloaded and the route will be sent to the cpu for
+ * forwarding. This flag makes no sense unless you are in
+ * an asic offload situation
+ */
+#define ZEBRA_FLAG_TRAPPED 0x80
+/*
+ * This flag tells everyone that the route has been
+ * successfully offloaded to an asic for forwarding.
+ * This flag makes no sense unless you are in an asic
+ * offload situation.
+ */
+#define ZEBRA_FLAG_OFFLOADED 0x100
+/*
+ * This flag tells everyone that the route has
+ * failed offloading.
+ * This flag makes no sense unless you are in an asic
+ * offload situation.
+ */
+#define ZEBRA_FLAG_OFFLOAD_FAILED 0x200
+
+/*
+ * This flag lets us know that we think the route entry
+ * received has caused us to be out of sync with the
+ * kernel (NLM_F_APPEND at the very least )
+ */
+#define ZEBRA_FLAG_OUTOFSYNC 0x400
+
+ /* The older XXX_MESSAGE flags live here */
+ uint32_t message;
+
+ /*
+ * This is an enum but we are going to treat it as a uint8_t
+ * for purpose of encoding/decoding
+ */
+ safi_t safi;
+
+ struct prefix prefix;
+ struct prefix_ipv6 src_prefix;
+
+ uint16_t nexthop_num;
+ struct zapi_nexthop nexthops[MULTIPATH_NUM];
+
+ /* Support backup routes for IP FRR, TI-LFA, traffic engineering */
+ uint16_t backup_nexthop_num;
+ struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
+
+ uint32_t nhgid;
+
+ uint8_t distance;
+
+ uint32_t metric;
+
+ route_tag_t tag;
+
+ uint32_t mtu;
+
+ vrf_id_t vrf_id;
+
+ uint32_t tableid;
+
+ /* SR-TE color (used for nexthop updates only). */
+ uint32_t srte_color;
+
+#define ZAPI_MESSAGE_OPAQUE_LENGTH 1024
+ struct {
+ uint16_t length;
+ uint8_t data[ZAPI_MESSAGE_OPAQUE_LENGTH];
+ } opaque;
+};
+
+extern char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len);
+
+struct zapi_labels {
+ uint8_t message;
+#define ZAPI_LABELS_FTN 0x01
+#define ZAPI_LABELS_HAS_BACKUPS 0x02
+ enum lsp_types_t type;
+ mpls_label_t local_label;
+ struct {
+ struct prefix prefix;
+ uint8_t type;
+ unsigned short instance;
+ } route;
+
+ uint16_t nexthop_num;
+ struct zapi_nexthop nexthops[MULTIPATH_NUM];
+
+ /* Backup nexthops, if present */
+ uint16_t backup_nexthop_num;
+ struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
+};
+
+struct zapi_srte_tunnel {
+ enum lsp_types_t type;
+ mpls_label_t local_label;
+ uint8_t label_num;
+ mpls_label_t labels[MPLS_MAX_LABELS];
+};
+
+struct zapi_sr_policy {
+ uint32_t color;
+ struct ipaddr endpoint;
+ char name[SRTE_POLICY_NAME_MAX_LENGTH];
+ struct zapi_srte_tunnel segment_list;
+ int status;
+};
+
+struct zapi_pw {
+ char ifname[INTERFACE_NAMSIZ];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ uint8_t protocol;
+};
+
+struct zapi_pw_status {
+ char ifname[INTERFACE_NAMSIZ];
+ ifindex_t ifindex;
+ uint32_t status;
+};
+
+/* IGP instance data associated to a RLFA. */
+struct zapi_rlfa_igp {
+ vrf_id_t vrf_id;
+ int protocol;
+ union {
+ struct {
+ char area_tag[32];
+ struct {
+ int tree_id;
+ int level;
+ unsigned int run_id;
+ } spf;
+ } isis;
+ };
+};
+
+/* IGP -> LDP RLFA (un)registration message. */
+struct zapi_rlfa_request {
+ /* IGP instance data. */
+ struct zapi_rlfa_igp igp;
+
+ /* Destination prefix. */
+ struct prefix destination;
+
+ /* PQ node address. */
+ struct in_addr pq_address;
+};
+
+/* LDP -> IGP RLFA label update. */
+struct zapi_rlfa_response {
+ /* IGP instance data. */
+ struct zapi_rlfa_igp igp;
+
+ /* Destination prefix. */
+ struct prefix destination;
+
+ /* Resolved LDP labels. */
+ mpls_label_t pq_label;
+ uint16_t nexthop_num;
+ struct {
+ int family;
+ union g_addr gate;
+ mpls_label_t label;
+ } nexthops[MULTIPATH_NUM];
+};
+
+enum zapi_route_notify_owner {
+ ZAPI_ROUTE_FAIL_INSTALL,
+ ZAPI_ROUTE_BETTER_ADMIN_WON,
+ ZAPI_ROUTE_INSTALLED,
+ ZAPI_ROUTE_REMOVED,
+ ZAPI_ROUTE_REMOVE_FAIL,
+};
+
+enum zapi_nhg_notify_owner {
+ ZAPI_NHG_FAIL_INSTALL,
+ ZAPI_NHG_INSTALLED,
+ ZAPI_NHG_REMOVED,
+ ZAPI_NHG_REMOVE_FAIL,
+};
+
+enum zapi_rule_notify_owner {
+ ZAPI_RULE_FAIL_INSTALL,
+ ZAPI_RULE_INSTALLED,
+ ZAPI_RULE_REMOVED,
+ ZAPI_RULE_FAIL_REMOVE,
+};
+
+enum ipset_type {
+ IPSET_NET_NET = 1,
+ IPSET_NET_PORT_NET,
+ IPSET_NET_PORT,
+ IPSET_NET
+};
+
+enum zapi_ipset_notify_owner {
+ ZAPI_IPSET_FAIL_INSTALL = 0,
+ ZAPI_IPSET_INSTALLED,
+ ZAPI_IPSET_REMOVED,
+ ZAPI_IPSET_FAIL_REMOVE,
+};
+
+enum zapi_ipset_entry_notify_owner {
+ ZAPI_IPSET_ENTRY_FAIL_INSTALL = 0,
+ ZAPI_IPSET_ENTRY_INSTALLED,
+ ZAPI_IPSET_ENTRY_REMOVED,
+ ZAPI_IPSET_ENTRY_FAIL_REMOVE,
+};
+
+enum zapi_iptable_notify_owner {
+ ZAPI_IPTABLE_FAIL_INSTALL = 0,
+ ZAPI_IPTABLE_INSTALLED,
+ ZAPI_IPTABLE_REMOVED,
+ ZAPI_IPTABLE_FAIL_REMOVE,
+};
+
+enum zclient_send_status {
+ ZCLIENT_SEND_FAILURE = -1,
+ ZCLIENT_SEND_SUCCESS = 0,
+ ZCLIENT_SEND_BUFFERED = 1
+};
+
+static inline const char *
+zapi_nhg_notify_owner2str(enum zapi_nhg_notify_owner note)
+{
+ const char *ret = "UNKNOWN";
+
+ switch (note) {
+ case ZAPI_NHG_FAIL_INSTALL:
+ ret = "ZAPI_NHG_FAIL_INSTALL";
+ break;
+ case ZAPI_NHG_INSTALLED:
+ ret = "ZAPI_NHG_INSTALLED";
+ break;
+ case ZAPI_NHG_REMOVE_FAIL:
+ ret = "ZAPI_NHG_REMOVE_FAIL";
+ break;
+ case ZAPI_NHG_REMOVED:
+ ret = "ZAPI_NHG_REMOVED";
+ break;
+ }
+
+ return ret;
+}
+
+static inline const char *
+zapi_rule_notify_owner2str(enum zapi_rule_notify_owner note)
+{
+ const char *ret = "UNKNOWN";
+
+ switch (note) {
+ case ZAPI_RULE_FAIL_INSTALL:
+ ret = "ZAPI_RULE_FAIL_INSTALL";
+ break;
+ case ZAPI_RULE_INSTALLED:
+ ret = "ZAPI_RULE_INSTALLED";
+ break;
+ case ZAPI_RULE_FAIL_REMOVE:
+ ret = "ZAPI_RULE_FAIL_REMOVE";
+ break;
+ case ZAPI_RULE_REMOVED:
+ ret = "ZAPI_RULE_REMOVED";
+ break;
+ }
+
+ return ret;
+}
+
+/* Zebra MAC types */
+#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
+#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
+#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */
+#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */
+#define ZEBRA_MACIP_TYPE_SVI_IP 0x10 /* SVI MAC-IP */
+#define ZEBRA_MACIP_TYPE_PROXY_ADVERT 0x20 /* Not locally active */
+#define ZEBRA_MACIP_TYPE_SYNC_PATH 0x40 /* sync path */
+/* XXX - flags is an u8; that needs to be changed to u32 if you need
+ * to allocate past 0x80. Additionally touch zclient_evpn_dump_macip_flags
+ */
+#define MACIP_BUF_SIZE 128
+extern char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf,
+ size_t len);
+
+/* Zebra ES VTEP flags (ZEBRA_REMOTE_ES_VTEP_ADD) */
+/* ESR has been rxed from the VTEP. Only VTEPs that have advertised the
+ * Type-4 route can participate in DF election.
+ */
+#define ZAPI_ES_VTEP_FLAG_ESR_RXED (1 << 0)
+
+enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+
+struct zclient_options {
+ bool receive_notify;
+ bool synchronous;
+};
+
+extern struct zclient_options zclient_options_default;
+
+/* link layer representation for GRE like interfaces
+ * ip_in is the underlay IP, ip_out is the tunnel dest
+ * index stands for the index of the interface
+ * ndm state stands for the NDM value in netlink
+ * (see linux/neighbour.h)
+ */
+#define ZEBRA_NEIGH_STATE_INCOMPLETE (0x01)
+#define ZEBRA_NEIGH_STATE_REACHABLE (0x02)
+#define ZEBRA_NEIGH_STATE_STALE (0x04)
+#define ZEBRA_NEIGH_STATE_DELAY (0x08)
+#define ZEBRA_NEIGH_STATE_PROBE (0x10)
+#define ZEBRA_NEIGH_STATE_FAILED (0x20)
+#define ZEBRA_NEIGH_STATE_NOARP (0x40)
+#define ZEBRA_NEIGH_STATE_PERMANENT (0x80)
+#define ZEBRA_NEIGH_STATE_NONE (0x00)
+
+struct zapi_neigh_ip {
+ int cmd;
+ struct ipaddr ip_in;
+ struct ipaddr ip_out;
+ ifindex_t index;
+ uint32_t ndm_state;
+};
+int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api);
+int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
+ union sockunion *out, struct interface *ifp,
+ int ndm_state);
+
+/*
+ * We reserve the top 4 bits for l2-NHG, everything else
+ * is for zebra/proto l3-NHG.
+ *
+ * Each client is going to get it's own nexthop group space
+ * and we'll separate them, we'll figure out where to start based upon
+ * the route_types.h
+ */
+#define ZEBRA_NHG_PROTO_UPPER \
+ ((uint32_t)250000000) /* Bottom 28 bits then rounded down */
+#define ZEBRA_NHG_PROTO_SPACING (ZEBRA_NHG_PROTO_UPPER / ZEBRA_ROUTE_MAX)
+#define ZEBRA_NHG_PROTO_LOWER \
+ (ZEBRA_NHG_PROTO_SPACING * (ZEBRA_ROUTE_CONNECT + 1))
+
+extern uint32_t zclient_get_nhg_start(uint32_t proto);
+
+extern struct zclient *zclient_new(struct event_loop *m,
+ struct zclient_options *opt,
+ zclient_handler *const *handlers,
+ size_t n_handlers);
+
+extern void zclient_init(struct zclient *, int, unsigned short,
+ struct zebra_privs_t *privs);
+extern int zclient_start(struct zclient *);
+extern void zclient_stop(struct zclient *);
+extern void zclient_reset(struct zclient *);
+extern void zclient_free(struct zclient *);
+
+extern int zclient_socket_connect(struct zclient *);
+
+extern unsigned short *redist_check_instance(struct redist_proto *,
+ unsigned short);
+extern void redist_add_instance(struct redist_proto *, unsigned short);
+extern void redist_del_instance(struct redist_proto *, unsigned short);
+extern void redist_del_all_instances(struct redist_proto *red);
+
+/*
+ * Send to zebra that the specified vrf is using label to resolve
+ * itself for L3VPN's. Repeated calls of this function with
+ * different labels will cause an effective update of the
+ * label for lookup. If you pass in MPLS_LABEL_NONE
+ * we will cause a delete action and remove this label pop
+ * operation.
+ *
+ * The underlying AF_MPLS doesn't care about afi's
+ * but we can make the zebra_vrf keep track of what
+ * we have installed and play some special games
+ * to get them both installed.
+ */
+extern enum zclient_send_status
+zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi,
+ mpls_label_t label, enum lsp_types_t ltype);
+
+extern enum zclient_send_status
+zclient_send_localsid(struct zclient *zclient, const struct in6_addr *sid,
+ vrf_id_t vrf_id, enum seg6local_action_t action,
+ const struct seg6local_context *context);
+
+extern void zclient_send_reg_requests(struct zclient *, vrf_id_t);
+extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t);
+extern enum zclient_send_status
+zclient_send_router_id_update(struct zclient *zclient,
+ zebra_message_types_t type, afi_t afi,
+ vrf_id_t vrf_id);
+
+extern enum zclient_send_status
+zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
+ struct interface *ifp, int enable,
+ uint32_t ra_interval);
+extern enum zclient_send_status
+zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
+ struct interface *ifp, bool down);
+
+/* Send redistribute command to zebra daemon. Do not update zclient state. */
+extern enum zclient_send_status
+zebra_redistribute_send(int command, struct zclient *, afi_t, int type,
+ unsigned short instance, vrf_id_t vrf_id);
+
+extern enum zclient_send_status
+zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi,
+ vrf_id_t vrf_id);
+
+/* Send route notify request to zebra */
+extern int zebra_route_notify_send(int command, struct zclient *zclient,
+ bool set);
+
+/* If state has changed, update state and call zebra_redistribute_send. */
+extern void zclient_redistribute(int command, struct zclient *, afi_t, int type,
+ unsigned short instance, vrf_id_t vrf_id);
+
+/* If state has changed, update state and send the command to zebra. */
+extern void zclient_redistribute_default(int command, struct zclient *,
+ afi_t, vrf_id_t vrf_id);
+
+/*
+ * Send the message in zclient->obuf to the zebra daemon (or enqueue it).
+ * Returns:
+ * -1 on a I/O error
+ * 0 data was successfully sent
+ * 1 data was buffered for future usage
+ */
+extern enum zclient_send_status zclient_send_message(struct zclient *);
+
+/* create header for command, length to be filled in by user later */
+extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t);
+/*
+ * Read sizeof(struct zmsghdr) bytes from the provided socket and parse the
+ * received data into the specified fields. If this is successful, read the
+ * rest of the packet into the provided stream.
+ *
+ * s
+ * The stream to read into
+ *
+ * sock
+ * The socket to read from
+ *
+ * size
+ * Parsed message size will be placed in the pointed-at integer
+ *
+ * marker
+ * Parsed marker will be placed in the pointed-at byte
+ *
+ * version
+ * Parsed version will be placed in the pointed-at byte
+ *
+ * vrf_id
+ * Parsed VRF ID will be placed in the pointed-at vrf_id_t
+ *
+ * cmd
+ * Parsed command number will be placed in the pointed-at integer
+ *
+ * Returns:
+ * -1 if:
+ * - insufficient data for header was read
+ * - a version mismatch was detected
+ * - a marker mismatch was detected
+ * - header size field specified more data than could be read
+ */
+extern int zclient_read_header(struct stream *s, int sock, uint16_t *size,
+ uint8_t *marker, uint8_t *version,
+ vrf_id_t *vrf_id, uint16_t *cmd);
+/*
+ * Parse header from ZAPI message stream into struct zmsghdr.
+ * This function assumes the stream getp points at the first byte of the header.
+ * If the function is successful then the stream getp will point to the byte
+ * immediately after the last byte of the header.
+ *
+ * zmsg
+ * The stream containing the header
+ *
+ * hdr
+ * The header struct to parse into.
+ *
+ * Returns:
+ * true if parsing succeeded, false otherwise
+ */
+extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr);
+
+extern enum zclient_send_status
+zclient_interface_set_master(struct zclient *client, struct interface *master,
+ struct interface *slave);
+extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t);
+extern struct connected *zebra_interface_address_read(int, struct stream *,
+ vrf_id_t);
+extern struct nbr_connected *
+zebra_interface_nbr_address_read(int, struct stream *, vrf_id_t);
+extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
+ vrf_id_t vrf_id,
+ vrf_id_t *new_vrf_id);
+extern int zebra_router_id_update_read(struct stream *s, struct prefix *rid);
+
+extern struct interface *zebra_interface_link_params_read(struct stream *s,
+ vrf_id_t vrf_id,
+ bool *changed);
+extern size_t zebra_interface_link_params_write(struct stream *,
+ struct interface *);
+extern enum zclient_send_status
+zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
+ uint32_t chunk_size, uint32_t base);
+
+extern int lm_label_manager_connect(struct zclient *zclient, int async);
+extern int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
+ uint32_t base, uint32_t chunk_size,
+ uint32_t *start, uint32_t *end);
+extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
+ uint32_t end);
+extern int tm_table_manager_connect(struct zclient *zclient);
+extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
+ uint32_t *start, uint32_t *end);
+extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
+ uint32_t end);
+extern int srv6_manager_get_locator_chunk(struct zclient *zclient,
+ const char *locator_name);
+extern int srv6_manager_release_locator_chunk(struct zclient *zclient,
+ const char *locator_name);
+
+extern enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient,
+ int cmd,
+ struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_encode(struct stream *s, int cmd,
+ struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_notify_status_decode(struct stream *s,
+ struct zapi_sr_policy *zp);
+
+extern enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
+ int cmd,
+ struct zapi_labels *zl);
+extern int zapi_labels_encode(struct stream *s, int cmd,
+ struct zapi_labels *zl);
+extern int zapi_labels_decode(struct stream *s, struct zapi_labels *zl);
+
+extern int zapi_srv6_locator_encode(struct stream *s,
+ const struct srv6_locator *l);
+extern int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l);
+extern int zapi_srv6_locator_chunk_encode(struct stream *s,
+ const struct srv6_locator_chunk *c);
+extern int zapi_srv6_locator_chunk_decode(struct stream *s,
+ struct srv6_locator_chunk *c);
+
+extern enum zclient_send_status zebra_send_pw(struct zclient *zclient,
+ int command, struct zapi_pw *pw);
+extern int zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS,
+ struct zapi_pw_status *pw);
+
+extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *,
+ struct zapi_route *);
+extern enum zclient_send_status
+zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p,
+ safi_t safi, bool connected, bool resolve_via_default,
+ vrf_id_t vrf_id);
+int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
+ uint32_t api_flags, uint32_t api_message);
+extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *);
+extern int zapi_route_decode(struct stream *s, struct zapi_route *api);
+extern int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
+ uint32_t api_flags, uint32_t api_message);
+bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
+ enum zapi_nhg_notify_owner *note);
+bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
+ uint32_t *tableid,
+ enum zapi_route_notify_owner *note,
+ afi_t *afi, safi_t *safi);
+bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
+ uint32_t *priority, uint32_t *unique, char *ifname,
+ enum zapi_rule_notify_owner *note);
+bool zapi_ipset_notify_decode(struct stream *s,
+ uint32_t *unique,
+ enum zapi_ipset_notify_owner *note);
+
+/* Nexthop-group message apis */
+extern enum zclient_send_status
+zclient_nhg_send(struct zclient *zclient, int cmd, struct zapi_nhg *api_nhg);
+
+#define ZEBRA_IPSET_NAME_SIZE 32
+
+bool zapi_ipset_entry_notify_decode(struct stream *s,
+ uint32_t *unique,
+ char *ipset_name,
+ enum zapi_ipset_entry_notify_owner *note);
+bool zapi_iptable_notify_decode(struct stream *s,
+ uint32_t *unique,
+ enum zapi_iptable_notify_owner *note);
+
+extern struct nexthop *
+nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh);
+int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
+ const struct nexthop *nh);
+int zapi_backup_nexthop_from_nexthop(struct zapi_nexthop *znh,
+ const struct nexthop *nh);
+/*
+ * match -> is the prefix that the calling daemon asked to be matched
+ * against.
+ * nhr->prefix -> is the actual prefix that was matched against in the
+ * rib itself.
+ *
+ * This distinction is made because a LPM can be made if there is a
+ * covering route. This way the upper level protocol can make a decision
+ * point about whether or not it wants to use the match or not.
+ */
+extern bool zapi_nexthop_update_decode(struct stream *s, struct prefix *match,
+ struct zapi_route *nhr);
+const char *zapi_nexthop2str(const struct zapi_nexthop *znh, char *buf,
+ int bufsize);
+
+/* Decode the zebra error message */
+extern bool zapi_error_decode(struct stream *s, enum zebra_error_types *error);
+
+/* Encode and decode restart capabilities */
+extern enum zclient_send_status
+zclient_capabilities_send(uint32_t cmd, struct zclient *zclient,
+ struct zapi_cap *api);
+extern int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api);
+
+static inline void zapi_route_set_blackhole(struct zapi_route *api,
+ enum blackhole_type bh_type)
+{
+ api->nexthop_num = 1;
+ api->nexthops[0].type = NEXTHOP_TYPE_BLACKHOLE;
+ api->nexthops[0].vrf_id = VRF_DEFAULT;
+ api->nexthops[0].bh_type = bh_type;
+ SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
+};
+
+extern enum zclient_send_status
+zclient_send_mlag_register(struct zclient *client, uint32_t bit_map);
+extern enum zclient_send_status
+zclient_send_mlag_deregister(struct zclient *client);
+
+extern enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
+ struct stream *client_s);
+
+/*
+ * Send an OPAQUE message, contents opaque to zebra - but note that
+ * the length of the payload is restricted by the zclient's
+ * outgoing message buffer.
+ * The message header is a message subtype; please use the registry
+ * below to avoid sub-type collisions. Clients use the registration
+ * apis to manage the specific opaque subtypes they want to receive.
+ */
+enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
+ uint32_t type, const uint8_t *data,
+ size_t datasize);
+
+enum zclient_send_status
+zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
+ uint8_t proto, uint16_t instance,
+ uint32_t session_id, const uint8_t *data,
+ size_t datasize);
+
+/* Init functions also provided for clients who want to encode their
+ * data inline into the zclient's stream buffer. Please use these instead
+ * of hand-encoding the header info, since that may change over time.
+ * Note that these will reset the zclient's outbound stream before encoding.
+ */
+enum zclient_send_status zapi_opaque_init(struct zclient *zclient,
+ uint32_t type, uint16_t flags);
+
+enum zclient_send_status
+zapi_opaque_unicast_init(struct zclient *zclient, uint32_t type, uint16_t flags,
+ uint8_t proto, uint16_t instance, uint32_t session_id);
+
+/* Struct representing the decoded opaque header info */
+struct zapi_opaque_msg {
+ uint32_t type; /* Subtype */
+ uint16_t len; /* len after zapi header and this info */
+ uint16_t flags;
+
+ /* Sending client info */
+ uint8_t src_proto;
+ uint16_t src_instance;
+ uint32_t src_session_id;
+
+ /* Destination client info - *if* UNICAST flag is set */
+ uint8_t dest_proto;
+ uint16_t dest_instance;
+ uint32_t dest_session_id;
+};
+
+#define ZAPI_OPAQUE_FLAG_UNICAST 0x01
+
+/* Simple struct to convey registration/unreg requests */
+struct zapi_opaque_reg_info {
+ /* Message subtype */
+ uint32_t type;
+
+ /* Client session tuple */
+ uint8_t proto;
+ uint16_t instance;
+ uint32_t session_id;
+};
+
+/* Simple struct conveying information about opaque notifications.
+ * Daemons can request notifications about the status of registration for
+ * opaque message types. For example, a client daemon can request notification
+ * when a server registers to receive a certain message code. Or a server can
+ * request notification when a subscriber registers for its output.
+ */
+struct zapi_opaque_notif_info {
+ bool request; /* Request to register, or notification from zebra */
+ bool reg; /* Register or unregister */
+ uint32_t msg_type; /* Target message code */
+
+ /* For notif registration, zapi info for the client.
+ * For notifications, zapi info for the message's server/registrant.
+ * For notification that there is no server/registrant, not present.
+ */
+ uint8_t proto;
+ uint16_t instance;
+ uint32_t session_id;
+};
+
+/* The same ZAPI message is used for daemon->zebra requests, and for
+ * zebra->daemon notifications.
+ * Daemons send 'request' true, and 'reg' true or false.
+ * Zebra sends 'request' false, 'reg' set if the notification is a
+ * server/receiver registration for the message type, and false if the event
+ * is the end of registrations.
+ */
+
+/* Decode incoming opaque */
+int zclient_opaque_decode(struct stream *msg, struct zapi_opaque_msg *info);
+
+enum zclient_send_status zclient_register_opaque(struct zclient *zclient,
+ uint32_t type);
+enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient,
+ uint32_t type);
+int zapi_opaque_reg_decode(struct stream *msg,
+ struct zapi_opaque_reg_info *info);
+
+/* Opaque notification features */
+enum zclient_send_status zclient_opaque_request_notify(struct zclient *zclient,
+ uint32_t msgtype);
+enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient,
+ uint32_t msgtype);
+
+/* Encode, decode an incoming zapi opaque notification */
+int zclient_opaque_notif_encode(struct stream *s, uint32_t msg_type,
+ bool reg /* register or unreg*/, uint8_t proto,
+ uint16_t instance, uint32_t session_id);
+int zclient_opaque_notif_decode(struct stream *s,
+ struct zapi_opaque_notif_info *info);
+
+/*
+ * Registry of opaque message types. Please do not reuse an in-use
+ * type code; some daemons are likely relying on it.
+ */
+enum zapi_opaque_registry {
+ /* Request link-state database dump, at restart for example */
+ LINK_STATE_SYNC = 1,
+ /* Update containing link-state db info */
+ LINK_STATE_UPDATE = 2,
+ /* Request LDP-SYNC state from LDP */
+ LDP_IGP_SYNC_IF_STATE_REQUEST = 3,
+ /* Update containing LDP IGP Sync State info */
+ LDP_IGP_SYNC_IF_STATE_UPDATE = 4,
+ /* Announce that LDP is up */
+ LDP_IGP_SYNC_ANNOUNCE_UPDATE = 5,
+ /* Register RLFA with LDP */
+ LDP_RLFA_REGISTER = 7,
+ /* Unregister all RLFAs with LDP */
+ LDP_RLFA_UNREGISTER_ALL = 8,
+ /* Announce LDP labels associated to a previously registered RLFA */
+ LDP_RLFA_LABELS = 9,
+};
+
+/* Send the hello message.
+ * Returns 0 for success or -1 on an I/O error.
+ */
+extern enum zclient_send_status zclient_send_hello(struct zclient *client);
+
+extern enum zclient_send_status
+zclient_send_neigh_discovery_req(struct zclient *zclient,
+ const struct interface *ifp,
+ const struct prefix *p);
+
+struct zapi_client_close_info {
+ /* Client session tuple */
+ uint8_t proto;
+ uint16_t instance;
+ uint32_t session_id;
+};
+
+/* Decode incoming client close notify */
+extern int zapi_client_close_notify_decode(struct stream *s,
+ struct zapi_client_close_info *info);
+
+extern int zclient_send_zebra_gre_request(struct zclient *client,
+ struct interface *ifp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZEBRA_ZCLIENT_H */