back to topotato report
topotato coverage report
Current view: top level - lib - zclient.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 736 2287 32.2 %
Date: 2023-11-16 17:19:14 Functions: 55 286 19.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* Zebra's client library.
       3             :  * Copyright (C) 1999 Kunihiro Ishiguro
       4             :  * Copyright (C) 2005 Andrew J. Schorr
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : 
       9             : #include "prefix.h"
      10             : #include "stream.h"
      11             : #include "buffer.h"
      12             : #include "network.h"
      13             : #include "vrf.h"
      14             : #include "vrf_int.h"
      15             : #include "if.h"
      16             : #include "log.h"
      17             : #include "frrevent.h"
      18             : #include "zclient.h"
      19             : #include "memory.h"
      20             : #include "table.h"
      21             : #include "nexthop.h"
      22             : #include "mpls.h"
      23             : #include "sockopt.h"
      24             : #include "pbr.h"
      25             : #include "tc.h"
      26             : #include "nexthop_group.h"
      27             : #include "lib_errors.h"
      28             : #include "srte.h"
      29             : #include "printfrr.h"
      30             : #include "srv6.h"
      31             : 
      32          12 : DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient");
      33          12 : DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs");
      34             : 
      35             : /* Zebra client events. */
      36             : enum zclient_event { ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT };
      37             : 
      38             : /* Prototype for event manager. */
      39             : static void zclient_event(enum zclient_event, struct zclient *);
      40             : 
      41             : static void zebra_interface_if_set_value(struct stream *s,
      42             :                                          struct interface *ifp);
      43             : 
      44             : struct zclient_options zclient_options_default = {.receive_notify = false,
      45             :                                                   .synchronous = false};
      46             : 
      47             : struct sockaddr_storage zclient_addr;
      48             : socklen_t zclient_addr_len;
      49             : 
      50             : /* This file local debug flag. */
      51             : static int zclient_debug;
      52             : 
      53             : /* Allocate zclient structure. */
      54           6 : struct zclient *zclient_new(struct event_loop *master,
      55             :                             struct zclient_options *opt,
      56             :                             zclient_handler *const *handlers, size_t n_handlers)
      57             : {
      58           6 :         struct zclient *zclient;
      59           6 :         size_t stream_size =
      60             :                 MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
      61             : 
      62           6 :         zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
      63             : 
      64           6 :         zclient->ibuf = stream_new(stream_size);
      65           6 :         zclient->obuf = stream_new(stream_size);
      66           6 :         zclient->wb = buffer_new(0);
      67           6 :         zclient->master = master;
      68             : 
      69           6 :         zclient->handlers = handlers;
      70           6 :         zclient->n_handlers = n_handlers;
      71             : 
      72           6 :         zclient->receive_notify = opt->receive_notify;
      73           6 :         zclient->synchronous = opt->synchronous;
      74             : 
      75           6 :         return zclient;
      76             : }
      77             : 
      78             : /* This function is only called when exiting, because
      79             :    many parts of the code do not check for I/O errors, so they could
      80             :    reference an invalid pointer if the structure was ever freed.
      81             : 
      82             :    Free zclient structure. */
      83           6 : void zclient_free(struct zclient *zclient)
      84             : {
      85           6 :         if (zclient->ibuf)
      86           6 :                 stream_free(zclient->ibuf);
      87           6 :         if (zclient->obuf)
      88           6 :                 stream_free(zclient->obuf);
      89           6 :         if (zclient->wb)
      90           6 :                 buffer_free(zclient->wb);
      91             : 
      92           6 :         XFREE(MTYPE_ZCLIENT, zclient);
      93           6 : }
      94             : 
      95          18 : unsigned short *redist_check_instance(struct redist_proto *red,
      96             :                                       unsigned short instance)
      97             : {
      98          18 :         struct listnode *node;
      99          18 :         unsigned short *id;
     100             : 
     101          18 :         if (!red->instances)
     102             :                 return NULL;
     103             : 
     104          12 :         for (ALL_LIST_ELEMENTS_RO(red->instances, node, id))
     105          12 :                 if (*id == instance)
     106          12 :                         return id;
     107             : 
     108             :         return NULL;
     109             : }
     110             : 
     111          12 : void redist_add_instance(struct redist_proto *red, unsigned short instance)
     112             : {
     113          12 :         unsigned short *in;
     114             : 
     115          12 :         red->enabled = 1;
     116             : 
     117          12 :         if (!red->instances)
     118          12 :                 red->instances = list_new();
     119             : 
     120          12 :         in = XMALLOC(MTYPE_REDIST_INST, sizeof(unsigned short));
     121          12 :         *in = instance;
     122          12 :         listnode_add(red->instances, in);
     123          12 : }
     124             : 
     125          18 : void redist_del_instance(struct redist_proto *red, unsigned short instance)
     126             : {
     127          18 :         unsigned short *id;
     128             : 
     129          18 :         id = redist_check_instance(red, instance);
     130          18 :         if (!id)
     131             :                 return;
     132             : 
     133          12 :         listnode_delete(red->instances, id);
     134          12 :         XFREE(MTYPE_REDIST_INST, id);
     135          12 :         if (!red->instances->count) {
     136          12 :                 red->enabled = 0;
     137          12 :                 list_delete(&red->instances);
     138             :         }
     139             : }
     140             : 
     141         576 : void redist_del_all_instances(struct redist_proto *red)
     142             : {
     143         576 :         struct listnode *ln, *nn;
     144         576 :         unsigned short *id;
     145             : 
     146         576 :         if (!red->instances)
     147             :                 return;
     148             : 
     149           0 :         for (ALL_LIST_ELEMENTS(red->instances, ln, nn, id))
     150           0 :                 redist_del_instance(red, *id);
     151             : }
     152             : 
     153             : /* Stop zebra client services. */
     154           6 : void zclient_stop(struct zclient *zclient)
     155             : {
     156           6 :         afi_t afi;
     157           6 :         int i;
     158             : 
     159           6 :         if (zclient_debug)
     160           0 :                 zlog_debug("zclient %p stopped", zclient);
     161             : 
     162             :         /* Stop threads. */
     163           6 :         EVENT_OFF(zclient->t_read);
     164           6 :         EVENT_OFF(zclient->t_connect);
     165           6 :         EVENT_OFF(zclient->t_write);
     166             : 
     167             :         /* Reset streams. */
     168           6 :         stream_reset(zclient->ibuf);
     169           6 :         stream_reset(zclient->obuf);
     170             : 
     171             :         /* Empty the write buffer. */
     172           6 :         buffer_reset(zclient->wb);
     173             : 
     174             :         /* Close socket. */
     175           6 :         if (zclient->sock >= 0) {
     176           6 :                 close(zclient->sock);
     177           6 :                 zclient->sock = -1;
     178             :         }
     179           6 :         zclient->fail = 0;
     180             : 
     181          24 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     182         594 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
     183         576 :                         vrf_bitmap_free(&zclient->redist[afi][i]);
     184         576 :                         zclient->redist[afi][i] = VRF_BITMAP_NULL;
     185             :                 }
     186          18 :                 redist_del_instance(
     187          18 :                         &zclient->mi_redist[afi][zclient->redist_default],
     188          18 :                         zclient->instance);
     189             : 
     190          18 :                 vrf_bitmap_free(&zclient->default_information[afi]);
     191          18 :                 zclient->default_information[afi] = VRF_BITMAP_NULL;
     192             :         }
     193           6 : }
     194             : 
     195           0 : void zclient_reset(struct zclient *zclient)
     196             : {
     197           0 :         afi_t afi;
     198             : 
     199           0 :         zclient_stop(zclient);
     200             : 
     201           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
     202           0 :                 redist_del_instance(
     203           0 :                         &zclient->mi_redist[afi][zclient->redist_default],
     204           0 :                         zclient->instance);
     205             : 
     206           0 :         zclient_init(zclient, zclient->redist_default, zclient->instance,
     207             :                      zclient->privs);
     208           0 : }
     209             : 
     210             : /**
     211             :  * Connect to zebra daemon.
     212             :  * @param zclient a pointer to zclient structure
     213             :  * @return socket fd just to make sure that connection established
     214             :  * @see zclient_init
     215             :  * @see zclient_new
     216             :  */
     217           6 : int zclient_socket_connect(struct zclient *zclient)
     218             : {
     219           6 :         int sock;
     220           6 :         int ret;
     221             : 
     222             :         /* We should think about IPv6 connection. */
     223           6 :         sock = socket(zclient_addr.ss_family, SOCK_STREAM, 0);
     224           6 :         if (sock < 0)
     225             :                 return -1;
     226             : 
     227           6 :         set_cloexec(sock);
     228           6 :         setsockopt_so_sendbuf(sock, 1048576);
     229             : 
     230             :         /* Connect to zebra. */
     231           6 :         ret = connect(sock, (struct sockaddr *)&zclient_addr, zclient_addr_len);
     232           6 :         if (ret < 0) {
     233           0 :                 if (zclient_debug)
     234           0 :                         zlog_debug("%s connect failure: %d(%s)", __func__,
     235             :                                    errno, safe_strerror(errno));
     236           0 :                 close(sock);
     237           0 :                 return -1;
     238             :         }
     239             : 
     240           6 :         zclient->sock = sock;
     241           6 :         return sock;
     242             : }
     243             : 
     244           0 : static enum zclient_send_status zclient_failed(struct zclient *zclient)
     245             : {
     246           0 :         zclient->fail++;
     247           0 :         zclient_stop(zclient);
     248           0 :         zclient_event(ZCLIENT_CONNECT, zclient);
     249           0 :         return ZCLIENT_SEND_FAILURE;
     250             : }
     251             : 
     252           0 : static void zclient_flush_data(struct event *thread)
     253             : {
     254           0 :         struct zclient *zclient = EVENT_ARG(thread);
     255             : 
     256           0 :         zclient->t_write = NULL;
     257           0 :         if (zclient->sock < 0)
     258             :                 return;
     259           0 :         switch (buffer_flush_available(zclient->wb, zclient->sock)) {
     260           0 :         case BUFFER_ERROR:
     261           0 :                 flog_err(
     262             :                         EC_LIB_ZAPI_SOCKET,
     263             :                         "%s: buffer_flush_available failed on zclient fd %d, closing",
     264             :                         __func__, zclient->sock);
     265           0 :                 zclient_failed(zclient);
     266           0 :                 return;
     267           0 :         case BUFFER_PENDING:
     268           0 :                 zclient->t_write = NULL;
     269           0 :                 event_add_write(zclient->master, zclient_flush_data, zclient,
     270             :                                 zclient->sock, &zclient->t_write);
     271           0 :                 break;
     272           0 :         case BUFFER_EMPTY:
     273           0 :                 if (zclient->zebra_buffer_write_ready)
     274           0 :                         (*zclient->zebra_buffer_write_ready)();
     275             :                 break;
     276             :         }
     277             : }
     278             : 
     279             : /*
     280             :  * Returns:
     281             :  * ZCLIENT_SEND_FAILED   - is a failure
     282             :  * ZCLIENT_SEND_SUCCESS  - means we sent data to zebra
     283             :  * ZCLIENT_SEND_BUFFERED - means we are buffering
     284             :  */
     285         130 : enum zclient_send_status zclient_send_message(struct zclient *zclient)
     286             : {
     287         130 :         if (zclient->sock < 0)
     288             :                 return ZCLIENT_SEND_FAILURE;
     289         130 :         switch (buffer_write(zclient->wb, zclient->sock,
     290         130 :                              STREAM_DATA(zclient->obuf),
     291         130 :                              stream_get_endp(zclient->obuf))) {
     292           0 :         case BUFFER_ERROR:
     293           0 :                 flog_err(EC_LIB_ZAPI_SOCKET,
     294             :                          "%s: buffer_write failed to zclient fd %d, closing",
     295             :                          __func__, zclient->sock);
     296           0 :                 return zclient_failed(zclient);
     297         130 :         case BUFFER_EMPTY:
     298         130 :                 EVENT_OFF(zclient->t_write);
     299             :                 return ZCLIENT_SEND_SUCCESS;
     300           0 :         case BUFFER_PENDING:
     301           0 :                 event_add_write(zclient->master, zclient_flush_data, zclient,
     302             :                                 zclient->sock, &zclient->t_write);
     303           0 :                 return ZCLIENT_SEND_BUFFERED;
     304             :         }
     305             : 
     306             :         /* should not get here */
     307             :         return ZCLIENT_SEND_SUCCESS;
     308             : }
     309             : 
     310             : /*
     311             :  * If we add more data to this structure please ensure that
     312             :  * struct zmsghdr in lib/zclient.h is updated as appropriate.
     313             :  */
     314         307 : void zclient_create_header(struct stream *s, uint16_t command, vrf_id_t vrf_id)
     315             : {
     316             :         /* length placeholder, caller can update */
     317         307 :         stream_putw(s, ZEBRA_HEADER_SIZE);
     318         307 :         stream_putc(s, ZEBRA_HEADER_MARKER);
     319         307 :         stream_putc(s, ZSERV_VERSION);
     320         307 :         stream_putl(s, vrf_id);
     321         307 :         stream_putw(s, command);
     322         307 : }
     323             : 
     324           2 : int zclient_read_header(struct stream *s, int sock, uint16_t *size,
     325             :                         uint8_t *marker, uint8_t *version, vrf_id_t *vrf_id,
     326             :                         uint16_t *cmd)
     327             : {
     328           2 :         if (stream_read(s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE)
     329             :                 return -1;
     330             : 
     331           2 :         STREAM_GETW(s, *size);
     332           2 :         *size -= ZEBRA_HEADER_SIZE;
     333           2 :         STREAM_GETC(s, *marker);
     334           2 :         STREAM_GETC(s, *version);
     335           2 :         STREAM_GETL(s, *vrf_id);
     336           2 :         STREAM_GETW(s, *cmd);
     337             : 
     338           2 :         if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) {
     339           0 :                 flog_err(
     340             :                         EC_LIB_ZAPI_MISSMATCH,
     341             :                         "%s: socket %d version mismatch, marker %d, version %d",
     342             :                         __func__, sock, *marker, *version);
     343           0 :                 return -1;
     344             :         }
     345             : 
     346           2 :         if (*size && stream_read(s, sock, *size) != *size)
     347             :                 return -1;
     348             : 
     349             :         return 0;
     350             : stream_failure:
     351             :         return -1;
     352             : }
     353             : 
     354         264 : bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr)
     355             : {
     356         264 :         STREAM_GETW(zmsg, hdr->length);
     357         264 :         STREAM_GETC(zmsg, hdr->marker);
     358         264 :         STREAM_GETC(zmsg, hdr->version);
     359         264 :         STREAM_GETL(zmsg, hdr->vrf_id);
     360         264 :         STREAM_GETW(zmsg, hdr->command);
     361         264 :         return true;
     362             : stream_failure:
     363             :         return false;
     364             : }
     365             : 
     366             : /* Send simple Zebra message. */
     367           8 : static enum zclient_send_status zebra_message_send(struct zclient *zclient,
     368             :                                                    int command, vrf_id_t vrf_id)
     369             : {
     370           8 :         struct stream *s;
     371             : 
     372             :         /* Get zclient output buffer. */
     373           8 :         s = zclient->obuf;
     374           8 :         stream_reset(s);
     375             : 
     376             :         /* Send very simple command only Zebra message. */
     377           8 :         zclient_create_header(s, command, vrf_id);
     378             : 
     379           8 :         return zclient_send_message(zclient);
     380             : }
     381             : 
     382           6 : enum zclient_send_status zclient_send_hello(struct zclient *zclient)
     383             : {
     384           6 :         struct stream *s;
     385             : 
     386           6 :         if (zclient->redist_default || zclient->synchronous) {
     387           6 :                 s = zclient->obuf;
     388           6 :                 stream_reset(s);
     389             : 
     390             :                 /* The VRF ID in the HELLO message is always 0. */
     391           6 :                 zclient_create_header(s, ZEBRA_HELLO, VRF_DEFAULT);
     392           6 :                 stream_putc(s, zclient->redist_default);
     393           6 :                 stream_putw(s, zclient->instance);
     394           6 :                 stream_putl(s, zclient->session_id);
     395           6 :                 if (zclient->receive_notify)
     396           0 :                         stream_putc(s, 1);
     397             :                 else
     398           6 :                         stream_putc(s, 0);
     399           6 :                 if (zclient->synchronous)
     400           2 :                         stream_putc(s, 1);
     401             :                 else
     402           4 :                         stream_putc(s, 0);
     403             : 
     404           6 :                 stream_putw_at(s, 0, stream_get_endp(s));
     405           6 :                 return zclient_send_message(zclient);
     406             :         }
     407             : 
     408             :         return ZCLIENT_SEND_SUCCESS;
     409             : }
     410             : 
     411           4 : enum zclient_send_status zclient_send_vrf_label(struct zclient *zclient,
     412             :                                                 vrf_id_t vrf_id, afi_t afi,
     413             :                                                 mpls_label_t label,
     414             :                                                 enum lsp_types_t ltype)
     415             : {
     416           4 :         struct stream *s;
     417             : 
     418           4 :         s = zclient->obuf;
     419           4 :         stream_reset(s);
     420             : 
     421           4 :         zclient_create_header(s, ZEBRA_VRF_LABEL, vrf_id);
     422           4 :         stream_putl(s, label);
     423           4 :         stream_putc(s, afi);
     424           4 :         stream_putc(s, ltype);
     425           4 :         stream_putw_at(s, 0, stream_get_endp(s));
     426           4 :         return zclient_send_message(zclient);
     427             : }
     428             : 
     429           0 : enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
     430             :                 const struct in6_addr *sid, vrf_id_t vrf_id,
     431             :                 enum seg6local_action_t action,
     432             :                 const struct seg6local_context *context)
     433             : {
     434           0 :         struct prefix_ipv6 p = {};
     435           0 :         struct zapi_route api = {};
     436           0 :         struct zapi_nexthop *znh;
     437           0 :         struct interface *ifp;
     438             : 
     439           0 :         ifp = if_get_vrf_loopback(vrf_id);
     440           0 :         if (ifp == NULL)
     441             :                 return ZCLIENT_SEND_FAILURE;
     442             : 
     443           0 :         p.family = AF_INET6;
     444           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     445           0 :         p.prefix = *sid;
     446             : 
     447           0 :         api.vrf_id = VRF_DEFAULT;
     448           0 :         api.type = zclient->redist_default;
     449           0 :         api.instance = 0;
     450           0 :         api.safi = SAFI_UNICAST;
     451           0 :         memcpy(&api.prefix, &p, sizeof(p));
     452             : 
     453           0 :         if (action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
     454           0 :                 return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
     455             : 
     456           0 :         SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
     457           0 :         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
     458             : 
     459           0 :         znh = &api.nexthops[0];
     460             : 
     461           0 :         memset(znh, 0, sizeof(*znh));
     462             : 
     463           0 :         znh->type = NEXTHOP_TYPE_IFINDEX;
     464           0 :         znh->ifindex = ifp->ifindex;
     465           0 :         SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
     466           0 :         znh->seg6local_action = action;
     467           0 :         memcpy(&znh->seg6local_ctx, context, sizeof(struct seg6local_context));
     468             : 
     469           0 :         api.nexthop_num = 1;
     470             : 
     471           0 :         return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
     472             : }
     473             : 
     474             : /* Send register requests to zebra daemon for the information in a VRF. */
     475           2 : void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
     476             : {
     477           2 :         int i;
     478           2 :         afi_t afi;
     479             : 
     480             :         /* If not connected to the zebra yet. */
     481           2 :         if (zclient->sock < 0)
     482             :                 return;
     483             : 
     484           2 :         if (zclient_debug)
     485           0 :                 zlog_debug("%s: send register messages for VRF %u", __func__,
     486             :                            vrf_id);
     487             : 
     488             :         /* We need router-id information. */
     489           2 :         zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_ADD, AFI_IP,
     490             :                                       vrf_id);
     491             : 
     492             :         /* We need interface information. */
     493           2 :         zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id);
     494             : 
     495             :         /* Set unwanted redistribute route. */
     496          10 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
     497           6 :                 vrf_bitmap_set(&zclient->redist[afi][zclient->redist_default],
     498             :                                vrf_id);
     499             : 
     500             :         /* Flush all redistribute request. */
     501           2 :         if (vrf_id == VRF_DEFAULT) {
     502           8 :                 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     503         198 :                         for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
     504         192 :                                 if (!zclient->mi_redist[afi][i].enabled)
     505         186 :                                         continue;
     506             : 
     507           6 :                                 struct listnode *node;
     508           6 :                                 unsigned short *id;
     509             : 
     510          18 :                                 for (ALL_LIST_ELEMENTS_RO(
     511             :                                              zclient->mi_redist[afi][i]
     512             :                                                      .instances,
     513             :                                              node, id))
     514           6 :                                         if (!(i == zclient->redist_default
     515           6 :                                               && *id == zclient->instance))
     516           0 :                                                 zebra_redistribute_send(
     517             :                                                         ZEBRA_REDISTRIBUTE_ADD,
     518           0 :                                                         zclient, afi, i, *id,
     519             :                                                         VRF_DEFAULT);
     520             :                         }
     521             :                 }
     522             :         }
     523             : 
     524             :         /* Resend all redistribute request. */
     525           8 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     526         198 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
     527         378 :                         if (i != zclient->redist_default &&
     528         186 :                             vrf_bitmap_check(&zclient->redist[afi][i], vrf_id))
     529           0 :                                 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD,
     530             :                                                         zclient, afi, i, 0,
     531             :                                                         vrf_id);
     532             : 
     533             :                 /* If default information is needed. */
     534           6 :                 if (vrf_bitmap_check(&zclient->default_information[afi],
     535             :                                      vrf_id))
     536           0 :                         zebra_redistribute_default_send(
     537             :                                 ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi,
     538             :                                 vrf_id);
     539             :         }
     540             : }
     541             : 
     542             : /* Send unregister requests to zebra daemon for the information in a VRF. */
     543           2 : void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
     544             : {
     545           2 :         int i;
     546           2 :         afi_t afi;
     547             : 
     548             :         /* If not connected to the zebra yet. */
     549           2 :         if (zclient->sock < 0)
     550             :                 return;
     551             : 
     552           2 :         if (zclient_debug)
     553           0 :                 zlog_debug("%s: send deregister messages for VRF %u", __func__,
     554             :                            vrf_id);
     555             : 
     556             :         /* We need router-id information. */
     557           2 :         zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_DELETE, AFI_IP,
     558             :                                       vrf_id);
     559             : 
     560           2 :         zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id);
     561             : 
     562             :         /* Set unwanted redistribute route. */
     563          10 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
     564           6 :                 vrf_bitmap_unset(&zclient->redist[afi][zclient->redist_default],
     565             :                                  vrf_id);
     566             : 
     567             :         /* Flush all redistribute request. */
     568           2 :         if (vrf_id == VRF_DEFAULT) {
     569           8 :                 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     570         198 :                         for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
     571         192 :                                 if (!zclient->mi_redist[afi][i].enabled)
     572         186 :                                         continue;
     573             : 
     574           6 :                                 struct listnode *node;
     575           6 :                                 unsigned short *id;
     576             : 
     577          18 :                                 for (ALL_LIST_ELEMENTS_RO(
     578             :                                              zclient->mi_redist[afi][i]
     579             :                                                      .instances,
     580             :                                              node, id))
     581           6 :                                         if (!(i == zclient->redist_default
     582           6 :                                               && *id == zclient->instance))
     583           0 :                                                 zebra_redistribute_send(
     584             :                                                         ZEBRA_REDISTRIBUTE_DELETE,
     585           0 :                                                         zclient, afi, i, *id,
     586             :                                                         VRF_DEFAULT);
     587             :                         }
     588             :                 }
     589             :         }
     590             : 
     591             :         /* Flush all redistribute request. */
     592           8 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     593         198 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
     594         378 :                         if (i != zclient->redist_default &&
     595         186 :                             vrf_bitmap_check(&zclient->redist[afi][i], vrf_id))
     596           0 :                                 zebra_redistribute_send(
     597             :                                         ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
     598             :                                         i, 0, vrf_id);
     599             : 
     600             :                 /* If default information is needed. */
     601           6 :                 if (vrf_bitmap_check(&zclient->default_information[afi],
     602             :                                      vrf_id))
     603           0 :                         zebra_redistribute_default_send(
     604             :                                 ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi,
     605             :                                 vrf_id);
     606             :         }
     607             : }
     608             : 
     609             : enum zclient_send_status
     610           4 : zclient_send_router_id_update(struct zclient *zclient,
     611             :                               zebra_message_types_t type, afi_t afi,
     612             :                               vrf_id_t vrf_id)
     613             : {
     614           4 :         struct stream *s = zclient->obuf;
     615           4 :         stream_reset(s);
     616           4 :         zclient_create_header(s, type, vrf_id);
     617           4 :         stream_putw(s, afi);
     618           4 :         stream_putw_at(s, 0, stream_get_endp(s));
     619           4 :         return zclient_send_message(zclient);
     620             : }
     621             : 
     622             : /* Send request to zebra daemon to start or stop RA. */
     623             : enum zclient_send_status
     624           2 : zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
     625             :                                 struct interface *ifp, int enable,
     626             :                                 uint32_t ra_interval)
     627             : {
     628           2 :         struct stream *s;
     629             : 
     630             :         /* If not connected to the zebra yet. */
     631           2 :         if (zclient->sock < 0)
     632             :                 return ZCLIENT_SEND_FAILURE;
     633             : 
     634             :         /* Form and send message. */
     635           2 :         s = zclient->obuf;
     636           2 :         stream_reset(s);
     637             : 
     638           2 :         if (enable)
     639           2 :                 zclient_create_header(s, ZEBRA_INTERFACE_ENABLE_RADV, vrf_id);
     640             :         else
     641           0 :                 zclient_create_header(s, ZEBRA_INTERFACE_DISABLE_RADV, vrf_id);
     642             : 
     643           2 :         stream_putl(s, ifp->ifindex);
     644           2 :         stream_putl(s, ra_interval);
     645             : 
     646           2 :         stream_putw_at(s, 0, stream_get_endp(s));
     647             : 
     648           2 :         return zclient_send_message(zclient);
     649             : }
     650             : 
     651             : enum zclient_send_status
     652           0 : zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
     653             :                                  struct interface *ifp, bool down)
     654             : {
     655           0 :         struct stream *s;
     656             : 
     657           0 :         if (zclient->sock < 0)
     658             :                 return ZCLIENT_SEND_FAILURE;
     659             : 
     660           0 :         s = zclient->obuf;
     661           0 :         stream_reset(s);
     662           0 :         zclient_create_header(s, ZEBRA_INTERFACE_SET_PROTODOWN, vrf_id);
     663           0 :         stream_putl(s, ifp->ifindex);
     664           0 :         stream_putc(s, !!down);
     665           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     666           0 :         return zclient_send_message(zclient);
     667             : }
     668             : 
     669             : /* Make connection to zebra daemon. */
     670           4 : int zclient_start(struct zclient *zclient)
     671             : {
     672           4 :         if (zclient_debug)
     673           0 :                 zlog_info("zclient_start is called");
     674             : 
     675             :         /* If already connected to the zebra. */
     676           4 :         if (zclient->sock >= 0)
     677             :                 return 0;
     678             : 
     679             :         /* Check connect thread. */
     680           4 :         if (zclient->t_connect)
     681             :                 return 0;
     682             : 
     683           4 :         if (zclient_socket_connect(zclient) < 0) {
     684           0 :                 if (zclient_debug)
     685           0 :                         zlog_debug("zclient connection fail");
     686           0 :                 zclient->fail++;
     687           0 :                 zclient_event(ZCLIENT_CONNECT, zclient);
     688           0 :                 return -1;
     689             :         }
     690             : 
     691           4 :         if (set_nonblocking(zclient->sock) < 0)
     692           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "%s: set_nonblocking(%d) failed",
     693             :                          __func__, zclient->sock);
     694             : 
     695             :         /* Clear fail count. */
     696           4 :         zclient->fail = 0;
     697           4 :         if (zclient_debug)
     698           0 :                 zlog_debug("zclient connect success with socket [%d]",
     699             :                            zclient->sock);
     700             : 
     701             :         /* Create read thread. */
     702           4 :         zclient_event(ZCLIENT_READ, zclient);
     703             : 
     704           4 :         zclient_send_hello(zclient);
     705             : 
     706           4 :         zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, VRF_DEFAULT);
     707             : 
     708             :         /* Inform the successful connection. */
     709           4 :         if (zclient->zebra_connected)
     710           2 :                 (*zclient->zebra_connected)(zclient);
     711             : 
     712             :         return 0;
     713             : }
     714             : 
     715             : /* Initialize zebra client.  Argument redist_default is unwanted
     716             :    redistribute route type. */
     717           4 : void zclient_init(struct zclient *zclient, int redist_default,
     718             :                   unsigned short instance, struct zebra_privs_t *privs)
     719             : {
     720           4 :         int afi, i;
     721             : 
     722             :         /* Set -1 to the default socket value. */
     723           4 :         zclient->sock = -1;
     724           4 :         zclient->privs = privs;
     725             : 
     726             :         /* Clear redistribution flags. */
     727          16 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
     728         396 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
     729         384 :                         vrf_bitmap_init(&zclient->redist[afi][i]);
     730             : 
     731             :         /* Set unwanted redistribute route.  bgpd does not need BGP route
     732             :            redistribution. */
     733           4 :         zclient->redist_default = redist_default;
     734           4 :         zclient->instance = instance;
     735             :         /* Pending: make afi(s) an arg. */
     736          16 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
     737          12 :                 redist_add_instance(&zclient->mi_redist[afi][redist_default],
     738             :                                     instance);
     739             : 
     740             :                 /* Set default-information redistribute to zero. */
     741          12 :                 vrf_bitmap_init(&zclient->default_information[afi]);
     742             :         }
     743             : 
     744           4 :         if (zclient_debug)
     745           0 :                 zlog_debug("scheduling zclient connection");
     746             : 
     747           4 :         zclient_event(ZCLIENT_SCHEDULE, zclient);
     748           4 : }
     749             : 
     750             : /* This function is a wrapper function for calling zclient_start from
     751             :    timer or event thread. */
     752           4 : static void zclient_connect(struct event *t)
     753             : {
     754           4 :         struct zclient *zclient;
     755             : 
     756           4 :         zclient = EVENT_ARG(t);
     757           4 :         zclient->t_connect = NULL;
     758             : 
     759           4 :         if (zclient_debug)
     760           0 :                 zlog_debug("zclient_connect is called");
     761             : 
     762           4 :         zclient_start(zclient);
     763           4 : }
     764             : 
     765           6 : enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command,
     766             :                                           const struct prefix *p, safi_t safi,
     767             :                                           bool connected, bool resolve_via_def,
     768             :                                           vrf_id_t vrf_id)
     769             : {
     770           6 :         struct stream *s;
     771             : 
     772           6 :         s = zclient->obuf;
     773           6 :         stream_reset(s);
     774           6 :         zclient_create_header(s, command, vrf_id);
     775           6 :         stream_putc(s, (connected) ? 1 : 0);
     776           6 :         stream_putc(s, (resolve_via_def) ? 1 : 0);
     777           6 :         stream_putw(s, safi);
     778           6 :         stream_putw(s, PREFIX_FAMILY(p));
     779           6 :         stream_putc(s, p->prefixlen);
     780           6 :         switch (PREFIX_FAMILY(p)) {
     781           0 :         case AF_INET:
     782           0 :                 stream_put_in_addr(s, &p->u.prefix4);
     783           0 :                 break;
     784           6 :         case AF_INET6:
     785           6 :                 stream_put(s, &(p->u.prefix6), 16);
     786           6 :                 break;
     787             :         default:
     788             :                 break;
     789             :         }
     790           6 :         stream_putw_at(s, 0, stream_get_endp(s));
     791             : 
     792           6 :         return zclient_send_message(zclient);
     793             : }
     794             : 
     795             : /*
     796             :  * "xdr_encode"-like interface that allows daemon (client) to send
     797             :  * a message to zebra server for a route that needs to be
     798             :  * added/deleted to the kernel. Info about the route is specified
     799             :  * by the caller in a struct zapi_route. zapi_route_encode() then writes
     800             :  * the info down the zclient socket using the stream_* functions.
     801             :  *
     802             :  * The corresponding read ("xdr_decode") function on the server
     803             :  * side is zapi_route_decode().
     804             :  *
     805             :  * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
     806             :  * byte value.
     807             :  *
     808             :  * If ZAPI_MESSAGE_METRIC is set, the metric value is written as a 4
     809             :  * byte value.
     810             :  *
     811             :  * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value
     812             :  *
     813             :  * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value
     814             :  *
     815             :  * XXX: No attention paid to alignment.
     816             :  */
     817             : enum zclient_send_status
     818           4 : zclient_route_send(uint8_t cmd, struct zclient *zclient, struct zapi_route *api)
     819             : {
     820           4 :         if (zapi_route_encode(cmd, zclient->obuf, api) < 0)
     821             :                 return ZCLIENT_SEND_FAILURE;
     822           4 :         return zclient_send_message(zclient);
     823             : }
     824             : 
     825           0 : static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1,
     826             :                                    const struct zapi_nexthop *next2)
     827             : {
     828           0 :         if (next1->label_num > next2->label_num)
     829             :                 return 1;
     830             : 
     831           0 :         if (next1->label_num < next2->label_num)
     832             :                 return -1;
     833             : 
     834           0 :         return memcmp(next1->labels, next2->labels, next1->label_num);
     835             : }
     836             : 
     837           0 : static int zapi_nexthop_srv6_cmp(const struct zapi_nexthop *next1,
     838             :                                  const struct zapi_nexthop *next2)
     839             : {
     840           0 :         int ret = 0;
     841             : 
     842           0 :         ret = memcmp(&next1->seg6_segs, &next2->seg6_segs,
     843             :                      sizeof(struct in6_addr));
     844           0 :         if (ret != 0)
     845             :                 return ret;
     846             : 
     847           0 :         if (next1->seg6local_action > next2->seg6local_action)
     848             :                 return 1;
     849             : 
     850           0 :         if (next1->seg6local_action < next2->seg6local_action)
     851             :                 return -1;
     852             : 
     853           0 :         return memcmp(&next1->seg6local_ctx, &next2->seg6local_ctx,
     854             :                       sizeof(struct seg6local_context));
     855             : }
     856             : 
     857           2 : static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
     858             :                                       const struct zapi_nexthop *next2)
     859             : {
     860           2 :         int ret = 0;
     861             : 
     862           2 :         if (next1->vrf_id < next2->vrf_id)
     863             :                 return -1;
     864             : 
     865           2 :         if (next1->vrf_id > next2->vrf_id)
     866             :                 return 1;
     867             : 
     868           2 :         if (next1->type < next2->type)
     869             :                 return -1;
     870             : 
     871           2 :         if (next1->type > next2->type)
     872             :                 return 1;
     873             : 
     874           2 :         if (next1->weight < next2->weight)
     875             :                 return -1;
     876             : 
     877           2 :         if (next1->weight > next2->weight)
     878             :                 return 1;
     879             : 
     880           2 :         switch (next1->type) {
     881           0 :         case NEXTHOP_TYPE_IPV4:
     882             :         case NEXTHOP_TYPE_IPV6:
     883           0 :                 ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
     884             :                                          &next2->gate);
     885           0 :                 if (ret != 0)
     886             :                         return ret;
     887             :                 break;
     888           2 :         case NEXTHOP_TYPE_IPV4_IFINDEX:
     889             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
     890           2 :                 ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
     891             :                                          &next2->gate);
     892           2 :                 if (ret != 0)
     893             :                         return ret;
     894           0 :                 fallthrough;
     895             :         case NEXTHOP_TYPE_IFINDEX:
     896           0 :                 if (next1->ifindex < next2->ifindex)
     897             :                         return -1;
     898             : 
     899           0 :                 if (next1->ifindex > next2->ifindex)
     900             :                         return 1;
     901             :                 break;
     902           0 :         case NEXTHOP_TYPE_BLACKHOLE:
     903           0 :                 if (next1->bh_type < next2->bh_type)
     904             :                         return -1;
     905             : 
     906           0 :                 if (next1->bh_type > next2->bh_type)
     907             :                         return 1;
     908             :                 break;
     909             :         }
     910             : 
     911           0 :         if (next1->srte_color < next2->srte_color)
     912             :                 return -1;
     913           0 :         if (next1->srte_color > next2->srte_color)
     914             :                 return 1;
     915             : 
     916           0 :         if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
     917           0 :             CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
     918             : 
     919           0 :                 if (!CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
     920           0 :                     CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
     921             :                         return -1;
     922             : 
     923           0 :                 if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
     924           0 :                     !CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
     925             :                         return 1;
     926             : 
     927           0 :                 if (next1->backup_num > 0 || next2->backup_num > 0) {
     928             : 
     929           0 :                         if (next1->backup_num < next2->backup_num)
     930             :                                 return -1;
     931             : 
     932           0 :                         if (next1->backup_num > next2->backup_num)
     933             :                                 return 1;
     934             : 
     935           0 :                         ret = memcmp(next1->backup_idx,
     936           0 :                                      next2->backup_idx, next1->backup_num);
     937           0 :                         if (ret != 0)
     938             :                                 return ret;
     939             :                 }
     940             :         }
     941             : 
     942             :         return 0;
     943             : }
     944             : 
     945           2 : static int zapi_nexthop_cmp(const void *item1, const void *item2)
     946             : {
     947           2 :         int ret = 0;
     948             : 
     949           2 :         const struct zapi_nexthop *next1 = item1;
     950           2 :         const struct zapi_nexthop *next2 = item2;
     951             : 
     952           2 :         ret = zapi_nexthop_cmp_no_labels(next1, next2);
     953           2 :         if (ret != 0)
     954             :                 return ret;
     955             : 
     956           0 :         ret = zapi_nexthop_labels_cmp(next1, next2);
     957           0 :         if (ret != 0)
     958             :                 return ret;
     959             : 
     960           0 :         ret = zapi_nexthop_srv6_cmp(next1, next2);
     961             : 
     962           0 :         return ret;
     963             : }
     964             : 
     965           9 : static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
     966             :                                     uint16_t nexthop_num)
     967             : {
     968           9 :         qsort(nh_grp, nexthop_num, sizeof(struct zapi_nexthop),
     969             :               &zapi_nexthop_cmp);
     970             : }
     971             : 
     972             : /*
     973             :  * Encode a single zapi nexthop
     974             :  */
     975          15 : int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
     976             :                         uint32_t api_flags, uint32_t api_message)
     977             : {
     978          15 :         int i, ret = 0;
     979          15 :         int nh_flags = api_nh->flags;
     980             : 
     981          15 :         stream_putl(s, api_nh->vrf_id);
     982          15 :         stream_putc(s, api_nh->type);
     983             : 
     984             :         /* If needed, set 'labelled nexthop' flag */
     985          15 :         if (api_nh->label_num > 0) {
     986           0 :                 SET_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_LABEL);
     987             : 
     988             :                 /* Validate label count */
     989           0 :                 if (api_nh->label_num > MPLS_MAX_LABELS) {
     990           0 :                         ret = -1;
     991           0 :                         goto done;
     992             :                 }
     993             :         }
     994             : 
     995             :         /* If present, set 'weight' flag before encoding flags */
     996          15 :         if (api_nh->weight)
     997           0 :                 SET_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_WEIGHT);
     998             : 
     999             :         /* Note that we're only encoding a single octet */
    1000          15 :         stream_putc(s, nh_flags);
    1001             : 
    1002          15 :         switch (api_nh->type) {
    1003           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    1004           0 :                 stream_putc(s, api_nh->bh_type);
    1005           0 :                 break;
    1006           0 :         case NEXTHOP_TYPE_IPV4:
    1007             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1008           0 :                 stream_put_in_addr(s, &api_nh->gate.ipv4);
    1009           0 :                 stream_putl(s, api_nh->ifindex);
    1010           0 :                 break;
    1011          11 :         case NEXTHOP_TYPE_IFINDEX:
    1012          11 :                 stream_putl(s, api_nh->ifindex);
    1013          11 :                 break;
    1014           4 :         case NEXTHOP_TYPE_IPV6:
    1015             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1016           4 :                 stream_write(s, (uint8_t *)&api_nh->gate.ipv6,
    1017             :                              16);
    1018           4 :                 stream_putl(s, api_nh->ifindex);
    1019           4 :                 break;
    1020             :         }
    1021             : 
    1022             :         /* We only encode labels if we have >0 - we use
    1023             :          * the per-nexthop flag above to signal that the count
    1024             :          * is present in the payload.
    1025             :          */
    1026          15 :         if (api_nh->label_num > 0) {
    1027           0 :                 stream_putc(s, api_nh->label_num);
    1028           0 :                 stream_putc(s, api_nh->label_type);
    1029           0 :                 stream_put(s, &api_nh->labels[0],
    1030           0 :                            api_nh->label_num * sizeof(mpls_label_t));
    1031             :         }
    1032             : 
    1033          15 :         if (api_nh->weight)
    1034           0 :                 stream_putl(s, api_nh->weight);
    1035             : 
    1036             :         /* Router MAC for EVPN routes. */
    1037          15 :         if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
    1038           0 :                 stream_put(s, &(api_nh->rmac),
    1039             :                            sizeof(struct ethaddr));
    1040             : 
    1041             :         /* Color for Segment Routing TE. */
    1042          15 :         if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
    1043           0 :                 stream_putl(s, api_nh->srte_color);
    1044             : 
    1045             :         /* Index of backup nexthop */
    1046          15 :         if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
    1047             :                 /* Validate backup count */
    1048           0 :                 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
    1049           0 :                         ret = -1;
    1050           0 :                         goto done;
    1051             :                 }
    1052             : 
    1053           0 :                 stream_putc(s, api_nh->backup_num);
    1054           0 :                 for (i = 0; i < api_nh->backup_num; i++)
    1055           0 :                         stream_putc(s, api_nh->backup_idx[i]);
    1056             :         }
    1057             : 
    1058          15 :         if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
    1059           0 :                 stream_putl(s, api_nh->seg6local_action);
    1060           0 :                 stream_write(s, &api_nh->seg6local_ctx,
    1061             :                              sizeof(struct seg6local_context));
    1062             :         }
    1063             : 
    1064          15 :         if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6)) {
    1065           0 :                 stream_putc(s, api_nh->seg_num);
    1066           0 :                 stream_put(s, &api_nh->seg6_segs[0],
    1067           0 :                            api_nh->seg_num * sizeof(struct in6_addr));
    1068             :         }
    1069          15 : done:
    1070          15 :         return ret;
    1071             : }
    1072             : 
    1073           0 : int zapi_srv6_locator_chunk_encode(struct stream *s,
    1074             :                                    const struct srv6_locator_chunk *c)
    1075             : {
    1076           0 :         stream_putw(s, strlen(c->locator_name));
    1077           0 :         stream_put(s, c->locator_name, strlen(c->locator_name));
    1078           0 :         stream_putw(s, c->prefix.prefixlen);
    1079           0 :         stream_put(s, &c->prefix.prefix, sizeof(c->prefix.prefix));
    1080           0 :         stream_putc(s, c->block_bits_length);
    1081           0 :         stream_putc(s, c->node_bits_length);
    1082           0 :         stream_putc(s, c->function_bits_length);
    1083           0 :         stream_putc(s, c->argument_bits_length);
    1084           0 :         stream_putc(s, c->flags);
    1085           0 :         return 0;
    1086             : }
    1087             : 
    1088           0 : int zapi_srv6_locator_chunk_decode(struct stream *s,
    1089             :                                    struct srv6_locator_chunk *c)
    1090             : {
    1091           0 :         uint16_t len = 0;
    1092             : 
    1093           0 :         c->prefix.family = AF_INET6;
    1094             : 
    1095           0 :         STREAM_GETW(s, len);
    1096           0 :         if (len > SRV6_LOCNAME_SIZE)
    1097           0 :                 goto stream_failure;
    1098             : 
    1099           0 :         STREAM_GET(c->locator_name, s, len);
    1100           0 :         STREAM_GETW(s, c->prefix.prefixlen);
    1101           0 :         STREAM_GET(&c->prefix.prefix, s, sizeof(c->prefix.prefix));
    1102           0 :         STREAM_GETC(s, c->block_bits_length);
    1103           0 :         STREAM_GETC(s, c->node_bits_length);
    1104           0 :         STREAM_GETC(s, c->function_bits_length);
    1105           0 :         STREAM_GETC(s, c->argument_bits_length);
    1106           0 :         STREAM_GETC(s, c->flags);
    1107           0 :         return 0;
    1108             : 
    1109             : stream_failure:
    1110             :         return -1;
    1111             : }
    1112             : 
    1113           0 : int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
    1114             : {
    1115           0 :         stream_putw(s, strlen(l->name));
    1116           0 :         stream_put(s, l->name, strlen(l->name));
    1117           0 :         stream_putw(s, l->prefix.prefixlen);
    1118           0 :         stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
    1119           0 :         return 0;
    1120             : }
    1121             : 
    1122           0 : int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
    1123             : {
    1124           0 :         uint16_t len = 0;
    1125             : 
    1126           0 :         STREAM_GETW(s, len);
    1127           0 :         if (len > SRV6_LOCNAME_SIZE)
    1128           0 :                 goto stream_failure;
    1129             : 
    1130           0 :         STREAM_GET(l->name, s, len);
    1131           0 :         STREAM_GETW(s, l->prefix.prefixlen);
    1132           0 :         STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
    1133           0 :         l->prefix.family = AF_INET6;
    1134           0 :         return 0;
    1135             : 
    1136             : stream_failure:
    1137             :         return -1;
    1138             : }
    1139             : 
    1140           0 : static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
    1141             : {
    1142           0 :         int i;
    1143             : 
    1144           0 :         if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) {
    1145           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1146             :                          "%s: Specified zapi NHG command (%d) doesn't exist",
    1147             :                          __func__, cmd);
    1148           0 :                 return -1;
    1149             :         }
    1150             : 
    1151           0 :         if (api_nhg->nexthop_num >= MULTIPATH_NUM ||
    1152           0 :             api_nhg->backup_nexthop_num >= MULTIPATH_NUM) {
    1153           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1154             :                          "%s: zapi NHG encode with invalid input", __func__);
    1155           0 :                 return -1;
    1156             :         }
    1157             : 
    1158           0 :         stream_reset(s);
    1159           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    1160             : 
    1161           0 :         stream_putw(s, api_nhg->proto);
    1162           0 :         stream_putl(s, api_nhg->id);
    1163             : 
    1164           0 :         stream_putw(s, api_nhg->resilience.buckets);
    1165           0 :         stream_putl(s, api_nhg->resilience.idle_timer);
    1166           0 :         stream_putl(s, api_nhg->resilience.unbalanced_timer);
    1167             : 
    1168           0 :         if (cmd == ZEBRA_NHG_ADD) {
    1169             :                 /* Nexthops */
    1170           0 :                 zapi_nexthop_group_sort(api_nhg->nexthops,
    1171           0 :                                         api_nhg->nexthop_num);
    1172             : 
    1173           0 :                 stream_putw(s, api_nhg->nexthop_num);
    1174             : 
    1175           0 :                 for (i = 0; i < api_nhg->nexthop_num; i++)
    1176           0 :                         zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0);
    1177             : 
    1178             :                 /* Backup nexthops */
    1179           0 :                 stream_putw(s, api_nhg->backup_nexthop_num);
    1180             : 
    1181           0 :                 for (i = 0; i < api_nhg->backup_nexthop_num; i++)
    1182           0 :                         zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0,
    1183             :                                             0);
    1184             :         }
    1185             : 
    1186           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1187             : 
    1188           0 :         return 0;
    1189             : }
    1190             : 
    1191           0 : enum zclient_send_status zclient_nhg_send(struct zclient *zclient, int cmd,
    1192             :                                           struct zapi_nhg *api_nhg)
    1193             : {
    1194           0 :         api_nhg->proto = zclient->redist_default;
    1195             : 
    1196           0 :         if (zapi_nhg_encode(zclient->obuf, cmd, api_nhg))
    1197             :                 return -1;
    1198             : 
    1199           0 :         return zclient_send_message(zclient);
    1200             : }
    1201             : 
    1202          11 : int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
    1203             : {
    1204          11 :         struct zapi_nexthop *api_nh;
    1205          11 :         int i;
    1206          11 :         int psize;
    1207             : 
    1208          11 :         stream_reset(s);
    1209          11 :         zclient_create_header(s, cmd, api->vrf_id);
    1210             : 
    1211          11 :         if (api->type >= ZEBRA_ROUTE_MAX) {
    1212           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1213             :                          "%s: Specified route type (%u) is not a legal value",
    1214             :                          __func__, api->type);
    1215           0 :                 return -1;
    1216             :         }
    1217          11 :         stream_putc(s, api->type);
    1218             : 
    1219          11 :         stream_putw(s, api->instance);
    1220          11 :         stream_putl(s, api->flags);
    1221          11 :         stream_putl(s, api->message);
    1222             : 
    1223          11 :         if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
    1224           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1225             :                          "%s: Specified route SAFI (%u) is not a legal value",
    1226             :                          __func__, api->safi);
    1227           0 :                 return -1;
    1228             :         }
    1229          11 :         stream_putc(s, api->safi);
    1230             : 
    1231             :         /* Put prefix information. */
    1232          11 :         stream_putc(s, api->prefix.family);
    1233          11 :         psize = PSIZE(api->prefix.prefixlen);
    1234          11 :         stream_putc(s, api->prefix.prefixlen);
    1235          11 :         stream_write(s, &api->prefix.u.prefix, psize);
    1236             : 
    1237          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
    1238           0 :                 psize = PSIZE(api->src_prefix.prefixlen);
    1239           0 :                 stream_putc(s, api->src_prefix.prefixlen);
    1240           0 :                 stream_write(s, (uint8_t *)&api->src_prefix.prefix, psize);
    1241             :         }
    1242             : 
    1243          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
    1244           0 :                 stream_putl(s, api->nhgid);
    1245             : 
    1246             :         /* Nexthops.  */
    1247          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
    1248             :                 /* limit the number of nexthops if necessary */
    1249           9 :                 if (api->nexthop_num > MULTIPATH_NUM) {
    1250           0 :                         flog_err(
    1251             :                                 EC_LIB_ZAPI_ENCODE,
    1252             :                                 "%s: prefix %pFX: can't encode %u nexthops (maximum is %u)",
    1253             :                                 __func__, &api->prefix, api->nexthop_num,
    1254             :                                 MULTIPATH_NUM);
    1255           0 :                         return -1;
    1256             :                 }
    1257             : 
    1258             :                 /* We canonicalize the nexthops by sorting them; this allows
    1259             :                  * zebra to resolve the list of nexthops to a nexthop-group
    1260             :                  * more efficiently.
    1261             :                  */
    1262           9 :                 zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
    1263             : 
    1264           9 :                 stream_putw(s, api->nexthop_num);
    1265             : 
    1266          29 :                 for (i = 0; i < api->nexthop_num; i++) {
    1267          11 :                         api_nh = &api->nexthops[i];
    1268             : 
    1269             :                         /* MPLS labels for BGP-LU or Segment Routing */
    1270          11 :                         if (api_nh->label_num > MPLS_MAX_LABELS) {
    1271           0 :                                 flog_err(
    1272             :                                         EC_LIB_ZAPI_ENCODE,
    1273             :                                         "%s: prefix %pFX: can't encode %u labels (maximum is %u)",
    1274             :                                         __func__, &api->prefix,
    1275             :                                         api_nh->label_num, MPLS_MAX_LABELS);
    1276           0 :                                 return -1;
    1277             :                         }
    1278             : 
    1279          11 :                         if (zapi_nexthop_encode(s, api_nh, api->flags,
    1280             :                                                 api->message)
    1281             :                             != 0)
    1282             :                                 return -1;
    1283             :                 }
    1284             :         }
    1285             : 
    1286             :         /* Backup nexthops  */
    1287          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
    1288             :                 /* limit the number of nexthops if necessary */
    1289           0 :                 if (api->backup_nexthop_num > MULTIPATH_NUM) {
    1290           0 :                         flog_err(
    1291             :                                 EC_LIB_ZAPI_ENCODE,
    1292             :                                 "%s: prefix %pFX: can't encode %u backup nexthops (maximum is %u)",
    1293             :                                 __func__, &api->prefix, api->backup_nexthop_num,
    1294             :                                 MULTIPATH_NUM);
    1295           0 :                         return -1;
    1296             :                 }
    1297             : 
    1298             :                 /* Note that we do not sort the list of backup nexthops -
    1299             :                  * this list is treated as an array and indexed by each
    1300             :                  * primary nexthop that is associated with a backup.
    1301             :                  */
    1302             : 
    1303           0 :                 stream_putw(s, api->backup_nexthop_num);
    1304             : 
    1305           0 :                 for (i = 0; i < api->backup_nexthop_num; i++) {
    1306           0 :                         api_nh = &api->backup_nexthops[i];
    1307             : 
    1308             :                         /* MPLS labels for BGP-LU or Segment Routing */
    1309           0 :                         if (api_nh->label_num > MPLS_MAX_LABELS) {
    1310           0 :                                 flog_err(
    1311             :                                         EC_LIB_ZAPI_ENCODE,
    1312             :                                         "%s: prefix %pFX: backup: can't encode %u labels (maximum is %u)",
    1313             :                                         __func__, &api->prefix,
    1314             :                                         api_nh->label_num, MPLS_MAX_LABELS);
    1315           0 :                                 return -1;
    1316             :                         }
    1317             : 
    1318           0 :                         if (zapi_nexthop_encode(s, api_nh, api->flags,
    1319             :                                                 api->message)
    1320             :                             != 0)
    1321             :                                 return -1;
    1322             :                 }
    1323             :         }
    1324             : 
    1325             :         /* Attributes. */
    1326          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
    1327           9 :                 stream_putc(s, api->distance);
    1328          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
    1329           9 :                 stream_putl(s, api->metric);
    1330          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
    1331           0 :                 stream_putl(s, api->tag);
    1332          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
    1333           7 :                 stream_putl(s, api->mtu);
    1334          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
    1335           0 :                 stream_putl(s, api->tableid);
    1336             : 
    1337          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
    1338           0 :                 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
    1339           0 :                         flog_err(
    1340             :                                 EC_LIB_ZAPI_ENCODE,
    1341             :                                 "%s: opaque length %u is greater than allowed value",
    1342             :                                 __func__, api->opaque.length);
    1343           0 :                         return -1;
    1344             :                 }
    1345             : 
    1346           0 :                 stream_putw(s, api->opaque.length);
    1347           0 :                 stream_write(s, api->opaque.data, api->opaque.length);
    1348             :         }
    1349             :         /* Put length at the first point of the stream. */
    1350          11 :         stream_putw_at(s, 0, stream_get_endp(s));
    1351             : 
    1352          11 :         return 0;
    1353             : }
    1354             : 
    1355             : /*
    1356             :  * Decode a single zapi nexthop object
    1357             :  */
    1358          15 : int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
    1359             :                         uint32_t api_flags, uint32_t api_message)
    1360             : {
    1361          15 :         int i, ret = -1;
    1362             : 
    1363          15 :         STREAM_GETL(s, api_nh->vrf_id);
    1364          15 :         STREAM_GETC(s, api_nh->type);
    1365             : 
    1366             :         /* Note that we're only using a single octet of flags */
    1367          15 :         STREAM_GETC(s, api_nh->flags);
    1368             : 
    1369          15 :         switch (api_nh->type) {
    1370           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    1371           0 :                 STREAM_GETC(s, api_nh->bh_type);
    1372           0 :                 break;
    1373           0 :         case NEXTHOP_TYPE_IPV4:
    1374             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1375           0 :                 STREAM_GET(&api_nh->gate.ipv4.s_addr, s,
    1376             :                            IPV4_MAX_BYTELEN);
    1377           0 :                 STREAM_GETL(s, api_nh->ifindex);
    1378           0 :                 break;
    1379          11 :         case NEXTHOP_TYPE_IFINDEX:
    1380          11 :                 STREAM_GETL(s, api_nh->ifindex);
    1381          11 :                 break;
    1382           4 :         case NEXTHOP_TYPE_IPV6:
    1383             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1384           4 :                 STREAM_GET(&api_nh->gate.ipv6, s, 16);
    1385           4 :                 STREAM_GETL(s, api_nh->ifindex);
    1386           4 :                 break;
    1387             :         }
    1388             : 
    1389             :         /* MPLS labels for BGP-LU or Segment Routing */
    1390          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)) {
    1391           0 :                 STREAM_GETC(s, api_nh->label_num);
    1392           0 :                 STREAM_GETC(s, api_nh->label_type);
    1393           0 :                 if (api_nh->label_num > MPLS_MAX_LABELS) {
    1394           0 :                         flog_err(
    1395             :                                 EC_LIB_ZAPI_ENCODE,
    1396             :                                 "%s: invalid number of MPLS labels (%u)",
    1397             :                                 __func__, api_nh->label_num);
    1398           0 :                         return -1;
    1399             :                 }
    1400             : 
    1401           0 :                 STREAM_GET(&api_nh->labels[0], s,
    1402             :                            api_nh->label_num * sizeof(mpls_label_t));
    1403             :         }
    1404             : 
    1405          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
    1406           0 :                 STREAM_GETL(s, api_nh->weight);
    1407             : 
    1408             :         /* Router MAC for EVPN routes. */
    1409          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
    1410           0 :                 STREAM_GET(&(api_nh->rmac), s,
    1411             :                            sizeof(struct ethaddr));
    1412             : 
    1413             :         /* Color for Segment Routing TE. */
    1414          15 :         if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
    1415           0 :                 STREAM_GETL(s, api_nh->srte_color);
    1416             : 
    1417             :         /* Backup nexthop index */
    1418          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
    1419           0 :                 STREAM_GETC(s, api_nh->backup_num);
    1420             : 
    1421           0 :                 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS)
    1422             :                         return -1;
    1423             : 
    1424           0 :                 for (i = 0; i < api_nh->backup_num; i++)
    1425           0 :                         STREAM_GETC(s, api_nh->backup_idx[i]);
    1426             :         }
    1427             : 
    1428          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
    1429           0 :                 STREAM_GETL(s, api_nh->seg6local_action);
    1430           0 :                 STREAM_GET(&api_nh->seg6local_ctx, s,
    1431             :                            sizeof(struct seg6local_context));
    1432             :         }
    1433             : 
    1434          15 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6)) {
    1435           0 :                 STREAM_GETC(s, api_nh->seg_num);
    1436           0 :                 if (api_nh->seg_num > SRV6_MAX_SIDS) {
    1437           0 :                         flog_err(EC_LIB_ZAPI_ENCODE,
    1438             :                                  "%s: invalid number of SRv6 Segs (%u)",
    1439             :                                  __func__, api_nh->seg_num);
    1440           0 :                         return -1;
    1441             :                 }
    1442             : 
    1443           0 :                 STREAM_GET(&api_nh->seg6_segs[0], s,
    1444             :                            api_nh->seg_num * sizeof(struct in6_addr));
    1445             :         }
    1446             : 
    1447             :         /* Success */
    1448             :         ret = 0;
    1449             : 
    1450             : stream_failure:
    1451             : 
    1452             :         return ret;
    1453             : }
    1454             : 
    1455          11 : int zapi_route_decode(struct stream *s, struct zapi_route *api)
    1456             : {
    1457          11 :         struct zapi_nexthop *api_nh;
    1458          11 :         int i;
    1459             : 
    1460          11 :         memset(api, 0, sizeof(*api));
    1461             : 
    1462             :         /* Type, flags, message. */
    1463          11 :         STREAM_GETC(s, api->type);
    1464          11 :         if (api->type >= ZEBRA_ROUTE_MAX) {
    1465           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1466             :                          "%s: Specified route type: %d is not a legal value",
    1467             :                          __func__, api->type);
    1468           0 :                 return -1;
    1469             :         }
    1470             : 
    1471          11 :         STREAM_GETW(s, api->instance);
    1472          11 :         STREAM_GETL(s, api->flags);
    1473          11 :         STREAM_GETL(s, api->message);
    1474          11 :         STREAM_GETC(s, api->safi);
    1475          11 :         if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
    1476           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1477             :                          "%s: Specified route SAFI (%u) is not a legal value",
    1478             :                          __func__, api->safi);
    1479           0 :                 return -1;
    1480             :         }
    1481             : 
    1482             :         /* Prefix. */
    1483          11 :         STREAM_GETC(s, api->prefix.family);
    1484          11 :         STREAM_GETC(s, api->prefix.prefixlen);
    1485          11 :         switch (api->prefix.family) {
    1486          11 :         case AF_INET:
    1487          11 :                 if (api->prefix.prefixlen > IPV4_MAX_BITLEN) {
    1488           0 :                         flog_err(
    1489             :                                 EC_LIB_ZAPI_ENCODE,
    1490             :                                 "%s: V4 prefixlen is %d which should not be more than 32",
    1491             :                                 __func__, api->prefix.prefixlen);
    1492           0 :                         return -1;
    1493             :                 }
    1494             :                 break;
    1495           0 :         case AF_INET6:
    1496           0 :                 if (api->prefix.prefixlen > IPV6_MAX_BITLEN) {
    1497           0 :                         flog_err(
    1498             :                                 EC_LIB_ZAPI_ENCODE,
    1499             :                                 "%s: v6 prefixlen is %d which should not be more than 128",
    1500             :                                 __func__, api->prefix.prefixlen);
    1501           0 :                         return -1;
    1502             :                 }
    1503             :                 break;
    1504           0 :         default:
    1505           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    1506             :                          "%s: Specified family %d is not v4 or v6", __func__,
    1507             :                          api->prefix.family);
    1508           0 :                 return -1;
    1509             :         }
    1510          11 :         STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
    1511             : 
    1512          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
    1513           0 :                 api->src_prefix.family = AF_INET6;
    1514           0 :                 STREAM_GETC(s, api->src_prefix.prefixlen);
    1515           0 :                 if (api->src_prefix.prefixlen > IPV6_MAX_BITLEN) {
    1516           0 :                         flog_err(
    1517             :                                 EC_LIB_ZAPI_ENCODE,
    1518             :                                 "%s: SRC Prefix prefixlen received: %d is too large",
    1519             :                                 __func__, api->src_prefix.prefixlen);
    1520           0 :                         return -1;
    1521             :                 }
    1522           0 :                 STREAM_GET(&api->src_prefix.prefix, s,
    1523             :                            PSIZE(api->src_prefix.prefixlen));
    1524             : 
    1525           0 :                 if (api->prefix.family != AF_INET6
    1526           0 :                     || api->src_prefix.prefixlen == 0) {
    1527           0 :                         flog_err(
    1528             :                                 EC_LIB_ZAPI_ENCODE,
    1529             :                                 "%s: SRC prefix specified in some manner that makes no sense",
    1530             :                                 __func__);
    1531           0 :                         return -1;
    1532             :                 }
    1533             :         }
    1534             : 
    1535          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
    1536           0 :                 STREAM_GETL(s, api->nhgid);
    1537             : 
    1538             :         /* Nexthops. */
    1539          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
    1540           9 :                 STREAM_GETW(s, api->nexthop_num);
    1541           9 :                 if (api->nexthop_num > MULTIPATH_NUM) {
    1542           0 :                         flog_err(EC_LIB_ZAPI_ENCODE,
    1543             :                                  "%s: invalid number of nexthops (%u)",
    1544             :                                  __func__, api->nexthop_num);
    1545           0 :                         return -1;
    1546             :                 }
    1547             : 
    1548          20 :                 for (i = 0; i < api->nexthop_num; i++) {
    1549          11 :                         api_nh = &api->nexthops[i];
    1550             : 
    1551          11 :                         if (zapi_nexthop_decode(s, api_nh, api->flags,
    1552             :                                                 api->message)
    1553             :                             != 0)
    1554             :                                 return -1;
    1555             :                 }
    1556             :         }
    1557             : 
    1558             :         /* Backup nexthops. */
    1559          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
    1560           0 :                 STREAM_GETW(s, api->backup_nexthop_num);
    1561           0 :                 if (api->backup_nexthop_num > MULTIPATH_NUM) {
    1562           0 :                         flog_err(EC_LIB_ZAPI_ENCODE,
    1563             :                                  "%s: invalid number of backup nexthops (%u)",
    1564             :                                  __func__, api->backup_nexthop_num);
    1565           0 :                         return -1;
    1566             :                 }
    1567             : 
    1568           0 :                 for (i = 0; i < api->backup_nexthop_num; i++) {
    1569           0 :                         api_nh = &api->backup_nexthops[i];
    1570             : 
    1571           0 :                         if (zapi_nexthop_decode(s, api_nh, api->flags,
    1572             :                                                 api->message)
    1573             :                             != 0)
    1574             :                                 return -1;
    1575             :                 }
    1576             :         }
    1577             : 
    1578             :         /* Attributes. */
    1579          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
    1580           9 :                 STREAM_GETC(s, api->distance);
    1581          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
    1582           9 :                 STREAM_GETL(s, api->metric);
    1583          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
    1584           0 :                 STREAM_GETL(s, api->tag);
    1585          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
    1586           7 :                 STREAM_GETL(s, api->mtu);
    1587          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
    1588           0 :                 STREAM_GETL(s, api->tableid);
    1589             : 
    1590          11 :         if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
    1591           0 :                 STREAM_GETW(s, api->opaque.length);
    1592           0 :                 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
    1593           0 :                         flog_err(
    1594             :                                 EC_LIB_ZAPI_ENCODE,
    1595             :                                 "%s: opaque length %u is greater than allowed value",
    1596             :                                 __func__, api->opaque.length);
    1597           0 :                         return -1;
    1598             :                 }
    1599             : 
    1600           0 :                 STREAM_GET(api->opaque.data, s, api->opaque.length);
    1601             :         }
    1602             : 
    1603             :         return 0;
    1604             : stream_failure:
    1605             :         return -1;
    1606             : }
    1607             : 
    1608           0 : static void zapi_encode_prefix(struct stream *s, struct prefix *p,
    1609             :                                uint8_t family)
    1610             : {
    1611           0 :         struct prefix any;
    1612             : 
    1613           0 :         if (!p) {
    1614           0 :                 memset(&any, 0, sizeof(any));
    1615           0 :                 any.family = family;
    1616           0 :                 p = &any;
    1617             :         }
    1618             : 
    1619           0 :         stream_putc(s, p->family);
    1620           0 :         stream_putc(s, p->prefixlen);
    1621           0 :         stream_put(s, &p->u.prefix, prefix_blen(p));
    1622           0 : }
    1623             : 
    1624           0 : static bool zapi_decode_prefix(struct stream *s, struct prefix *p)
    1625             : {
    1626           0 :         STREAM_GETC(s, p->family);
    1627           0 :         STREAM_GETC(s, p->prefixlen);
    1628           0 :         STREAM_GET(&(p->u.prefix), s, prefix_blen(p));
    1629             :         return true;
    1630             : 
    1631             : stream_failure:
    1632             :         return false;
    1633             : }
    1634             : 
    1635           0 : static void zapi_encode_sockunion(struct stream *s, const union sockunion *su)
    1636             : {
    1637           0 :         int family = sockunion_family(su);
    1638           0 :         size_t addrlen = family2addrsize(family);
    1639             : 
    1640             :         /*
    1641             :          * Must know length to encode
    1642             :          */
    1643           0 :         assert(addrlen);
    1644             : 
    1645           0 :         stream_putc(s, (uint8_t)family);
    1646             : 
    1647           0 :         stream_write(s, sockunion_get_addr(su), addrlen);
    1648           0 : }
    1649             : 
    1650           0 : static bool zapi_decode_sockunion(struct stream *s, union sockunion *su)
    1651             : {
    1652           0 :         uint8_t family;
    1653           0 :         size_t addrlen;
    1654           0 :         uint8_t buf[sizeof(union sockunion)];
    1655             : 
    1656           0 :         memset(su, 0, sizeof(*su));
    1657             : 
    1658           0 :         STREAM_GETC(s, family);
    1659           0 :         sockunion_family(su) = family;
    1660             : 
    1661           0 :         addrlen = family2addrsize(family);
    1662           0 :         if (!addrlen)
    1663             :                 return false;
    1664             : 
    1665           0 :         if (addrlen > sizeof(buf))
    1666             :                 return false;
    1667             : 
    1668           0 :         STREAM_GET(buf, s, addrlen);
    1669           0 :         sockunion_set(su, family, buf, addrlen);
    1670           0 :         return true;
    1671             : 
    1672             : stream_failure:
    1673             :         return false;
    1674             : }
    1675             : 
    1676             : /*
    1677             :  * Encode filter subsection of pbr_rule
    1678             :  */
    1679           0 : static void zapi_pbr_rule_filter_encode(struct stream *s, struct pbr_filter *f)
    1680             : {
    1681           0 :         assert(f->src_ip.family == f->dst_ip.family);
    1682           0 :         assert((f->src_ip.family == AF_INET) || (f->src_ip.family == AF_INET6));
    1683             : 
    1684           0 :         stream_putl(s, f->filter_bm);
    1685             : 
    1686           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_IP_PROTOCOL))
    1687           0 :                 stream_putc(s, f->ip_proto);
    1688             : 
    1689             :         /* addresses */
    1690           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_IP))
    1691           0 :                 zapi_encode_prefix(s, &f->src_ip, f->src_ip.family);
    1692           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_IP))
    1693           0 :                 zapi_encode_prefix(s, &f->dst_ip, f->dst_ip.family);
    1694             : 
    1695             :         /* port numbers */
    1696           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_PORT))
    1697           0 :                 stream_putw(s, f->src_port);
    1698           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_PORT))
    1699           0 :                 stream_putw(s, f->dst_port);
    1700             : 
    1701           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DSCP))
    1702           0 :                 stream_putc(s, f->dsfield & PBR_DSFIELD_DSCP);
    1703           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_ECN))
    1704           0 :                 stream_putc(s, f->dsfield & PBR_DSFIELD_ECN);
    1705             : 
    1706             :         /* vlan */
    1707           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_PCP))
    1708           0 :                 stream_putc(s, f->pcp);
    1709           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_ID))
    1710           0 :                 stream_putw(s, f->vlan_id);
    1711           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_FLAGS))
    1712           0 :                 stream_putw(s, f->vlan_flags);
    1713             : 
    1714             : 
    1715           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_FWMARK))
    1716           0 :                 stream_putl(s, f->fwmark);
    1717           0 : }
    1718             : 
    1719           0 : static bool zapi_pbr_rule_filter_decode(struct stream *s, struct pbr_filter *f)
    1720             : {
    1721           0 :         uint8_t dscp = 0;
    1722           0 :         uint8_t ecn = 0;
    1723             : 
    1724           0 :         STREAM_GETL(s, f->filter_bm);
    1725             : 
    1726           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_IP_PROTOCOL))
    1727           0 :                 STREAM_GETC(s, f->ip_proto);
    1728             : 
    1729           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_IP))
    1730           0 :                 if (!zapi_decode_prefix(s, &(f->src_ip)))
    1731           0 :                         goto stream_failure;
    1732           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_IP))
    1733           0 :                 if (!zapi_decode_prefix(s, &(f->dst_ip)))
    1734           0 :                         goto stream_failure;
    1735             : 
    1736           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_PORT))
    1737           0 :                 STREAM_GETW(s, f->src_port);
    1738           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_PORT))
    1739           0 :                 STREAM_GETW(s, f->dst_port);
    1740             : 
    1741           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DSCP))
    1742           0 :                 STREAM_GETC(s, dscp);
    1743           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_ECN))
    1744           0 :                 STREAM_GETC(s, ecn);
    1745           0 :         f->dsfield = (dscp & PBR_DSFIELD_DSCP) | (ecn & PBR_DSFIELD_ECN);
    1746             : 
    1747             :         /* vlan */
    1748           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_PCP))
    1749           0 :                 STREAM_GETC(s, f->pcp);
    1750           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_ID))
    1751           0 :                 STREAM_GETW(s, f->vlan_id);
    1752           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_FLAGS))
    1753           0 :                 STREAM_GETW(s, f->vlan_flags);
    1754             : 
    1755           0 :         if (CHECK_FLAG(f->filter_bm, PBR_FILTER_FWMARK))
    1756           0 :                 STREAM_GETL(s, f->fwmark);
    1757             : 
    1758             :         return true;
    1759             : 
    1760             : stream_failure:
    1761             :         return false;
    1762             : }
    1763             : 
    1764           0 : static void zapi_pbr_rule_action_encode(struct stream *s, struct pbr_action *a)
    1765             : {
    1766           0 :         stream_putl(s, a->flags);
    1767             : 
    1768           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_TABLE))
    1769           0 :                 stream_putl(s, a->table);
    1770           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_QUEUE_ID))
    1771           0 :                 stream_putl(s, a->queue_id);
    1772             : 
    1773             :         /* L3 */
    1774           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_IP))
    1775           0 :                 zapi_encode_sockunion(s, &a->src_ip);
    1776           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DST_IP))
    1777           0 :                 zapi_encode_sockunion(s, &a->dst_ip);
    1778           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_PORT))
    1779           0 :                 stream_putw(s, a->src_port);
    1780           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DST_PORT))
    1781           0 :                 stream_putw(s, a->dst_port);
    1782             : 
    1783           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DSCP))
    1784           0 :                 stream_putc(s, a->dscp & PBR_DSFIELD_DSCP);
    1785           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_ECN))
    1786           0 :                 stream_putc(s, a->ecn & PBR_DSFIELD_ECN);
    1787             : 
    1788             :         /* L2 */
    1789           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_PCP))
    1790           0 :                 stream_putc(s, a->pcp);
    1791           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_VLAN_ID))
    1792           0 :                 stream_putw(s, a->vlan_id);
    1793           0 : }
    1794             : 
    1795           0 : static bool zapi_pbr_rule_action_decode(struct stream *s, struct pbr_action *a)
    1796             : {
    1797           0 :         STREAM_GETL(s, a->flags);
    1798             : 
    1799           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_TABLE))
    1800           0 :                 STREAM_GETL(s, a->table);
    1801           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_QUEUE_ID))
    1802           0 :                 STREAM_GETL(s, a->queue_id);
    1803             : 
    1804             :         /* L3 */
    1805           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_IP)) {
    1806           0 :                 if (!zapi_decode_sockunion(s, &(a->src_ip)))
    1807           0 :                         goto stream_failure;
    1808             :         }
    1809           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DST_IP))
    1810           0 :                 if (!zapi_decode_sockunion(s, &(a->dst_ip)))
    1811           0 :                         goto stream_failure;
    1812             : 
    1813           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_PORT))
    1814           0 :                 STREAM_GETW(s, a->src_port);
    1815           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DST_PORT))
    1816           0 :                 STREAM_GETW(s, a->dst_port);
    1817             : 
    1818           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_DSCP)) {
    1819           0 :                 STREAM_GETC(s, a->dscp);
    1820           0 :                 a->dscp &= PBR_DSFIELD_DSCP;
    1821             :         }
    1822           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_ECN)) {
    1823           0 :                 STREAM_GETC(s, a->ecn);
    1824           0 :                 a->ecn &= PBR_DSFIELD_ECN;
    1825             :         }
    1826             : 
    1827             :         /* L2 */
    1828           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_PCP))
    1829           0 :                 STREAM_GETC(s, a->pcp);
    1830           0 :         if (CHECK_FLAG(a->flags, PBR_ACTION_VLAN_ID))
    1831           0 :                 STREAM_GETW(s, a->vlan_id);
    1832             : 
    1833             :         return true;
    1834             : 
    1835             : stream_failure:
    1836             :         return false;
    1837             : }
    1838             : 
    1839           0 : int zapi_pbr_rule_encode(struct stream *s, struct pbr_rule *r)
    1840             : {
    1841             :         /*
    1842             :          * PBR record count is always 1
    1843             :          */
    1844           0 :         stream_putl(s, 1);
    1845             : 
    1846           0 :         stream_putc(s, r->family);
    1847           0 :         stream_putl(s, r->seq);
    1848           0 :         stream_putl(s, r->priority);
    1849           0 :         stream_putl(s, r->unique);
    1850             : 
    1851           0 :         zapi_pbr_rule_filter_encode(s, &(r->filter));
    1852           0 :         zapi_pbr_rule_action_encode(s, &(r->action));
    1853             : 
    1854           0 :         stream_put(s, r->ifname, INTERFACE_NAMSIZ);
    1855             : 
    1856             :         /* Put length at the first point of the stream. */
    1857           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1858             : 
    1859           0 :         return 0;
    1860             : }
    1861             : 
    1862           0 : bool zapi_pbr_rule_decode(struct stream *s, struct pbr_rule *r)
    1863             : {
    1864             :         /* NB caller has already read 4-byte rule count */
    1865             : 
    1866           0 :         memset(r, 0, sizeof(*r));
    1867             : 
    1868           0 :         STREAM_GETC(s, r->family);
    1869           0 :         STREAM_GETL(s, r->seq);
    1870           0 :         STREAM_GETL(s, r->priority);
    1871           0 :         STREAM_GETL(s, r->unique);
    1872             : 
    1873           0 :         if (!zapi_pbr_rule_filter_decode(s, &(r->filter)))
    1874           0 :                 goto stream_failure;
    1875           0 :         if (!zapi_pbr_rule_action_decode(s, &(r->action)))
    1876           0 :                 goto stream_failure;
    1877             : 
    1878           0 :         STREAM_GET(r->ifname, s, INTERFACE_NAMSIZ);
    1879             :         return true;
    1880             : 
    1881             : stream_failure:
    1882             :         return false;
    1883             : }
    1884             : 
    1885           0 : int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, struct tc_qdisc *qdisc)
    1886             : {
    1887           0 :         stream_reset(s);
    1888           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    1889             : 
    1890             : 
    1891           0 :         stream_putl(s, 1);
    1892             : 
    1893           0 :         stream_putl(s, qdisc->ifindex);
    1894           0 :         stream_putl(s, qdisc->kind);
    1895             : 
    1896           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1897             : 
    1898           0 :         return 0;
    1899             : }
    1900             : 
    1901           0 : int zapi_tc_class_encode(uint8_t cmd, struct stream *s, struct tc_class *class)
    1902             : {
    1903           0 :         stream_reset(s);
    1904           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    1905             : 
    1906           0 :         stream_putl(s, 1);
    1907             : 
    1908           0 :         stream_putl(s, class->ifindex);
    1909           0 :         stream_putl(s, class->handle);
    1910           0 :         stream_putl(s, class->kind);
    1911             : 
    1912           0 :         switch (class->kind) {
    1913           0 :         case TC_QDISC_HTB:
    1914           0 :                 stream_putq(s, class->u.htb.rate);
    1915           0 :                 stream_putq(s, class->u.htb.ceil);
    1916           0 :                 break;
    1917             :         case TC_QDISC_UNSPEC:
    1918             :         case TC_QDISC_NOQUEUE:
    1919             :                 /* not implemented */
    1920             :                 break;
    1921             :         }
    1922           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1923             : 
    1924           0 :         return 0;
    1925             : }
    1926             : 
    1927           0 : int zapi_tc_filter_encode(uint8_t cmd, struct stream *s,
    1928             :                           struct tc_filter *filter)
    1929             : {
    1930           0 :         stream_reset(s);
    1931           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    1932             : 
    1933           0 :         stream_putl(s, 1);
    1934             : 
    1935           0 :         stream_putl(s, filter->ifindex);
    1936           0 :         stream_putl(s, filter->handle);
    1937           0 :         stream_putl(s, filter->priority);
    1938           0 :         stream_putl(s, filter->protocol);
    1939           0 :         stream_putl(s, filter->kind);
    1940             : 
    1941           0 :         switch (filter->kind) {
    1942           0 :         case TC_FILTER_FLOWER:
    1943           0 :                 stream_putl(s, filter->u.flower.filter_bm);
    1944           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_IP_PROTOCOL)
    1945           0 :                         stream_putc(s, filter->u.flower.ip_proto);
    1946           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_SRC_IP)
    1947           0 :                         zapi_encode_prefix(s, &filter->u.flower.src_ip,
    1948           0 :                                            filter->u.flower.src_ip.family);
    1949           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_SRC_PORT) {
    1950           0 :                         stream_putw(s, filter->u.flower.src_port_min);
    1951           0 :                         stream_putw(s, filter->u.flower.src_port_max);
    1952             :                 }
    1953           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_DST_IP)
    1954           0 :                         zapi_encode_prefix(s, &filter->u.flower.dst_ip,
    1955           0 :                                            filter->u.flower.dst_ip.family);
    1956           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_DST_PORT) {
    1957           0 :                         stream_putw(s, filter->u.flower.dst_port_min);
    1958           0 :                         stream_putw(s, filter->u.flower.dst_port_max);
    1959             :                 }
    1960           0 :                 if (filter->u.flower.filter_bm & TC_FLOWER_DSFIELD) {
    1961           0 :                         stream_putc(s, filter->u.flower.dsfield);
    1962           0 :                         stream_putc(s, filter->u.flower.dsfield_mask);
    1963             :                 }
    1964           0 :                 stream_putl(s, filter->u.flower.classid);
    1965           0 :                 break;
    1966             :         case TC_FILTER_UNSPEC:
    1967             :         case TC_FILTER_BPF:
    1968             :         case TC_FILTER_FLOW:
    1969             :         case TC_FILTER_U32:
    1970             :                 /* not implemented */
    1971             :                 break;
    1972             :         }
    1973             : 
    1974           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1975             : 
    1976           0 :         return 0;
    1977             : }
    1978             : 
    1979           0 : bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
    1980             :                             enum zapi_nhg_notify_owner *note)
    1981             : {
    1982           0 :         uint32_t read_id;
    1983             : 
    1984           0 :         STREAM_GET(note, s, sizeof(*note));
    1985           0 :         STREAM_GETL(s, read_id);
    1986             : 
    1987           0 :         *id = read_id;
    1988             : 
    1989           0 :         return true;
    1990             : 
    1991             : stream_failure:
    1992             :         return false;
    1993             : }
    1994             : 
    1995           0 : bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
    1996             :                               uint32_t *tableid,
    1997             :                               enum zapi_route_notify_owner *note,
    1998             :                               afi_t *afi, safi_t *safi)
    1999             : {
    2000           0 :         uint32_t t;
    2001           0 :         afi_t afi_val;
    2002           0 :         safi_t safi_val;
    2003             : 
    2004           0 :         STREAM_GET(note, s, sizeof(*note));
    2005             : 
    2006           0 :         STREAM_GETC(s, p->family);
    2007           0 :         STREAM_GETC(s, p->prefixlen);
    2008           0 :         STREAM_GET(&p->u.prefix, s, prefix_blen(p));
    2009           0 :         STREAM_GETL(s, t);
    2010           0 :         STREAM_GETC(s, afi_val);
    2011           0 :         STREAM_GETC(s, safi_val);
    2012             : 
    2013           0 :         *tableid = t;
    2014             : 
    2015           0 :         if (afi)
    2016           0 :                 *afi = afi_val;
    2017           0 :         if (safi)
    2018           0 :                 *safi = safi_val;
    2019             : 
    2020             :         return true;
    2021             : 
    2022             : stream_failure:
    2023             :         return false;
    2024             : }
    2025             : 
    2026           0 : bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
    2027             :                              uint32_t *priority, uint32_t *unique, char *ifname,
    2028             :                              enum zapi_rule_notify_owner *note)
    2029             : {
    2030           0 :         uint32_t prio, seq, uni;
    2031             : 
    2032           0 :         STREAM_GET(note, s, sizeof(*note));
    2033             : 
    2034           0 :         STREAM_GETL(s, seq);
    2035           0 :         STREAM_GETL(s, prio);
    2036           0 :         STREAM_GETL(s, uni);
    2037           0 :         STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
    2038             : 
    2039           0 :         if (zclient_debug)
    2040           0 :                 zlog_debug("%s: %u %u %u %s", __func__, seq, prio, uni, ifname);
    2041           0 :         *seqno = seq;
    2042           0 :         *priority = prio;
    2043           0 :         *unique = uni;
    2044             : 
    2045           0 :         return true;
    2046             : 
    2047             : stream_failure:
    2048             :         return false;
    2049             : }
    2050             : 
    2051           0 : bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
    2052             :                               enum zapi_ipset_notify_owner *note)
    2053             : {
    2054           0 :         uint32_t uni;
    2055           0 :         uint16_t notew;
    2056             : 
    2057           0 :         STREAM_GETW(s, notew);
    2058             : 
    2059           0 :         STREAM_GETL(s, uni);
    2060             : 
    2061           0 :         if (zclient_debug)
    2062           0 :                 zlog_debug("%s: %u", __func__, uni);
    2063           0 :         *unique = uni;
    2064           0 :         *note = (enum zapi_ipset_notify_owner)notew;
    2065           0 :         return true;
    2066             : 
    2067             : stream_failure:
    2068             :         return false;
    2069             : }
    2070             : 
    2071           0 : bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
    2072             :                                     char *ipset_name,
    2073             :                                     enum zapi_ipset_entry_notify_owner *note)
    2074             : {
    2075           0 :         uint32_t uni;
    2076           0 :         uint16_t notew;
    2077             : 
    2078           0 :         STREAM_GETW(s, notew);
    2079             : 
    2080           0 :         STREAM_GETL(s, uni);
    2081             : 
    2082           0 :         STREAM_GET(ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
    2083             : 
    2084           0 :         if (zclient_debug)
    2085           0 :                 zlog_debug("%s: %u", __func__, uni);
    2086           0 :         *unique = uni;
    2087           0 :         *note = (enum zapi_ipset_entry_notify_owner)notew;
    2088             : 
    2089           0 :         return true;
    2090             : 
    2091             : stream_failure:
    2092             :         return false;
    2093             : }
    2094             : 
    2095           0 : bool zapi_iptable_notify_decode(struct stream *s,
    2096             :                 uint32_t *unique,
    2097             :                 enum zapi_iptable_notify_owner *note)
    2098             : {
    2099           0 :         uint32_t uni;
    2100           0 :         uint16_t notew;
    2101             : 
    2102           0 :         STREAM_GETW(s, notew);
    2103             : 
    2104           0 :         STREAM_GETL(s, uni);
    2105             : 
    2106           0 :         if (zclient_debug)
    2107           0 :                 zlog_debug("%s: %u", __func__, uni);
    2108           0 :         *unique = uni;
    2109           0 :         *note = (enum zapi_iptable_notify_owner)notew;
    2110             : 
    2111           0 :         return true;
    2112             : 
    2113             : stream_failure:
    2114             :         return false;
    2115             : }
    2116             : 
    2117           4 : struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
    2118             : {
    2119           4 :         struct nexthop *n = nexthop_new();
    2120             : 
    2121           4 :         n->type = znh->type;
    2122           4 :         n->vrf_id = znh->vrf_id;
    2123           4 :         n->ifindex = znh->ifindex;
    2124           4 :         n->gate = znh->gate;
    2125           4 :         n->srte_color = znh->srte_color;
    2126             : 
    2127             :         /*
    2128             :          * This function currently handles labels
    2129             :          */
    2130           4 :         if (znh->label_num) {
    2131           0 :                 nexthop_add_labels(n, ZEBRA_LSP_NONE, znh->label_num,
    2132           0 :                                    znh->labels);
    2133             :         }
    2134             : 
    2135           4 :         if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
    2136           0 :                 SET_FLAG(n->flags, NEXTHOP_FLAG_HAS_BACKUP);
    2137           0 :                 n->backup_num = znh->backup_num;
    2138           0 :                 memcpy(n->backup_idx, znh->backup_idx, n->backup_num);
    2139             :         }
    2140             : 
    2141           4 :         if (znh->seg6local_action != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
    2142           0 :                 nexthop_add_srv6_seg6local(n, znh->seg6local_action,
    2143             :                                            &znh->seg6local_ctx);
    2144             : 
    2145           4 :         if (znh->seg_num && !sid_zero_ipv6(znh->seg6_segs))
    2146           0 :                 nexthop_add_srv6_seg6(n, &znh->seg6_segs[0], znh->seg_num);
    2147             : 
    2148           4 :         return n;
    2149             : }
    2150             : 
    2151             : /*
    2152             :  * Convert nexthop to zapi nexthop
    2153             :  */
    2154           4 : int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
    2155             :                               const struct nexthop *nh)
    2156             : {
    2157           4 :         int i;
    2158             : 
    2159           4 :         memset(znh, 0, sizeof(*znh));
    2160             : 
    2161           4 :         znh->type = nh->type;
    2162           4 :         znh->vrf_id = nh->vrf_id;
    2163           4 :         znh->weight = nh->weight;
    2164           4 :         znh->ifindex = nh->ifindex;
    2165           4 :         znh->gate = nh->gate;
    2166             : 
    2167           4 :         if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
    2168           0 :                 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
    2169             : 
    2170           4 :         if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_EVPN))
    2171           0 :                 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_EVPN);
    2172             : 
    2173           4 :         if (nh->nh_label && (nh->nh_label->num_labels > 0)) {
    2174             : 
    2175             :                 /* Validate */
    2176           0 :                 if (nh->nh_label->num_labels > MPLS_MAX_LABELS)
    2177             :                         return -1;
    2178             : 
    2179           0 :                 for (i = 0; i < nh->nh_label->num_labels; i++)
    2180           0 :                         znh->labels[i] = nh->nh_label->label[i];
    2181             : 
    2182           0 :                 znh->label_num = i;
    2183           0 :                 znh->label_type = nh->nh_label_type;
    2184           0 :                 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
    2185             :         }
    2186             : 
    2187           4 :         if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
    2188           0 :                 if (nh->backup_num > NEXTHOP_MAX_BACKUPS)
    2189             :                         return -1;
    2190             : 
    2191           0 :                 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
    2192           0 :                 znh->backup_num = nh->backup_num;
    2193           0 :                 memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num);
    2194             :         }
    2195             : 
    2196           4 :         if (nh->nh_srv6) {
    2197           0 :                 if (nh->nh_srv6->seg6local_action !=
    2198             :                     ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
    2199           0 :                         SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
    2200           0 :                         znh->seg6local_action = nh->nh_srv6->seg6local_action;
    2201           0 :                         memcpy(&znh->seg6local_ctx,
    2202           0 :                                &nh->nh_srv6->seg6local_ctx,
    2203             :                                sizeof(struct seg6local_context));
    2204             :                 }
    2205             : 
    2206           0 :                 if (nh->nh_srv6->seg6_segs && nh->nh_srv6->seg6_segs->num_segs &&
    2207           0 :                     !sid_zero(nh->nh_srv6->seg6_segs)) {
    2208           0 :                         SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
    2209           0 :                         znh->seg_num = nh->nh_srv6->seg6_segs->num_segs;
    2210           0 :                         for (i = 0; i < nh->nh_srv6->seg6_segs->num_segs; i++)
    2211           0 :                                 memcpy(&znh->seg6_segs[i],
    2212           0 :                                        &nh->nh_srv6->seg6_segs->seg[i],
    2213             :                                        sizeof(struct in6_addr));
    2214             :                 }
    2215             :         }
    2216             : 
    2217             :         return 0;
    2218             : }
    2219             : 
    2220             : /*
    2221             :  * Wrapper that converts backup nexthop
    2222             :  */
    2223           0 : int zapi_backup_nexthop_from_nexthop(struct zapi_nexthop *znh,
    2224             :                                      const struct nexthop *nh)
    2225             : {
    2226           0 :         int ret;
    2227             : 
    2228             :         /* Ensure that zapi flags are correct: backups don't have backups */
    2229           0 :         ret = zapi_nexthop_from_nexthop(znh, nh);
    2230           0 :         if (ret == 0)
    2231           0 :                 UNSET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
    2232             : 
    2233           0 :         return ret;
    2234             : }
    2235             : 
    2236             : /*
    2237             :  * Format some info about a zapi nexthop, for debug or logging.
    2238             :  */
    2239           0 : const char *zapi_nexthop2str(const struct zapi_nexthop *znh, char *buf,
    2240             :                              int bufsize)
    2241             : {
    2242           0 :         char tmp[INET6_ADDRSTRLEN];
    2243             : 
    2244           0 :         switch (znh->type) {
    2245           0 :         case NEXTHOP_TYPE_IFINDEX:
    2246           0 :                 snprintf(buf, bufsize, "if %u", znh->ifindex);
    2247           0 :                 break;
    2248           0 :         case NEXTHOP_TYPE_IPV4:
    2249             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    2250           0 :                 inet_ntop(AF_INET, &znh->gate.ipv4, tmp, sizeof(tmp));
    2251           0 :                 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
    2252           0 :                 break;
    2253           0 :         case NEXTHOP_TYPE_IPV6:
    2254             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    2255           0 :                 inet_ntop(AF_INET6, &znh->gate.ipv6, tmp, sizeof(tmp));
    2256           0 :                 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
    2257           0 :                 break;
    2258           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    2259           0 :                 snprintf(buf, bufsize, "blackhole");
    2260           0 :                 break;
    2261           0 :         default:
    2262           0 :                 snprintf(buf, bufsize, "unknown");
    2263           0 :                 break;
    2264             :         }
    2265             : 
    2266           0 :         return buf;
    2267             : }
    2268             : 
    2269             : /*
    2270             :  * Decode the nexthop-tracking update message
    2271             :  */
    2272           4 : bool zapi_nexthop_update_decode(struct stream *s, struct prefix *match,
    2273             :                                 struct zapi_route *nhr)
    2274             : {
    2275           4 :         uint32_t i;
    2276             : 
    2277           4 :         memset(nhr, 0, sizeof(*nhr));
    2278             : 
    2279           4 :         STREAM_GETL(s, nhr->message);
    2280           4 :         STREAM_GETW(s, nhr->safi);
    2281           4 :         STREAM_GETW(s, match->family);
    2282           4 :         STREAM_GETC(s, match->prefixlen);
    2283             :         /*
    2284             :          * What we got told to match against
    2285             :          */
    2286           4 :         switch (match->family) {
    2287           0 :         case AF_INET:
    2288           0 :                 STREAM_GET(&match->u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
    2289             :                 break;
    2290           4 :         case AF_INET6:
    2291           4 :                 STREAM_GET(&match->u.prefix6, s, IPV6_MAX_BYTELEN);
    2292             :                 break;
    2293             :         }
    2294             :         /*
    2295             :          * What we matched against
    2296             :          */
    2297           4 :         STREAM_GETW(s, nhr->prefix.family);
    2298           4 :         STREAM_GETC(s, nhr->prefix.prefixlen);
    2299           4 :         switch (nhr->prefix.family) {
    2300           0 :         case AF_INET:
    2301           0 :                 STREAM_GET(&nhr->prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
    2302             :                 break;
    2303           4 :         case AF_INET6:
    2304           4 :                 STREAM_GET(&nhr->prefix.u.prefix6, s, IPV6_MAX_BYTELEN);
    2305             :                 break;
    2306             :         default:
    2307             :                 break;
    2308             :         }
    2309           4 :         if (CHECK_FLAG(nhr->message, ZAPI_MESSAGE_SRTE))
    2310           0 :                 STREAM_GETL(s, nhr->srte_color);
    2311             : 
    2312           4 :         STREAM_GETC(s, nhr->type);
    2313           4 :         STREAM_GETW(s, nhr->instance);
    2314           4 :         STREAM_GETC(s, nhr->distance);
    2315           4 :         STREAM_GETL(s, nhr->metric);
    2316           4 :         STREAM_GETC(s, nhr->nexthop_num);
    2317             : 
    2318           8 :         for (i = 0; i < nhr->nexthop_num; i++) {
    2319           4 :                 if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0, 0) != 0)
    2320             :                         return false;
    2321             :         }
    2322             : 
    2323             :         return true;
    2324             : stream_failure:
    2325             :         return false;
    2326             : }
    2327             : 
    2328           0 : bool zapi_error_decode(struct stream *s, enum zebra_error_types *error)
    2329             : {
    2330           0 :         memset(error, 0, sizeof(*error));
    2331             : 
    2332           0 :         STREAM_GET(error, s, sizeof(*error));
    2333             : 
    2334           0 :         if (zclient_debug)
    2335           0 :                 zlog_debug("%s: type: %s", __func__,
    2336             :                            zebra_error_type2str(*error));
    2337             : 
    2338             :         return true;
    2339           0 : stream_failure:
    2340           0 :         return false;
    2341             : }
    2342             : 
    2343             : /*
    2344             :  * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
    2345             :  * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
    2346             :  * then set/unset redist[type] in the client handle (a struct zserv) for the
    2347             :  * sending client
    2348             :  */
    2349             : enum zclient_send_status
    2350           4 : zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi,
    2351             :                         int type, unsigned short instance, vrf_id_t vrf_id)
    2352             : {
    2353           4 :         struct stream *s;
    2354             : 
    2355           4 :         s = zclient->obuf;
    2356           4 :         stream_reset(s);
    2357             : 
    2358           4 :         zclient_create_header(s, command, vrf_id);
    2359           4 :         stream_putc(s, afi);
    2360           4 :         stream_putc(s, type);
    2361           4 :         stream_putw(s, instance);
    2362             : 
    2363           4 :         stream_putw_at(s, 0, stream_get_endp(s));
    2364             : 
    2365           4 :         return zclient_send_message(zclient);
    2366             : }
    2367             : 
    2368             : enum zclient_send_status
    2369           0 : zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi,
    2370             :                                 vrf_id_t vrf_id)
    2371             : {
    2372           0 :         struct stream *s;
    2373             : 
    2374           0 :         s = zclient->obuf;
    2375           0 :         stream_reset(s);
    2376             : 
    2377           0 :         zclient_create_header(s, command, vrf_id);
    2378           0 :         stream_putc(s, afi);
    2379             : 
    2380           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2381             : 
    2382           0 :         return zclient_send_message(zclient);
    2383             : }
    2384             : 
    2385             : /* Send route notify request to zebra */
    2386           0 : int zebra_route_notify_send(int command, struct zclient *zclient, bool set)
    2387             : {
    2388           0 :         struct stream *s;
    2389             : 
    2390           0 :         s = zclient->obuf;
    2391           0 :         stream_reset(s);
    2392             : 
    2393           0 :         zclient_create_header(s, command, 0);
    2394           0 :         stream_putc(s, !!set);
    2395             : 
    2396           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2397             : 
    2398           0 :         return zclient_send_message(zclient);
    2399             : }
    2400             : 
    2401             : /* Get prefix in ZServ format; family should be filled in on prefix */
    2402          41 : static int zclient_stream_get_prefix(struct stream *s, struct prefix *p)
    2403             : {
    2404          41 :         size_t plen = prefix_blen(p);
    2405          41 :         uint8_t c;
    2406          41 :         p->prefixlen = 0;
    2407             : 
    2408          41 :         if (plen == 0)
    2409             :                 return -1;
    2410             : 
    2411          41 :         STREAM_GET(&p->u.prefix, s, plen);
    2412          41 :         STREAM_GETC(s, c);
    2413          41 :         p->prefixlen = MIN(plen * 8, c);
    2414             : 
    2415          41 :         return 0;
    2416             : stream_failure:
    2417             :         return -1;
    2418             : }
    2419             : 
    2420             : /* Router-id update from zebra daemon. */
    2421           2 : int zebra_router_id_update_read(struct stream *s, struct prefix *rid)
    2422             : {
    2423             :         /* Fetch interface address. */
    2424           2 :         STREAM_GETC(s, rid->family);
    2425             : 
    2426           2 :         return zclient_stream_get_prefix(s, rid);
    2427             : 
    2428           0 : stream_failure:
    2429           0 :         return -1;
    2430             : }
    2431             : 
    2432             : /* Interface addition from zebra daemon. */
    2433             : /*
    2434             :  * The format of the message sent with type ZEBRA_INTERFACE_ADD or
    2435             :  * ZEBRA_INTERFACE_DELETE from zebra to the client is:
    2436             :  *     0                   1                   2                   3
    2437             :  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    2438             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2439             :  * |  ifname                                                       |
    2440             :  * |                                                               |
    2441             :  * |                                                               |
    2442             :  * |                                                               |
    2443             :  * |                                                               |
    2444             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2445             :  * |  ifindex                                                      |
    2446             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2447             :  * |  status       |
    2448             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2449             :  * |  if_flags                                                     |
    2450             :  * |                                                               |
    2451             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2452             :  * |  metric                                                       |
    2453             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2454             :  * |  speed                                                        |
    2455             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2456             :  * |  ifmtu                                                        |
    2457             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2458             :  * |  ifmtu6                                                       |
    2459             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2460             :  * |  bandwidth                                                    |
    2461             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2462             :  * |  parent ifindex                                               |
    2463             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2464             :  * |  Link Layer Type                                              |
    2465             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2466             :  * |  Harware Address Length                                       |
    2467             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2468             :  * |  Hardware Address      if HW length different from 0          |
    2469             :  * |   ...                  max INTERFACE_HWADDR_MAX               |
    2470             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2471             :  * |  Link_params? |  Whether a link-params follows: 1 or 0.
    2472             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2473             :  * |  Link_params    0 or 1 INTERFACE_LINK_PARAMS_SIZE sized       |
    2474             :  * |   ....          (struct if_link_params).                      |
    2475             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    2476             :  */
    2477             : 
    2478           4 : static int zclient_vrf_add(ZAPI_CALLBACK_ARGS)
    2479             : {
    2480           4 :         struct vrf *vrf;
    2481           4 :         char vrfname_tmp[VRF_NAMSIZ + 1] = {};
    2482           4 :         struct vrf_data data;
    2483             : 
    2484           4 :         STREAM_GET(&data, zclient->ibuf, sizeof(struct vrf_data));
    2485             :         /* Read interface name. */
    2486           4 :         STREAM_GET(vrfname_tmp, zclient->ibuf, VRF_NAMSIZ);
    2487             : 
    2488           4 :         if (strlen(vrfname_tmp) == 0)
    2489           0 :                 goto stream_failure;
    2490             : 
    2491             :         /* Lookup/create vrf by name, then vrf_id. */
    2492           4 :         vrf = vrf_get(vrf_id, vrfname_tmp);
    2493             : 
    2494             :         /* If there's already a VRF with this name, don't create vrf */
    2495           4 :         if (!vrf)
    2496             :                 return 0;
    2497             : 
    2498           4 :         vrf->data.l.table_id = data.l.table_id;
    2499           4 :         memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ);
    2500           4 :         vrf_enable(vrf);
    2501             : 
    2502           4 :         return 0;
    2503             : stream_failure:
    2504             :         return -1;
    2505             : }
    2506             : 
    2507           0 : static int zclient_vrf_delete(ZAPI_CALLBACK_ARGS)
    2508             : {
    2509           0 :         struct vrf *vrf;
    2510             : 
    2511             :         /* Lookup vrf by vrf_id. */
    2512           0 :         vrf = vrf_lookup_by_id(vrf_id);
    2513             : 
    2514             :         /*
    2515             :          * If a routing protocol doesn't know about a
    2516             :          * vrf that is about to be deleted.  There is
    2517             :          * no point in attempting to delete it.
    2518             :          */
    2519           0 :         if (!vrf)
    2520             :                 return 0;
    2521             : 
    2522           0 :         vrf_delete(vrf);
    2523           0 :         return 0;
    2524             : }
    2525             : 
    2526          24 : static int zclient_interface_add(ZAPI_CALLBACK_ARGS)
    2527             : {
    2528          24 :         struct interface *ifp;
    2529          24 :         char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
    2530          24 :         struct stream *s = zclient->ibuf;
    2531          24 :         struct vrf *vrf;
    2532             : 
    2533             :         /* Read interface name. */
    2534          24 :         STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
    2535             : 
    2536             :         /* Lookup/create interface by name. */
    2537          24 :         vrf = vrf_lookup_by_id(vrf_id);
    2538          24 :         if (!vrf) {
    2539           0 :                 zlog_debug(
    2540             :                         "Rx'd interface add from Zebra, but VRF %u does not exist",
    2541             :                         vrf_id);
    2542           0 :                 return -1;
    2543             :         }
    2544             : 
    2545          24 :         ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name);
    2546             : 
    2547          24 :         zebra_interface_if_set_value(s, ifp);
    2548             : 
    2549          24 :         if_new_via_zapi(ifp);
    2550             : 
    2551          24 :         return 0;
    2552           0 : stream_failure:
    2553           0 :         return -1;
    2554             : }
    2555             : 
    2556             : /*
    2557             :  * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
    2558             :  * from zebra server.  The format of this message is the same as
    2559             :  * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE,
    2560             :  * except that no sockaddr_dl is sent at the tail of the message.
    2561             :  */
    2562          18 : struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t vrf_id)
    2563             : {
    2564          18 :         struct interface *ifp;
    2565          18 :         char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
    2566             : 
    2567             :         /* Read interface name. */
    2568          18 :         STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
    2569             : 
    2570             :         /* Lookup this by interface index. */
    2571          18 :         ifp = if_lookup_by_name(ifname_tmp, vrf_id);
    2572          18 :         if (ifp == NULL) {
    2573           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    2574             :                          "INTERFACE_STATE: Cannot find IF %s in VRF %d",
    2575             :                          ifname_tmp, vrf_id);
    2576           0 :                 return NULL;
    2577             :         }
    2578             : 
    2579          18 :         zebra_interface_if_set_value(s, ifp);
    2580             : 
    2581          18 :         return ifp;
    2582           0 : stream_failure:
    2583           0 :         return NULL;
    2584             : }
    2585             : 
    2586           0 : static int zclient_interface_delete(ZAPI_CALLBACK_ARGS)
    2587             : {
    2588           0 :         struct interface *ifp;
    2589           0 :         struct stream *s = zclient->ibuf;
    2590             : 
    2591           0 :         ifp = zebra_interface_state_read(s, vrf_id);
    2592             : 
    2593           0 :         if (ifp == NULL)
    2594             :                 return 0;
    2595             : 
    2596           0 :         if_destroy_via_zapi(ifp);
    2597           0 :         return 0;
    2598             : }
    2599             : 
    2600          12 : static int zclient_interface_up(ZAPI_CALLBACK_ARGS)
    2601             : {
    2602          12 :         struct interface *ifp;
    2603          12 :         struct stream *s = zclient->ibuf;
    2604             : 
    2605          12 :         ifp = zebra_interface_state_read(s, vrf_id);
    2606             : 
    2607          12 :         if (!ifp)
    2608             :                 return 0;
    2609             : 
    2610          12 :         if_up_via_zapi(ifp);
    2611          12 :         return 0;
    2612             : }
    2613             : 
    2614           6 : static int zclient_interface_down(ZAPI_CALLBACK_ARGS)
    2615             : {
    2616           6 :         struct interface *ifp;
    2617           6 :         struct stream *s = zclient->ibuf;
    2618             : 
    2619           6 :         ifp = zebra_interface_state_read(s, vrf_id);
    2620             : 
    2621           6 :         if (!ifp)
    2622             :                 return 0;
    2623             : 
    2624           6 :         if_down_via_zapi(ifp);
    2625           6 :         return 0;
    2626             : }
    2627             : 
    2628           0 : static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
    2629             : {
    2630           0 :         enum zebra_error_types error;
    2631           0 :         struct stream *s = zclient->ibuf;
    2632             : 
    2633           0 :         zapi_error_decode(s, &error);
    2634             : 
    2635           0 :         if (zclient->handle_error)
    2636           0 :                 (*zclient->handle_error)(error);
    2637           0 :         return 0;
    2638             : }
    2639             : 
    2640           0 : static int link_params_set_value(struct stream *s, struct interface *ifp)
    2641             : {
    2642           0 :         uint8_t link_params_enabled, nb_ext_adm_grp;
    2643           0 :         struct if_link_params *iflp;
    2644           0 :         uint32_t bwclassnum, bitmap_data;
    2645             : 
    2646           0 :         iflp = if_link_params_get(ifp);
    2647             : 
    2648           0 :         if (iflp == NULL)
    2649           0 :                 iflp = if_link_params_init(ifp);
    2650             : 
    2651           0 :         STREAM_GETC(s, link_params_enabled);
    2652           0 :         if (!link_params_enabled) {
    2653           0 :                 if_link_params_free(ifp);
    2654           0 :                 return 0;
    2655             :         }
    2656             : 
    2657           0 :         STREAM_GETL(s, iflp->lp_status);
    2658           0 :         STREAM_GETL(s, iflp->te_metric);
    2659           0 :         STREAM_GETF(s, iflp->max_bw);
    2660           0 :         STREAM_GETF(s, iflp->max_rsv_bw);
    2661           0 :         STREAM_GETL(s, bwclassnum);
    2662             :         {
    2663           0 :                 unsigned int i;
    2664           0 :                 for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
    2665           0 :                         STREAM_GETF(s, iflp->unrsv_bw[i]);
    2666           0 :                 if (i < bwclassnum)
    2667           0 :                         flog_err(
    2668             :                                 EC_LIB_ZAPI_MISSMATCH,
    2669             :                                 "%s: received %d > %d (MAX_CLASS_TYPE) bw entries - outdated library?",
    2670             :                                 __func__, bwclassnum, MAX_CLASS_TYPE);
    2671             :         }
    2672           0 :         STREAM_GETL(s, iflp->admin_grp);
    2673             : 
    2674             :         /* Extended Administrative Group */
    2675           0 :         admin_group_clear(&iflp->ext_admin_grp);
    2676           0 :         STREAM_GETC(s, nb_ext_adm_grp);
    2677           0 :         for (size_t i = 0; i < nb_ext_adm_grp; i++) {
    2678           0 :                 STREAM_GETL(s, bitmap_data);
    2679           0 :                 admin_group_bulk_set(&iflp->ext_admin_grp, bitmap_data, i);
    2680             :         }
    2681             : 
    2682           0 :         STREAM_GETL(s, iflp->rmt_as);
    2683           0 :         iflp->rmt_ip.s_addr = stream_get_ipv4(s);
    2684             : 
    2685           0 :         STREAM_GETL(s, iflp->av_delay);
    2686           0 :         STREAM_GETL(s, iflp->min_delay);
    2687           0 :         STREAM_GETL(s, iflp->max_delay);
    2688           0 :         STREAM_GETL(s, iflp->delay_var);
    2689             : 
    2690           0 :         STREAM_GETF(s, iflp->pkt_loss);
    2691           0 :         STREAM_GETF(s, iflp->res_bw);
    2692           0 :         STREAM_GETF(s, iflp->ava_bw);
    2693           0 :         STREAM_GETF(s, iflp->use_bw);
    2694             : 
    2695           0 :         return 0;
    2696             : stream_failure:
    2697             :         return -1;
    2698             : }
    2699             : 
    2700           0 : struct interface *zebra_interface_link_params_read(struct stream *s,
    2701             :                                                    vrf_id_t vrf_id,
    2702             :                                                    bool *changed)
    2703             : {
    2704           0 :         struct if_link_params *iflp;
    2705           0 :         struct if_link_params iflp_prev = {0};
    2706           0 :         ifindex_t ifindex;
    2707           0 :         bool iflp_prev_set = false;
    2708             : 
    2709           0 :         STREAM_GETL(s, ifindex);
    2710             : 
    2711           0 :         struct interface *ifp = if_lookup_by_index(ifindex, vrf_id);
    2712             : 
    2713           0 :         if (ifp == NULL) {
    2714           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    2715             :                          "%s: unknown ifindex %u, shouldn't happen", __func__,
    2716             :                          ifindex);
    2717           0 :                 return NULL;
    2718             :         }
    2719             : 
    2720           0 :         iflp = if_link_params_get(ifp);
    2721             : 
    2722           0 :         if (iflp) {
    2723           0 :                 iflp_prev_set = true;
    2724           0 :                 admin_group_init(&iflp_prev.ext_admin_grp);
    2725           0 :                 if_link_params_copy(&iflp_prev, iflp);
    2726             :         }
    2727             : 
    2728             :         /* read the link_params from stream
    2729             :          * Free ifp->link_params if the stream has no params
    2730             :          * to means that link-params are not enabled on links.
    2731             :          */
    2732           0 :         if (link_params_set_value(s, ifp) != 0)
    2733           0 :                 goto stream_failure;
    2734             : 
    2735           0 :         if (changed != NULL) {
    2736           0 :                 iflp = if_link_params_get(ifp);
    2737             : 
    2738           0 :                 if (iflp_prev_set && iflp) {
    2739           0 :                         if (if_link_params_cmp(&iflp_prev, iflp))
    2740           0 :                                 *changed = false;
    2741             :                         else
    2742           0 :                                 *changed = true;
    2743           0 :                 } else if (!iflp_prev_set && !iflp)
    2744           0 :                         *changed = false;
    2745             :                 else
    2746           0 :                         *changed = true;
    2747             :         }
    2748             : 
    2749           0 :         if (iflp_prev_set)
    2750           0 :                 admin_group_term(&iflp_prev.ext_admin_grp);
    2751             : 
    2752             :         return ifp;
    2753             : 
    2754           0 : stream_failure:
    2755           0 :         if (iflp_prev_set)
    2756           0 :                 admin_group_term(&iflp_prev.ext_admin_grp);
    2757             :         return NULL;
    2758             : }
    2759             : 
    2760          42 : static void zebra_interface_if_set_value(struct stream *s,
    2761             :                                          struct interface *ifp)
    2762             : {
    2763          42 :         uint8_t link_params_status = 0;
    2764          42 :         ifindex_t old_ifindex, new_ifindex;
    2765             : 
    2766          42 :         old_ifindex = ifp->oldifindex;
    2767             :         /* Read interface's index. */
    2768          42 :         STREAM_GETL(s, new_ifindex);
    2769          42 :         if_set_index(ifp, new_ifindex);
    2770          42 :         STREAM_GETC(s, ifp->status);
    2771             : 
    2772             :         /* Read interface's value. */
    2773          42 :         STREAM_GETQ(s, ifp->flags);
    2774          42 :         STREAM_GETC(s, ifp->ptm_enable);
    2775          42 :         STREAM_GETC(s, ifp->ptm_status);
    2776          42 :         STREAM_GETL(s, ifp->metric);
    2777          42 :         STREAM_GETL(s, ifp->speed);
    2778          42 :         STREAM_GETL(s, ifp->txqlen);
    2779          42 :         STREAM_GETL(s, ifp->mtu);
    2780          42 :         STREAM_GETL(s, ifp->mtu6);
    2781          42 :         STREAM_GETL(s, ifp->bandwidth);
    2782          42 :         STREAM_GETL(s, ifp->link_ifindex);
    2783          42 :         STREAM_GETL(s, ifp->ll_type);
    2784          42 :         STREAM_GETL(s, ifp->hw_addr_len);
    2785          42 :         if (ifp->hw_addr_len)
    2786          36 :                 STREAM_GET(ifp->hw_addr, s,
    2787             :                            MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
    2788             : 
    2789             :         /* Read Traffic Engineering status */
    2790          42 :         link_params_status = stream_getc(s);
    2791             :         /* Then, Traffic Engineering parameters if any */
    2792          42 :         if (link_params_status)
    2793           0 :                 link_params_set_value(s, ifp);
    2794             : 
    2795          42 :         nexthop_group_interface_state_change(ifp, old_ifindex);
    2796             : 
    2797          42 :         return;
    2798           0 : stream_failure:
    2799           0 :         zlog_err("Could not parse interface values; aborting");
    2800          42 :         assert(!"Failed to parse interface values");
    2801             : }
    2802             : 
    2803          36 : size_t zebra_interface_link_params_write(struct stream *s,
    2804             :                                          struct interface *ifp)
    2805             : {
    2806          36 :         size_t w, nb_ext_adm_grp;
    2807          36 :         struct if_link_params *iflp;
    2808          36 :         int i;
    2809             : 
    2810             : 
    2811          36 :         if (s == NULL || ifp == NULL)
    2812             :                 return 0;
    2813             : 
    2814          36 :         iflp = ifp->link_params;
    2815          36 :         w = 0;
    2816             : 
    2817             :         /* encode if link_params is enabled */
    2818          36 :         if (iflp) {
    2819           0 :                 w += stream_putc(s, true);
    2820             :         } else {
    2821          36 :                 w += stream_putc(s, false);
    2822          36 :                 return w;
    2823             :         }
    2824             : 
    2825           0 :         w += stream_putl(s, iflp->lp_status);
    2826             : 
    2827           0 :         w += stream_putl(s, iflp->te_metric);
    2828           0 :         w += stream_putf(s, iflp->max_bw);
    2829           0 :         w += stream_putf(s, iflp->max_rsv_bw);
    2830             : 
    2831           0 :         w += stream_putl(s, MAX_CLASS_TYPE);
    2832           0 :         for (i = 0; i < MAX_CLASS_TYPE; i++)
    2833           0 :                 w += stream_putf(s, iflp->unrsv_bw[i]);
    2834             : 
    2835           0 :         w += stream_putl(s, iflp->admin_grp);
    2836             : 
    2837             :         /* Extended Administrative Group */
    2838           0 :         nb_ext_adm_grp = admin_group_nb_words(&iflp->ext_admin_grp);
    2839           0 :         w += stream_putc(s, nb_ext_adm_grp);
    2840           0 :         for (size_t i = 0; i < nb_ext_adm_grp; i++)
    2841           0 :                 stream_putl(s, admin_group_get_offset(&iflp->ext_admin_grp, i));
    2842             : 
    2843           0 :         w += stream_putl(s, iflp->rmt_as);
    2844           0 :         w += stream_put_in_addr(s, &iflp->rmt_ip);
    2845             : 
    2846           0 :         w += stream_putl(s, iflp->av_delay);
    2847           0 :         w += stream_putl(s, iflp->min_delay);
    2848           0 :         w += stream_putl(s, iflp->max_delay);
    2849           0 :         w += stream_putl(s, iflp->delay_var);
    2850             : 
    2851           0 :         w += stream_putf(s, iflp->pkt_loss);
    2852           0 :         w += stream_putf(s, iflp->res_bw);
    2853           0 :         w += stream_putf(s, iflp->ava_bw);
    2854           0 :         w += stream_putf(s, iflp->use_bw);
    2855             : 
    2856           0 :         return w;
    2857             : }
    2858             : 
    2859             : /*
    2860             :  * format of message for address addition is:
    2861             :  *    0
    2862             :  *  0 1 2 3 4 5 6 7
    2863             :  * +-+-+-+-+-+-+-+-+
    2864             :  * |   type        |  ZEBRA_INTERFACE_ADDRESS_ADD or
    2865             :  * +-+-+-+-+-+-+-+-+  ZEBRA_INTERFACE_ADDRES_DELETE
    2866             :  * |               |
    2867             :  * +               +
    2868             :  * |   ifindex     |
    2869             :  * +               +
    2870             :  * |               |
    2871             :  * +               +
    2872             :  * |               |
    2873             :  * +-+-+-+-+-+-+-+-+
    2874             :  * |   ifc_flags   |  flags for connected address
    2875             :  * +-+-+-+-+-+-+-+-+
    2876             :  * |  addr_family  |
    2877             :  * +-+-+-+-+-+-+-+-+
    2878             :  * |    addr...    |
    2879             :  * :               :
    2880             :  * |               |
    2881             :  * +-+-+-+-+-+-+-+-+
    2882             :  * |    addr_len   |  len of addr. E.g., addr_len = 4 for ipv4 addrs.
    2883             :  * +-+-+-+-+-+-+-+-+
    2884             :  * |     daddr..   |
    2885             :  * :               :
    2886             :  * |               |
    2887             :  * +-+-+-+-+-+-+-+-+
    2888             :  */
    2889             : 
    2890             : static int memconstant(const void *s, int c, size_t n)
    2891             : {
    2892             :         const uint8_t *p = s;
    2893             : 
    2894         543 :         while (n-- > 0)
    2895         504 :                 if (*p++ != c)
    2896             :                         return 0;
    2897             :         return 1;
    2898             : }
    2899             : 
    2900             : 
    2901          39 : struct connected *zebra_interface_address_read(int type, struct stream *s,
    2902             :                                                vrf_id_t vrf_id)
    2903             : {
    2904          39 :         ifindex_t ifindex;
    2905          39 :         struct interface *ifp;
    2906          39 :         struct connected *ifc;
    2907          39 :         struct prefix p, d, *dp;
    2908          39 :         int plen;
    2909          39 :         uint8_t ifc_flags;
    2910             : 
    2911          39 :         memset(&p, 0, sizeof(p));
    2912          39 :         memset(&d, 0, sizeof(d));
    2913             : 
    2914             :         /* Get interface index. */
    2915          39 :         STREAM_GETL(s, ifindex);
    2916             : 
    2917             :         /* Lookup index. */
    2918          39 :         ifp = if_lookup_by_index(ifindex, vrf_id);
    2919          39 :         if (ifp == NULL) {
    2920           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    2921             :                          "INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d",
    2922             :                          (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL",
    2923             :                          ifindex, vrf_id);
    2924           0 :                 return NULL;
    2925             :         }
    2926             : 
    2927             :         /* Fetch flag. */
    2928          39 :         STREAM_GETC(s, ifc_flags);
    2929             : 
    2930             :         /* Fetch interface address. */
    2931          39 :         STREAM_GETC(s, d.family);
    2932          39 :         p.family = d.family;
    2933          39 :         plen = prefix_blen(&d);
    2934             : 
    2935          39 :         if (zclient_stream_get_prefix(s, &p) != 0)
    2936           0 :                 goto stream_failure;
    2937             : 
    2938             :         /* Fetch destination address. */
    2939          39 :         STREAM_GET(&d.u.prefix, s, plen);
    2940             : 
    2941             :         /* N.B. NULL destination pointers are encoded as all zeroes */
    2942          39 :         dp = memconstant(&d.u.prefix, 0, plen) ? NULL : &d;
    2943             : 
    2944          39 :         if (type == ZEBRA_INTERFACE_ADDRESS_ADD) {
    2945          35 :                 ifc = connected_lookup_prefix_exact(ifp, &p);
    2946          35 :                 if (!ifc) {
    2947             :                         /* N.B. NULL destination pointers are encoded as all
    2948             :                          * zeroes */
    2949          22 :                         ifc = connected_add_by_prefix(ifp, &p, dp);
    2950             :                 }
    2951          22 :                 if (ifc) {
    2952          35 :                         ifc->flags = ifc_flags;
    2953          35 :                         if (ifc->destination)
    2954           0 :                                 ifc->destination->prefixlen =
    2955           0 :                                         ifc->address->prefixlen;
    2956          35 :                         else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
    2957             :                                 /* carp interfaces on OpenBSD with 0.0.0.0/0 as
    2958             :                                  * "peer" */
    2959           0 :                                 flog_err(
    2960             :                                         EC_LIB_ZAPI_ENCODE,
    2961             :                                         "interface %s address %pFX with peer flag set, but no peer address!",
    2962             :                                         ifp->name, ifc->address);
    2963           0 :                                 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
    2964             :                         }
    2965             :                 }
    2966             :         } else {
    2967           4 :                 assert(type == ZEBRA_INTERFACE_ADDRESS_DELETE);
    2968           4 :                 ifc = connected_delete_by_prefix(ifp, &p);
    2969             :         }
    2970             : 
    2971             :         return ifc;
    2972             : 
    2973             : stream_failure:
    2974             :         return NULL;
    2975             : }
    2976             : 
    2977             : /*
    2978             :  * format of message for neighbor connected address is:
    2979             :  *    0
    2980             :  *  0 1 2 3 4 5 6 7
    2981             :  * +-+-+-+-+-+-+-+-+
    2982             :  * |   type        |  ZEBRA_INTERFACE_NBR_ADDRESS_ADD or
    2983             :  * +-+-+-+-+-+-+-+-+  ZEBRA_INTERFACE_NBR_ADDRES_DELETE
    2984             :  * |               |
    2985             :  * +               +
    2986             :  * |   ifindex     |
    2987             :  * +               +
    2988             :  * |               |
    2989             :  * +               +
    2990             :  * |               |
    2991             :  * +-+-+-+-+-+-+-+-+
    2992             :  * |  addr_family  |
    2993             :  * +-+-+-+-+-+-+-+-+
    2994             :  * |    addr...    |
    2995             :  * :               :
    2996             :  * |               |
    2997             :  * +-+-+-+-+-+-+-+-+
    2998             :  * |    addr_len   |  len of addr.
    2999             :  * +-+-+-+-+-+-+-+-+
    3000             :  */
    3001             : struct nbr_connected *
    3002           0 : zebra_interface_nbr_address_read(int type, struct stream *s, vrf_id_t vrf_id)
    3003             : {
    3004           0 :         unsigned int ifindex;
    3005           0 :         struct interface *ifp;
    3006           0 :         struct prefix p;
    3007           0 :         struct nbr_connected *ifc;
    3008             : 
    3009             :         /* Get interface index. */
    3010           0 :         STREAM_GETL(s, ifindex);
    3011             : 
    3012             :         /* Lookup index. */
    3013           0 :         ifp = if_lookup_by_index(ifindex, vrf_id);
    3014           0 :         if (ifp == NULL) {
    3015           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3016             :                          "INTERFACE_NBR_%s: Cannot find IF %u in VRF %d",
    3017             :                          (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD"
    3018             :                                                                    : "DELETE",
    3019             :                          ifindex, vrf_id);
    3020           0 :                 return NULL;
    3021             :         }
    3022             : 
    3023           0 :         STREAM_GETC(s, p.family);
    3024           0 :         STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
    3025           0 :         STREAM_GETC(s, p.prefixlen);
    3026             : 
    3027           0 :         if (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) {
    3028             :                 /* Currently only supporting P2P links, so any new RA source
    3029             :                    address is
    3030             :                    considered as the replacement of the previously learnt
    3031             :                    Link-Local address. */
    3032           0 :                 if (!(ifc = listnode_head(ifp->nbr_connected))) {
    3033           0 :                         ifc = nbr_connected_new();
    3034           0 :                         ifc->address = prefix_new();
    3035           0 :                         ifc->ifp = ifp;
    3036           0 :                         listnode_add(ifp->nbr_connected, ifc);
    3037             :                 }
    3038             : 
    3039           0 :                 prefix_copy(ifc->address, &p);
    3040             :         } else {
    3041           0 :                 assert(type == ZEBRA_INTERFACE_NBR_ADDRESS_DELETE);
    3042             : 
    3043           0 :                 ifc = nbr_connected_check(ifp, &p);
    3044           0 :                 if (ifc)
    3045           0 :                         listnode_delete(ifp->nbr_connected, ifc);
    3046             :         }
    3047             : 
    3048             :         return ifc;
    3049             : 
    3050             : stream_failure:
    3051             :         return NULL;
    3052             : }
    3053             : 
    3054           0 : struct interface *zebra_interface_vrf_update_read(struct stream *s,
    3055             :                                                   vrf_id_t vrf_id,
    3056             :                                                   vrf_id_t *new_vrf_id)
    3057             : {
    3058           0 :         char ifname[INTERFACE_NAMSIZ + 1] = {};
    3059           0 :         struct interface *ifp;
    3060           0 :         vrf_id_t new_id;
    3061             : 
    3062             :         /* Read interface name. */
    3063           0 :         STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
    3064             : 
    3065             :         /* Lookup interface. */
    3066           0 :         ifp = if_lookup_by_name(ifname, vrf_id);
    3067           0 :         if (ifp == NULL) {
    3068           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3069             :                          "INTERFACE_VRF_UPDATE: Cannot find IF %s in VRF %d",
    3070             :                          ifname, vrf_id);
    3071           0 :                 return NULL;
    3072             :         }
    3073             : 
    3074             :         /* Fetch new VRF Id. */
    3075           0 :         STREAM_GETL(s, new_id);
    3076             : 
    3077           0 :         *new_vrf_id = new_id;
    3078           0 :         return ifp;
    3079             : 
    3080             : stream_failure:
    3081             :         return NULL;
    3082             : }
    3083             : 
    3084             : /* filter unwanted messages until the expected one arrives */
    3085           2 : static int zclient_read_sync_response(struct zclient *zclient,
    3086             :                                       uint16_t expected_cmd)
    3087             : {
    3088           2 :         struct stream *s;
    3089           2 :         uint16_t size = -1;
    3090           2 :         uint8_t marker;
    3091           2 :         uint8_t version;
    3092           2 :         vrf_id_t vrf_id;
    3093           2 :         uint16_t cmd;
    3094           2 :         fd_set readfds;
    3095           2 :         int ret;
    3096             : 
    3097           2 :         ret = 0;
    3098           2 :         cmd = expected_cmd + 1;
    3099           2 :         while (ret == 0 && cmd != expected_cmd) {
    3100           2 :                 s = zclient->ibuf;
    3101           2 :                 stream_reset(s);
    3102             : 
    3103             :                 /* wait until response arrives */
    3104          36 :                 FD_ZERO(&readfds);
    3105           2 :                 FD_SET(zclient->sock, &readfds);
    3106           2 :                 select(zclient->sock + 1, &readfds, NULL, NULL, NULL);
    3107           2 :                 if (!FD_ISSET(zclient->sock, &readfds))
    3108           0 :                         continue;
    3109             :                 /* read response */
    3110           2 :                 ret = zclient_read_header(s, zclient->sock, &size, &marker,
    3111             :                                           &version, &vrf_id, &cmd);
    3112           2 :                 if (zclient_debug)
    3113           4 :                         zlog_debug("%s: Response (%d bytes) received", __func__,
    3114             :                                    size);
    3115             :         }
    3116           2 :         if (ret != 0) {
    3117           0 :                 flog_err(EC_LIB_ZAPI_ENCODE, "%s: Invalid Sync Message Reply",
    3118             :                          __func__);
    3119           0 :                 return -1;
    3120             :         }
    3121             : 
    3122             :         return 0;
    3123             : }
    3124             : /**
    3125             :  * Connect to label manager in a synchronous way
    3126             :  *
    3127             :  * It first writes the request to zclient output buffer and then
    3128             :  * immediately reads the answer from the input buffer.
    3129             :  *
    3130             :  * @param zclient Zclient used to connect to label manager (zebra)
    3131             :  * @param async Synchronous (0) or asynchronous (1) operation
    3132             :  * @result Result of response
    3133             :  */
    3134           2 : int lm_label_manager_connect(struct zclient *zclient, int async)
    3135             : {
    3136           2 :         int ret;
    3137           2 :         struct stream *s;
    3138           2 :         uint8_t result;
    3139           2 :         uint16_t cmd = async ? ZEBRA_LABEL_MANAGER_CONNECT_ASYNC :
    3140             :                                ZEBRA_LABEL_MANAGER_CONNECT;
    3141             : 
    3142           2 :         if (zclient_debug)
    3143           0 :                 zlog_debug("Connecting to Label Manager (LM)");
    3144             : 
    3145           2 :         if (zclient->sock < 0) {
    3146           0 :                 zlog_debug("%s: invalid zclient socket", __func__);
    3147           0 :                 return -1;
    3148             :         }
    3149             : 
    3150             :         /* send request */
    3151           2 :         s = zclient->obuf;
    3152           2 :         stream_reset(s);
    3153           2 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    3154             : 
    3155             :         /* proto */
    3156           2 :         stream_putc(s, zclient->redist_default);
    3157             :         /* instance */
    3158           2 :         stream_putw(s, zclient->instance);
    3159             : 
    3160             :         /* Put length at the first point of the stream. */
    3161           2 :         stream_putw_at(s, 0, stream_get_endp(s));
    3162             : 
    3163           2 :         ret = writen(zclient->sock, s->data, stream_get_endp(s));
    3164           2 :         if (ret < 0) {
    3165           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
    3166           0 :                 close(zclient->sock);
    3167           0 :                 zclient->sock = -1;
    3168           0 :                 return -1;
    3169             :         }
    3170           2 :         if (ret == 0) {
    3171           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
    3172           0 :                 close(zclient->sock);
    3173           0 :                 zclient->sock = -1;
    3174           0 :                 return -1;
    3175             :         }
    3176           2 :         if (zclient_debug)
    3177           0 :                 zlog_debug("LM connect request sent (%d bytes)", ret);
    3178             : 
    3179           2 :         if (async)
    3180             :                 return 0;
    3181             : 
    3182             :         /* read response */
    3183           2 :         if (zclient_read_sync_response(zclient, cmd)
    3184             :             != 0)
    3185             :                 return -1;
    3186             : 
    3187           2 :         s = zclient->ibuf;
    3188             : 
    3189             :         /* read instance and proto */
    3190           2 :         uint8_t proto;
    3191           2 :         uint16_t instance;
    3192             : 
    3193           2 :         STREAM_GETC(s, proto);
    3194           2 :         STREAM_GETW(s, instance);
    3195             : 
    3196             :         /* sanity */
    3197           2 :         if (proto != zclient->redist_default)
    3198           0 :                 flog_err(
    3199             :                         EC_LIB_ZAPI_ENCODE,
    3200             :                         "Wrong proto (%u) in LM connect response. Should be %u",
    3201             :                         proto, zclient->redist_default);
    3202           2 :         if (instance != zclient->instance)
    3203           0 :                 flog_err(
    3204             :                         EC_LIB_ZAPI_ENCODE,
    3205             :                         "Wrong instId (%u) in LM connect response. Should be %u",
    3206             :                         instance, zclient->instance);
    3207             : 
    3208             :         /* result code */
    3209           2 :         STREAM_GETC(s, result);
    3210           2 :         if (zclient_debug)
    3211           0 :                 zlog_debug("LM connect-response received, result %u", result);
    3212             : 
    3213           2 :         return (int)result;
    3214             : 
    3215             : stream_failure:
    3216             :         return -1;
    3217             : }
    3218             : 
    3219             : /**
    3220             :  * Function to request a srv6-locator chunk in an asynchronous way
    3221             :  *
    3222             :  * @param zclient Zclient used to connect to table manager (zebra)
    3223             :  * @param locator_name Name of SRv6-locator
    3224             :  * @result 0 on success, -1 otherwise
    3225             :  */
    3226           0 : int srv6_manager_get_locator_chunk(struct zclient *zclient,
    3227             :                                    const char *locator_name)
    3228             : {
    3229           0 :         struct stream *s;
    3230           0 :         const size_t len = strlen(locator_name);
    3231             : 
    3232           0 :         if (zclient_debug)
    3233           0 :                 zlog_debug("Getting SRv6-Locator Chunk %s", locator_name);
    3234             : 
    3235           0 :         if (zclient->sock < 0)
    3236             :                 return -1;
    3237             : 
    3238             :         /* send request */
    3239           0 :         s = zclient->obuf;
    3240           0 :         stream_reset(s);
    3241           0 :         zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
    3242             :                               VRF_DEFAULT);
    3243             : 
    3244             :         /* locator_name */
    3245           0 :         stream_putw(s, len);
    3246           0 :         stream_put(s, locator_name, len);
    3247             : 
    3248             :         /* Put length at the first point of the stream. */
    3249           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3250             : 
    3251           0 :         return zclient_send_message(zclient);
    3252             : }
    3253             : 
    3254             : /**
    3255             :  * Function to release a srv6-locator chunk
    3256             :  *
    3257             :  * @param zclient Zclient used to connect to table manager (zebra)
    3258             :  * @param locator_name Name of SRv6-locator
    3259             :  * @result 0 on success, -1 otherwise
    3260             :  */
    3261           0 : int srv6_manager_release_locator_chunk(struct zclient *zclient,
    3262             :                                        const char *locator_name)
    3263             : {
    3264           0 :         struct stream *s;
    3265           0 :         const size_t len = strlen(locator_name);
    3266             : 
    3267           0 :         if (zclient_debug)
    3268           0 :                 zlog_debug("Releasing SRv6-Locator Chunk %s", locator_name);
    3269             : 
    3270           0 :         if (zclient->sock < 0)
    3271             :                 return -1;
    3272             : 
    3273             :         /* send request */
    3274           0 :         s = zclient->obuf;
    3275           0 :         stream_reset(s);
    3276           0 :         zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
    3277             :                               VRF_DEFAULT);
    3278             : 
    3279             :         /* locator_name */
    3280           0 :         stream_putw(s, len);
    3281           0 :         stream_put(s, locator_name, len);
    3282             : 
    3283             :         /* Put length at the first point of the stream. */
    3284           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3285             : 
    3286           0 :         return zclient_send_message(zclient);
    3287             : }
    3288             : 
    3289             : /*
    3290             :  * Asynchronous label chunk request
    3291             :  *
    3292             :  * @param zclient Zclient used to connect to label manager (zebra)
    3293             :  * @param keep Avoid garbage collection
    3294             :  * @param chunk_size Amount of labels requested
    3295             :  * @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care
    3296             :  * @result 0 on success, -1 otherwise
    3297             :  */
    3298           0 : enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient,
    3299             :                                                       uint8_t keep,
    3300             :                                                       uint32_t chunk_size,
    3301             :                                                       uint32_t base)
    3302             : {
    3303           0 :         struct stream *s;
    3304             : 
    3305           0 :         if (zclient_debug)
    3306           0 :                 zlog_debug("Getting Label Chunk");
    3307             : 
    3308           0 :         if (zclient->sock < 0)
    3309             :                 return ZCLIENT_SEND_FAILURE;
    3310             : 
    3311           0 :         s = zclient->obuf;
    3312           0 :         stream_reset(s);
    3313             : 
    3314           0 :         zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
    3315             :         /* proto */
    3316           0 :         stream_putc(s, zclient->redist_default);
    3317             :         /* instance */
    3318           0 :         stream_putw(s, zclient->instance);
    3319           0 :         stream_putc(s, keep);
    3320           0 :         stream_putl(s, chunk_size);
    3321           0 :         stream_putl(s, base);
    3322             : 
    3323             :         /* Put length at the first point of the stream. */
    3324           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3325             : 
    3326           0 :         return zclient_send_message(zclient);
    3327             : }
    3328             : 
    3329             : /**
    3330             :  * Function to request a label chunk in a synchronous way
    3331             :  *
    3332             :  * It first writes the request to zclient output buffer and then
    3333             :  * immediately reads the answer from the input buffer.
    3334             :  *
    3335             :  * @param zclient Zclient used to connect to label manager (zebra)
    3336             :  * @param keep Avoid garbage collection
    3337             :  * @param chunk_size Amount of labels requested
    3338             :  * @param start To write first assigned chunk label to
    3339             :  * @param end To write last assigned chunk label to
    3340             :  * @result 0 on success, -1 otherwise
    3341             :  */
    3342           0 : int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t base,
    3343             :                        uint32_t chunk_size, uint32_t *start, uint32_t *end)
    3344             : {
    3345           0 :         int ret;
    3346           0 :         struct stream *s;
    3347           0 :         uint8_t response_keep;
    3348             : 
    3349           0 :         if (zclient_debug)
    3350           0 :                 zlog_debug("Getting Label Chunk");
    3351             : 
    3352           0 :         if (zclient->sock < 0)
    3353             :                 return -1;
    3354             : 
    3355             :         /* send request */
    3356           0 :         s = zclient->obuf;
    3357           0 :         stream_reset(s);
    3358           0 :         zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
    3359             :         /* proto */
    3360           0 :         stream_putc(s, zclient->redist_default);
    3361             :         /* instance */
    3362           0 :         stream_putw(s, zclient->instance);
    3363             :         /* keep */
    3364           0 :         stream_putc(s, keep);
    3365             :         /* chunk size */
    3366           0 :         stream_putl(s, chunk_size);
    3367             :         /* requested chunk base */
    3368           0 :         stream_putl(s, base);
    3369             :         /* Put length at the first point of the stream. */
    3370           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3371             : 
    3372           0 :         ret = writen(zclient->sock, s->data, stream_get_endp(s));
    3373           0 :         if (ret < 0) {
    3374           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
    3375           0 :                 close(zclient->sock);
    3376           0 :                 zclient->sock = -1;
    3377           0 :                 return -1;
    3378             :         }
    3379           0 :         if (ret == 0) {
    3380           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
    3381           0 :                 close(zclient->sock);
    3382           0 :                 zclient->sock = -1;
    3383           0 :                 return -1;
    3384             :         }
    3385           0 :         if (zclient_debug)
    3386           0 :                 zlog_debug("Label chunk request (%d bytes) sent", ret);
    3387             : 
    3388             :         /* read response */
    3389           0 :         if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0)
    3390             :                 return -1;
    3391             : 
    3392             :         /* parse response */
    3393           0 :         s = zclient->ibuf;
    3394             : 
    3395             :         /* read proto and instance */
    3396           0 :         uint8_t proto;
    3397           0 :         uint8_t instance;
    3398             : 
    3399           0 :         STREAM_GETC(s, proto);
    3400           0 :         STREAM_GETW(s, instance);
    3401             : 
    3402             :         /* sanities */
    3403           0 :         if (proto != zclient->redist_default)
    3404           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3405             :                          "Wrong proto (%u) in get chunk response. Should be %u",
    3406             :                          proto, zclient->redist_default);
    3407           0 :         if (instance != zclient->instance)
    3408           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3409             :                          "Wrong instId (%u) in get chunk response Should be %u",
    3410             :                          instance, zclient->instance);
    3411             : 
    3412             :         /* if we requested a specific chunk and it could not be allocated, the
    3413             :          * response message will end here
    3414             :          */
    3415           0 :         if (!STREAM_READABLE(s)) {
    3416           0 :                 zlog_info("Unable to assign Label Chunk to %s instance %u",
    3417             :                           zebra_route_string(proto), instance);
    3418           0 :                 return -1;
    3419             :         }
    3420             : 
    3421             :         /* keep */
    3422           0 :         STREAM_GETC(s, response_keep);
    3423             :         /* start and end labels */
    3424           0 :         STREAM_GETL(s, *start);
    3425           0 :         STREAM_GETL(s, *end);
    3426             : 
    3427             :         /* not owning this response */
    3428           0 :         if (keep != response_keep) {
    3429           0 :                 flog_err(
    3430             :                         EC_LIB_ZAPI_ENCODE,
    3431             :                         "Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
    3432             :                         *start, *end, keep, response_keep);
    3433             :         }
    3434             :         /* sanity */
    3435           0 :         if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
    3436           0 :             || *end > MPLS_LABEL_UNRESERVED_MAX) {
    3437           0 :                 flog_err(EC_LIB_ZAPI_ENCODE, "Invalid Label chunk: %u - %u",
    3438             :                          *start, *end);
    3439           0 :                 return -1;
    3440             :         }
    3441             : 
    3442           0 :         if (zclient_debug)
    3443           0 :                 zlog_debug("Label Chunk assign: %u - %u (%u)", *start, *end,
    3444             :                            response_keep);
    3445             : 
    3446             :         return 0;
    3447             : 
    3448             : stream_failure:
    3449             :         return -1;
    3450             : }
    3451             : 
    3452             : /**
    3453             :  * Function to release a label chunk
    3454             :  *
    3455             :  * @param zclient Zclient used to connect to label manager (zebra)
    3456             :  * @param start First label of chunk
    3457             :  * @param end Last label of chunk
    3458             :  * @result 0 on success, -1 otherwise
    3459             :  */
    3460           0 : int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
    3461             :                            uint32_t end)
    3462             : {
    3463           0 :         int ret;
    3464           0 :         struct stream *s;
    3465             : 
    3466           0 :         if (zclient_debug)
    3467           0 :                 zlog_debug("Releasing Label Chunk %u - %u", start, end);
    3468             : 
    3469           0 :         if (zclient->sock < 0)
    3470             :                 return -1;
    3471             : 
    3472             :         /* send request */
    3473           0 :         s = zclient->obuf;
    3474           0 :         stream_reset(s);
    3475           0 :         zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT);
    3476             : 
    3477             :         /* proto */
    3478           0 :         stream_putc(s, zclient->redist_default);
    3479             :         /* instance */
    3480           0 :         stream_putw(s, zclient->instance);
    3481             :         /* start */
    3482           0 :         stream_putl(s, start);
    3483             :         /* end */
    3484           0 :         stream_putl(s, end);
    3485             : 
    3486             :         /* Put length at the first point of the stream. */
    3487           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3488             : 
    3489           0 :         ret = writen(zclient->sock, s->data, stream_get_endp(s));
    3490           0 :         if (ret < 0) {
    3491           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
    3492           0 :                 close(zclient->sock);
    3493           0 :                 zclient->sock = -1;
    3494           0 :                 return -1;
    3495             :         }
    3496           0 :         if (ret == 0) {
    3497           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock connection closed");
    3498           0 :                 close(zclient->sock);
    3499           0 :                 zclient->sock = -1;
    3500           0 :                 return -1;
    3501             :         }
    3502             : 
    3503             :         return 0;
    3504             : }
    3505             : 
    3506             : /**
    3507             :  * Connect to table manager in a synchronous way
    3508             :  *
    3509             :  * It first writes the request to zclient output buffer and then
    3510             :  * immediately reads the answer from the input buffer.
    3511             :  *
    3512             :  * @param zclient Zclient used to connect to table manager (zebra)
    3513             :  * @result Result of response
    3514             :  */
    3515           0 : int tm_table_manager_connect(struct zclient *zclient)
    3516             : {
    3517           0 :         int ret;
    3518           0 :         struct stream *s;
    3519           0 :         uint8_t result;
    3520             : 
    3521           0 :         if (zclient_debug)
    3522           0 :                 zlog_debug("Connecting to Table Manager");
    3523             : 
    3524           0 :         if (zclient->sock < 0)
    3525             :                 return ZCLIENT_SEND_FAILURE;
    3526             : 
    3527             :         /* send request */
    3528           0 :         s = zclient->obuf;
    3529           0 :         stream_reset(s);
    3530           0 :         zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, VRF_DEFAULT);
    3531             : 
    3532             :         /* proto */
    3533           0 :         stream_putc(s, zclient->redist_default);
    3534             :         /* instance */
    3535           0 :         stream_putw(s, zclient->instance);
    3536             : 
    3537             :         /* Put length at the first point of the stream. */
    3538           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3539             : 
    3540           0 :         ret = zclient_send_message(zclient);
    3541           0 :         if (ret == ZCLIENT_SEND_FAILURE)
    3542             :                 return -1;
    3543             : 
    3544           0 :         if (zclient_debug)
    3545           0 :                 zlog_debug("%s: Table manager connect request sent", __func__);
    3546             : 
    3547             :         /* read response */
    3548           0 :         if (zclient_read_sync_response(zclient, ZEBRA_TABLE_MANAGER_CONNECT)
    3549             :             != 0)
    3550             :                 return -1;
    3551             : 
    3552             :         /* result */
    3553           0 :         s = zclient->ibuf;
    3554           0 :         STREAM_GETC(s, result);
    3555           0 :         if (zclient_debug)
    3556           0 :                 zlog_debug(
    3557             :                         "%s: Table Manager connect response received, result %u",
    3558             :                         __func__, result);
    3559             : 
    3560           0 :         return (int)result;
    3561           0 : stream_failure:
    3562           0 :         return -1;
    3563             : }
    3564             : 
    3565             : /**
    3566             :  * Function to request a table chunk in a synchronous way
    3567             :  *
    3568             :  * It first writes the request to zclient output buffer and then
    3569             :  * immediately reads the answer from the input buffer.
    3570             :  *
    3571             :  * @param zclient Zclient used to connect to table manager (zebra)
    3572             :  * @param chunk_size Amount of table requested
    3573             :  * @param start to write first assigned chunk table RT ID to
    3574             :  * @param end To write last assigned chunk table RT ID to
    3575             :  * @result 0 on success, -1 otherwise
    3576             :  */
    3577           0 : int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
    3578             :                        uint32_t *start, uint32_t *end)
    3579             : {
    3580           0 :         int ret;
    3581           0 :         struct stream *s;
    3582             : 
    3583           0 :         if (zclient_debug)
    3584           0 :                 zlog_debug("Getting Table Chunk");
    3585             : 
    3586           0 :         if (zclient->sock < 0)
    3587             :                 return -1;
    3588             : 
    3589             :         /* send request */
    3590           0 :         s = zclient->obuf;
    3591           0 :         stream_reset(s);
    3592           0 :         zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, VRF_DEFAULT);
    3593             :         /* chunk size */
    3594           0 :         stream_putl(s, chunk_size);
    3595             :         /* Put length at the first point of the stream. */
    3596           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3597             : 
    3598           0 :         ret = writen(zclient->sock, s->data, stream_get_endp(s));
    3599           0 :         if (ret < 0) {
    3600           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "%s: can't write to zclient->sock",
    3601             :                          __func__);
    3602           0 :                 close(zclient->sock);
    3603           0 :                 zclient->sock = -1;
    3604           0 :                 return -1;
    3605             :         }
    3606           0 :         if (ret == 0) {
    3607           0 :                 flog_err(EC_LIB_ZAPI_SOCKET,
    3608             :                          "%s: zclient->sock connection closed", __func__);
    3609           0 :                 close(zclient->sock);
    3610           0 :                 zclient->sock = -1;
    3611           0 :                 return -1;
    3612             :         }
    3613           0 :         if (zclient_debug)
    3614           0 :                 zlog_debug("%s: Table chunk request (%d bytes) sent", __func__,
    3615             :                            ret);
    3616             : 
    3617             :         /* read response */
    3618           0 :         if (zclient_read_sync_response(zclient, ZEBRA_GET_TABLE_CHUNK) != 0)
    3619             :                 return -1;
    3620             : 
    3621           0 :         s = zclient->ibuf;
    3622             :         /* start and end table IDs */
    3623           0 :         STREAM_GETL(s, *start);
    3624           0 :         STREAM_GETL(s, *end);
    3625             : 
    3626           0 :         if (zclient_debug)
    3627           0 :                 zlog_debug("Table Chunk assign: %u - %u ", *start, *end);
    3628             : 
    3629             :         return 0;
    3630             : stream_failure:
    3631             :         return -1;
    3632             : }
    3633             : 
    3634             : /**
    3635             :  * Function to release a table chunk
    3636             :  *
    3637             :  * @param zclient Zclient used to connect to table manager (zebra)
    3638             :  * @param start First label of table
    3639             :  * @param end Last label of chunk
    3640             :  * @result 0 on success, -1 otherwise
    3641             :  */
    3642           0 : int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
    3643             :                            uint32_t end)
    3644             : {
    3645           0 :         struct stream *s;
    3646             : 
    3647           0 :         if (zclient_debug)
    3648           0 :                 zlog_debug("Releasing Table Chunk");
    3649             : 
    3650           0 :         if (zclient->sock < 0)
    3651             :                 return -1;
    3652             : 
    3653             :         /* send request */
    3654           0 :         s = zclient->obuf;
    3655           0 :         stream_reset(s);
    3656           0 :         zclient_create_header(s, ZEBRA_RELEASE_TABLE_CHUNK, VRF_DEFAULT);
    3657             : 
    3658             :         /* start */
    3659           0 :         stream_putl(s, start);
    3660             :         /* end */
    3661           0 :         stream_putl(s, end);
    3662             : 
    3663             :         /* Put length at the first point of the stream. */
    3664           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3665             : 
    3666           0 :         if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
    3667             :                 return -1;
    3668             : 
    3669             :         return 0;
    3670             : }
    3671             : 
    3672           0 : enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd,
    3673             :                                               struct zapi_sr_policy *zp)
    3674             : {
    3675           0 :         if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
    3676             :                 return ZCLIENT_SEND_FAILURE;
    3677           0 :         return zclient_send_message(zclient);
    3678             : }
    3679             : 
    3680           0 : int zapi_sr_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
    3681             : {
    3682           0 :         struct zapi_srte_tunnel *zt = &zp->segment_list;
    3683             : 
    3684           0 :         stream_reset(s);
    3685             : 
    3686           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    3687           0 :         stream_putl(s, zp->color);
    3688           0 :         stream_put_ipaddr(s, &zp->endpoint);
    3689           0 :         stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);
    3690             : 
    3691           0 :         stream_putc(s, zt->type);
    3692           0 :         stream_putl(s, zt->local_label);
    3693             : 
    3694           0 :         if (zt->label_num > MPLS_MAX_LABELS) {
    3695           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3696             :                          "%s: label %u: can't encode %u labels (maximum is %u)",
    3697             :                          __func__, zt->local_label, zt->label_num,
    3698             :                          MPLS_MAX_LABELS);
    3699           0 :                 return -1;
    3700             :         }
    3701           0 :         stream_putw(s, zt->label_num);
    3702             : 
    3703           0 :         for (int i = 0; i < zt->label_num; i++)
    3704           0 :                 stream_putl(s, zt->labels[i]);
    3705             : 
    3706             :         /* Put length at the first point of the stream. */
    3707           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3708             : 
    3709           0 :         return 0;
    3710             : }
    3711             : 
    3712           0 : int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
    3713             : {
    3714           0 :         memset(zp, 0, sizeof(*zp));
    3715             : 
    3716           0 :         struct zapi_srte_tunnel *zt = &zp->segment_list;
    3717             : 
    3718           0 :         STREAM_GETL(s, zp->color);
    3719           0 :         STREAM_GET_IPADDR(s, &zp->endpoint);
    3720           0 :         STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
    3721             : 
    3722             :         /* segment list of active candidate path */
    3723           0 :         STREAM_GETC(s, zt->type);
    3724           0 :         STREAM_GETL(s, zt->local_label);
    3725           0 :         STREAM_GETW(s, zt->label_num);
    3726           0 :         if (zt->label_num > MPLS_MAX_LABELS) {
    3727           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    3728             :                          "%s: label %u: can't decode %u labels (maximum is %u)",
    3729             :                          __func__, zt->local_label, zt->label_num,
    3730             :                          MPLS_MAX_LABELS);
    3731           0 :                 return -1;
    3732             :         }
    3733           0 :         for (int i = 0; i < zt->label_num; i++)
    3734           0 :                 STREAM_GETL(s, zt->labels[i]);
    3735             : 
    3736             :         return 0;
    3737             : 
    3738             : stream_failure:
    3739             :         return -1;
    3740             : }
    3741             : 
    3742           0 : int zapi_sr_policy_notify_status_decode(struct stream *s,
    3743             :                                         struct zapi_sr_policy *zp)
    3744             : {
    3745           0 :         memset(zp, 0, sizeof(*zp));
    3746             : 
    3747           0 :         STREAM_GETL(s, zp->color);
    3748           0 :         STREAM_GET_IPADDR(s, &zp->endpoint);
    3749           0 :         STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
    3750           0 :         STREAM_GETL(s, zp->status);
    3751             : 
    3752           0 :         return 0;
    3753             : 
    3754             : stream_failure:
    3755             :         return -1;
    3756             : }
    3757             : 
    3758           0 : enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
    3759             :                                                 int cmd, struct zapi_labels *zl)
    3760             : {
    3761           0 :         if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0)
    3762             :                 return ZCLIENT_SEND_FAILURE;
    3763           0 :         return zclient_send_message(zclient);
    3764             : }
    3765             : 
    3766           0 : int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
    3767             : {
    3768           0 :         struct zapi_nexthop *znh;
    3769             : 
    3770           0 :         stream_reset(s);
    3771             : 
    3772           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    3773           0 :         stream_putc(s, zl->message);
    3774           0 :         stream_putc(s, zl->type);
    3775           0 :         stream_putl(s, zl->local_label);
    3776             : 
    3777           0 :         if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
    3778           0 :                 stream_putw(s, zl->route.prefix.family);
    3779           0 :                 stream_put_prefix(s, &zl->route.prefix);
    3780           0 :                 stream_putc(s, zl->route.type);
    3781           0 :                 stream_putw(s, zl->route.instance);
    3782             :         }
    3783             : 
    3784           0 :         if (zl->nexthop_num > MULTIPATH_NUM) {
    3785           0 :                 flog_err(
    3786             :                         EC_LIB_ZAPI_ENCODE,
    3787             :                         "%s: label %u: can't encode %u nexthops (maximum is %u)",
    3788             :                         __func__, zl->local_label, zl->nexthop_num,
    3789             :                         MULTIPATH_NUM);
    3790           0 :                 return -1;
    3791             :         }
    3792           0 :         stream_putw(s, zl->nexthop_num);
    3793             : 
    3794           0 :         for (int i = 0; i < zl->nexthop_num; i++) {
    3795           0 :                 znh = &zl->nexthops[i];
    3796             : 
    3797           0 :                 if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
    3798             :                         return -1;
    3799             :         }
    3800             : 
    3801           0 :         if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
    3802             : 
    3803           0 :                 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
    3804           0 :                         flog_err(
    3805             :                                 EC_LIB_ZAPI_ENCODE,
    3806             :                                 "%s: label %u: can't encode %u nexthops (maximum is %u)",
    3807             :                                 __func__, zl->local_label, zl->nexthop_num,
    3808             :                                 MULTIPATH_NUM);
    3809           0 :                         return -1;
    3810             :                 }
    3811           0 :                 stream_putw(s, zl->backup_nexthop_num);
    3812             : 
    3813           0 :                 for (int i = 0; i < zl->backup_nexthop_num; i++) {
    3814           0 :                         znh = &zl->backup_nexthops[i];
    3815             : 
    3816           0 :                         if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
    3817             :                                 return -1;
    3818             :                 }
    3819             : 
    3820             :         }
    3821             : 
    3822             :         /* Put length at the first point of the stream. */
    3823           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3824             : 
    3825           0 :         return 0;
    3826             : }
    3827             : 
    3828           0 : int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
    3829             : {
    3830           0 :         struct zapi_nexthop *znh;
    3831             : 
    3832           0 :         memset(zl, 0, sizeof(*zl));
    3833             : 
    3834             :         /* Get data. */
    3835           0 :         STREAM_GETC(s, zl->message);
    3836           0 :         STREAM_GETC(s, zl->type);
    3837           0 :         STREAM_GETL(s, zl->local_label);
    3838             : 
    3839           0 :         if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
    3840           0 :                 size_t psize;
    3841             : 
    3842           0 :                 STREAM_GETW(s, zl->route.prefix.family);
    3843           0 :                 STREAM_GETC(s, zl->route.prefix.prefixlen);
    3844             : 
    3845           0 :                 psize = PSIZE(zl->route.prefix.prefixlen);
    3846           0 :                 switch (zl->route.prefix.family) {
    3847           0 :                 case AF_INET:
    3848           0 :                         if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
    3849           0 :                                 zlog_debug(
    3850             :                                         "%s: Specified prefix length %d is greater than a v4 address can support",
    3851             :                                         __func__, zl->route.prefix.prefixlen);
    3852           0 :                                 return -1;
    3853             :                         }
    3854           0 :                         STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
    3855             :                                    psize);
    3856             :                         break;
    3857           0 :                 case AF_INET6:
    3858           0 :                         if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
    3859           0 :                                 zlog_debug(
    3860             :                                         "%s: Specified prefix length %d is greater than a v6 address can support",
    3861             :                                         __func__, zl->route.prefix.prefixlen);
    3862           0 :                                 return -1;
    3863             :                         }
    3864           0 :                         STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
    3865             :                         break;
    3866           0 :                 default:
    3867           0 :                         flog_err(EC_LIB_ZAPI_ENCODE,
    3868             :                                  "%s: Specified family %u is not v4 or v6",
    3869             :                                  __func__, zl->route.prefix.family);
    3870           0 :                         return -1;
    3871             :                 }
    3872             : 
    3873           0 :                 STREAM_GETC(s, zl->route.type);
    3874           0 :                 STREAM_GETW(s, zl->route.instance);
    3875             :         }
    3876             : 
    3877           0 :         STREAM_GETW(s, zl->nexthop_num);
    3878             : 
    3879           0 :         if (zl->nexthop_num > MULTIPATH_NUM) {
    3880           0 :                 flog_warn(
    3881             :                         EC_LIB_ZAPI_ENCODE,
    3882             :                         "%s: Prefix %pFX has %d nexthops, but we can only use the first %d",
    3883             :                         __func__, &zl->route.prefix, zl->nexthop_num,
    3884             :                         MULTIPATH_NUM);
    3885             :         }
    3886             : 
    3887           0 :         zl->nexthop_num = MIN(MULTIPATH_NUM, zl->nexthop_num);
    3888             : 
    3889           0 :         for (int i = 0; i < zl->nexthop_num; i++) {
    3890           0 :                 znh = &zl->nexthops[i];
    3891             : 
    3892           0 :                 if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
    3893             :                         return -1;
    3894             : 
    3895           0 :                 if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
    3896           0 :                         flog_warn(
    3897             :                                 EC_LIB_ZAPI_ENCODE,
    3898             :                                 "%s: Prefix %pFX has a blackhole nexthop which we cannot use for a label",
    3899             :                                 __func__, &zl->route.prefix);
    3900           0 :                         return -1;
    3901             :                 }
    3902             :         }
    3903             : 
    3904           0 :         if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
    3905           0 :                 STREAM_GETW(s, zl->backup_nexthop_num);
    3906             : 
    3907           0 :                 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
    3908           0 :                         flog_warn(
    3909             :                                 EC_LIB_ZAPI_ENCODE,
    3910             :                                 "%s: Prefix %pFX has %d backup nexthops, but we can only use the first %d",
    3911             :                                 __func__, &zl->route.prefix,
    3912             :                                 zl->backup_nexthop_num,      MULTIPATH_NUM);
    3913             :                 }
    3914             : 
    3915           0 :                 zl->backup_nexthop_num = MIN(MULTIPATH_NUM,
    3916             :                                              zl->backup_nexthop_num);
    3917             : 
    3918           0 :                 for (int i = 0; i < zl->backup_nexthop_num; i++) {
    3919           0 :                         znh = &zl->backup_nexthops[i];
    3920             : 
    3921           0 :                         if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
    3922             :                                 return -1;
    3923             : 
    3924           0 :                         if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
    3925           0 :                                 flog_warn(
    3926             :                                         EC_LIB_ZAPI_ENCODE,
    3927             :                                         "%s: Prefix %pFX has a backup blackhole nexthop which we cannot use for a label",
    3928             :                                         __func__, &zl->route.prefix);
    3929           0 :                                 return -1;
    3930             :                         }
    3931             :                 }
    3932             :         }
    3933             : 
    3934             :         return 0;
    3935             : stream_failure:
    3936             :         return -1;
    3937             : }
    3938             : 
    3939           0 : enum zclient_send_status zebra_send_pw(struct zclient *zclient, int command,
    3940             :                                        struct zapi_pw *pw)
    3941             : {
    3942           0 :         struct stream *s;
    3943             : 
    3944             :         /* Reset stream. */
    3945           0 :         s = zclient->obuf;
    3946           0 :         stream_reset(s);
    3947             : 
    3948           0 :         zclient_create_header(s, command, VRF_DEFAULT);
    3949           0 :         stream_write(s, pw->ifname, INTERFACE_NAMSIZ);
    3950           0 :         stream_putl(s, pw->ifindex);
    3951             : 
    3952             :         /* Put type */
    3953           0 :         stream_putl(s, pw->type);
    3954             : 
    3955             :         /* Put nexthop */
    3956           0 :         stream_putl(s, pw->af);
    3957           0 :         switch (pw->af) {
    3958           0 :         case AF_INET:
    3959           0 :                 stream_put_in_addr(s, &pw->nexthop.ipv4);
    3960           0 :                 break;
    3961           0 :         case AF_INET6:
    3962           0 :                 stream_write(s, (uint8_t *)&pw->nexthop.ipv6, 16);
    3963           0 :                 break;
    3964           0 :         default:
    3965           0 :                 flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__);
    3966           0 :                 return ZCLIENT_SEND_FAILURE;
    3967             :         }
    3968             : 
    3969             :         /* Put labels */
    3970           0 :         stream_putl(s, pw->local_label);
    3971           0 :         stream_putl(s, pw->remote_label);
    3972             : 
    3973             :         /* Put flags */
    3974           0 :         stream_putc(s, pw->flags);
    3975             : 
    3976             :         /* Protocol specific fields */
    3977           0 :         stream_write(s, &pw->data, sizeof(union pw_protocol_fields));
    3978             : 
    3979             :         /* Put length at the first point of the stream. */
    3980           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3981             : 
    3982           0 :         return zclient_send_message(zclient);
    3983             : }
    3984             : 
    3985             : /*
    3986             :  * Receive PW status update from Zebra and send it to LDE process.
    3987             :  */
    3988           0 : int zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw)
    3989             : {
    3990           0 :         struct stream *s;
    3991             : 
    3992           0 :         memset(pw, 0, sizeof(struct zapi_pw_status));
    3993           0 :         s = zclient->ibuf;
    3994             : 
    3995             :         /* Get data. */
    3996           0 :         stream_get(pw->ifname, s, INTERFACE_NAMSIZ);
    3997           0 :         STREAM_GETL(s, pw->ifindex);
    3998           0 :         STREAM_GETL(s, pw->status);
    3999             : 
    4000           0 :         return 0;
    4001             : stream_failure:
    4002             :         return -1;
    4003             : }
    4004             : 
    4005           4 : static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
    4006             : {
    4007           4 :         struct zclient_capabilities cap;
    4008           4 :         struct stream *s = zclient->ibuf;
    4009           4 :         int vrf_backend;
    4010           4 :         uint8_t mpls_enabled;
    4011             : 
    4012           4 :         STREAM_GETL(s, vrf_backend);
    4013             : 
    4014           4 :         if (vrf_backend < 0 || vrf_configure_backend(vrf_backend)) {
    4015           0 :                 flog_err(EC_LIB_ZAPI_ENCODE,
    4016             :                          "%s: Garbage VRF backend type: %d", __func__,
    4017             :                          vrf_backend);
    4018           0 :                 goto stream_failure;
    4019             :         }
    4020             : 
    4021             : 
    4022           4 :         memset(&cap, 0, sizeof(cap));
    4023           4 :         STREAM_GETC(s, mpls_enabled);
    4024           4 :         cap.mpls_enabled = !!mpls_enabled;
    4025           4 :         STREAM_GETL(s, cap.ecmp);
    4026           4 :         STREAM_GETC(s, cap.role);
    4027           4 :         STREAM_GETC(s, cap.v6_with_v4_nexthop);
    4028             : 
    4029           4 :         if (zclient->zebra_capabilities)
    4030           2 :                 (*zclient->zebra_capabilities)(&cap);
    4031             : 
    4032           2 : stream_failure:
    4033           4 :         return 0;
    4034             : }
    4035             : 
    4036           0 : enum zclient_send_status zclient_send_mlag_register(struct zclient *client,
    4037             :                                                     uint32_t bit_map)
    4038             : {
    4039           0 :         struct stream *s;
    4040             : 
    4041           0 :         s = client->obuf;
    4042           0 :         stream_reset(s);
    4043             : 
    4044           0 :         zclient_create_header(s, ZEBRA_MLAG_CLIENT_REGISTER, VRF_DEFAULT);
    4045           0 :         stream_putl(s, bit_map);
    4046             : 
    4047           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4048           0 :         return zclient_send_message(client);
    4049             : }
    4050             : 
    4051           0 : enum zclient_send_status zclient_send_mlag_deregister(struct zclient *client)
    4052             : {
    4053           0 :         return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER,
    4054             :                                   VRF_DEFAULT);
    4055             : }
    4056             : 
    4057           0 : enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
    4058             :                                                 struct stream *client_s)
    4059             : {
    4060           0 :         struct stream *s;
    4061             : 
    4062           0 :         s = client->obuf;
    4063           0 :         stream_reset(s);
    4064             : 
    4065           0 :         zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
    4066           0 :         stream_put(s, client_s->data, client_s->endp);
    4067             : 
    4068           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4069           0 :         return zclient_send_message(client);
    4070             : }
    4071             : 
    4072             : /*
    4073             :  * Init/header setup for opaque zapi messages
    4074             :  */
    4075           0 : enum zclient_send_status zapi_opaque_init(struct zclient *zclient,
    4076             :                                           uint32_t type, uint16_t flags)
    4077             : {
    4078           0 :         struct stream *s;
    4079             : 
    4080           0 :         s = zclient->obuf;
    4081           0 :         stream_reset(s);
    4082             : 
    4083           0 :         zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
    4084             : 
    4085             :         /* Send sub-type and flags */
    4086           0 :         stream_putl(s, type);
    4087           0 :         stream_putw(s, flags);
    4088             : 
    4089             :         /* Source daemon identifiers */
    4090           0 :         stream_putc(s, zclient->redist_default);
    4091           0 :         stream_putw(s, zclient->instance);
    4092           0 :         stream_putl(s, zclient->session_id);
    4093             : 
    4094           0 :         return ZCLIENT_SEND_SUCCESS;
    4095             : }
    4096             : 
    4097             : /*
    4098             :  * Init, header setup for opaque unicast messages.
    4099             :  */
    4100             : enum zclient_send_status
    4101           0 : zapi_opaque_unicast_init(struct zclient *zclient, uint32_t type, uint16_t flags,
    4102             :                          uint8_t proto, uint16_t instance, uint32_t session_id)
    4103             : {
    4104           0 :         struct stream *s;
    4105             : 
    4106           0 :         s = zclient->obuf;
    4107             : 
    4108             :         /* Common init */
    4109           0 :         zapi_opaque_init(zclient, type, flags | ZAPI_OPAQUE_FLAG_UNICAST);
    4110             : 
    4111             :         /* Send destination client info */
    4112           0 :         stream_putc(s, proto);
    4113           0 :         stream_putw(s, instance);
    4114           0 :         stream_putl(s, session_id);
    4115             : 
    4116           0 :         return ZCLIENT_SEND_SUCCESS;
    4117             : }
    4118             : 
    4119             : /*
    4120             :  * Send an OPAQUE message, contents opaque to zebra. The message header
    4121             :  * is a message subtype.
    4122             :  */
    4123           0 : enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
    4124             :                                              uint32_t type, const uint8_t *data,
    4125             :                                              size_t datasize)
    4126             : {
    4127           0 :         struct stream *s;
    4128           0 :         uint16_t flags = 0;
    4129             : 
    4130             :         /* Check buffer size */
    4131           0 :         if (STREAM_SIZE(zclient->obuf) <
    4132           0 :             (ZEBRA_HEADER_SIZE + sizeof(type) + datasize))
    4133             :                 return ZCLIENT_SEND_FAILURE;
    4134             : 
    4135           0 :         s = zclient->obuf;
    4136             : 
    4137           0 :         zapi_opaque_init(zclient, type, flags);
    4138             : 
    4139             :         /* Send opaque data */
    4140           0 :         if (datasize > 0)
    4141           0 :                 stream_write(s, data, datasize);
    4142             : 
    4143             :         /* Put length into the header at the start of the stream. */
    4144           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4145             : 
    4146           0 :         return zclient_send_message(zclient);
    4147             : }
    4148             : 
    4149             : /*
    4150             :  * Send an OPAQUE message to a specific zclient. The contents are opaque
    4151             :  * to zebra.
    4152             :  */
    4153             : enum zclient_send_status
    4154           0 : zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
    4155             :                             uint8_t proto, uint16_t instance,
    4156             :                             uint32_t session_id, const uint8_t *data,
    4157             :                             size_t datasize)
    4158             : {
    4159           0 :         struct stream *s;
    4160           0 :         uint16_t flags = 0;
    4161             : 
    4162             :         /* Check buffer size */
    4163           0 :         if (STREAM_SIZE(zclient->obuf) <
    4164           0 :             (ZEBRA_HEADER_SIZE + sizeof(struct zapi_opaque_msg) + datasize))
    4165             :                 return ZCLIENT_SEND_FAILURE;
    4166             : 
    4167           0 :         s = zclient->obuf;
    4168             : 
    4169             :         /* Common init */
    4170           0 :         zapi_opaque_unicast_init(zclient, type, flags, proto, instance,
    4171             :                                  session_id);
    4172             : 
    4173             :         /* Send opaque data */
    4174           0 :         if (datasize > 0)
    4175           0 :                 stream_write(s, data, datasize);
    4176             : 
    4177             :         /* Put length into the header at the start of the stream. */
    4178           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4179             : 
    4180           0 :         return zclient_send_message(zclient);
    4181             : }
    4182             : 
    4183             : /*
    4184             :  * Decode incoming opaque message into info struct
    4185             :  */
    4186           0 : int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
    4187             : {
    4188           0 :         memset(info, 0, sizeof(*info));
    4189             : 
    4190             :         /* Decode subtype and flags */
    4191           0 :         STREAM_GETL(s, info->type);
    4192           0 :         STREAM_GETW(s, info->flags);
    4193             : 
    4194             :         /* Decode sending daemon info */
    4195           0 :         STREAM_GETC(s, info->src_proto);
    4196           0 :         STREAM_GETW(s, info->src_instance);
    4197           0 :         STREAM_GETL(s, info->src_session_id);
    4198             : 
    4199             :         /* Decode unicast destination info, if present */
    4200           0 :         if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
    4201           0 :                 STREAM_GETC(s, info->dest_proto);
    4202           0 :                 STREAM_GETW(s, info->dest_instance);
    4203           0 :                 STREAM_GETL(s, info->dest_session_id);
    4204             :         }
    4205             : 
    4206           0 :         info->len = STREAM_READABLE(s);
    4207             : 
    4208           0 :         return 0;
    4209             : 
    4210             : stream_failure:
    4211             : 
    4212             :         return -1;
    4213             : }
    4214             : 
    4215             : /*
    4216             :  * Send a registration request for opaque messages with a specified subtype.
    4217             :  */
    4218           0 : enum zclient_send_status zclient_register_opaque(struct zclient *zclient,
    4219             :                                                  uint32_t type)
    4220             : {
    4221           0 :         struct stream *s;
    4222             : 
    4223           0 :         s = zclient->obuf;
    4224           0 :         stream_reset(s);
    4225             : 
    4226           0 :         zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
    4227             : 
    4228             :         /* Send sub-type */
    4229           0 :         stream_putl(s, type);
    4230             : 
    4231             :         /* Add zclient info */
    4232           0 :         stream_putc(s, zclient->redist_default);
    4233           0 :         stream_putw(s, zclient->instance);
    4234           0 :         stream_putl(s, zclient->session_id);
    4235             : 
    4236             :         /* Put length at the first point of the stream. */
    4237           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4238             : 
    4239           0 :         return zclient_send_message(zclient);
    4240             : }
    4241             : 
    4242             : /*
    4243             :  * Send an un-registration request for a specified opaque subtype.
    4244             :  */
    4245           0 : enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient,
    4246             :                                                    uint32_t type)
    4247             : {
    4248           0 :         struct stream *s;
    4249             : 
    4250           0 :         s = zclient->obuf;
    4251           0 :         stream_reset(s);
    4252             : 
    4253           0 :         zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
    4254             : 
    4255             :         /* Send sub-type */
    4256           0 :         stream_putl(s, type);
    4257             : 
    4258             :         /* Add zclient info */
    4259           0 :         stream_putc(s, zclient->redist_default);
    4260           0 :         stream_putw(s, zclient->instance);
    4261           0 :         stream_putl(s, zclient->session_id);
    4262             : 
    4263             :         /* Put length at the first point of the stream. */
    4264           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4265             : 
    4266           0 :         return zclient_send_message(zclient);
    4267             : }
    4268             : 
    4269             : /* Utility to decode opaque registration info */
    4270           0 : int zapi_opaque_reg_decode(struct stream *s, struct zapi_opaque_reg_info *info)
    4271             : {
    4272           0 :         STREAM_GETL(s, info->type);
    4273           0 :         STREAM_GETC(s, info->proto);
    4274           0 :         STREAM_GETW(s, info->instance);
    4275           0 :         STREAM_GETL(s, info->session_id);
    4276             : 
    4277           0 :         return 0;
    4278             : 
    4279             : stream_failure:
    4280             : 
    4281             :         return -1;
    4282             : }
    4283             : 
    4284             : /* Utility to decode client close notify info */
    4285           0 : int zapi_client_close_notify_decode(struct stream *s,
    4286             :                                     struct zapi_client_close_info *info)
    4287             : {
    4288           0 :         memset(info, 0, sizeof(*info));
    4289             : 
    4290           0 :         STREAM_GETC(s, info->proto);
    4291           0 :         STREAM_GETW(s, info->instance);
    4292           0 :         STREAM_GETL(s, info->session_id);
    4293             : 
    4294           0 :         return 0;
    4295             : 
    4296             : stream_failure:
    4297             : 
    4298             :         return -1;
    4299             : }
    4300             : 
    4301             : static zclient_handler *const lib_handlers[] = {
    4302             :         /* fundamentals */
    4303             :         [ZEBRA_CAPABILITIES] = zclient_capability_decode,
    4304             :         [ZEBRA_ERROR] = zclient_handle_error,
    4305             : 
    4306             :         /* VRF & interface code is shared in lib */
    4307             :         [ZEBRA_VRF_ADD] = zclient_vrf_add,
    4308             :         [ZEBRA_VRF_DELETE] = zclient_vrf_delete,
    4309             :         [ZEBRA_INTERFACE_ADD] = zclient_interface_add,
    4310             :         [ZEBRA_INTERFACE_DELETE] = zclient_interface_delete,
    4311             :         [ZEBRA_INTERFACE_UP] = zclient_interface_up,
    4312             :         [ZEBRA_INTERFACE_DOWN] = zclient_interface_down,
    4313             : 
    4314             :         /* BFD */
    4315             :         [ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_replay,
    4316             :         [ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update,
    4317             : };
    4318             : 
    4319             : /* Zebra client message read function. */
    4320         165 : static void zclient_read(struct event *thread)
    4321             : {
    4322         165 :         size_t already;
    4323         165 :         uint16_t length, command;
    4324         165 :         uint8_t marker, version;
    4325         165 :         vrf_id_t vrf_id;
    4326         165 :         struct zclient *zclient;
    4327             : 
    4328             :         /* Get socket to zebra. */
    4329         165 :         zclient = EVENT_ARG(thread);
    4330         165 :         zclient->t_read = NULL;
    4331             : 
    4332             :         /* Read zebra header (if we don't have it already). */
    4333         165 :         already = stream_get_endp(zclient->ibuf);
    4334         165 :         if (already < ZEBRA_HEADER_SIZE) {
    4335         165 :                 ssize_t nbyte;
    4336         165 :                 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
    4337             :                                               ZEBRA_HEADER_SIZE - already))
    4338             :                      == 0)
    4339         165 :                     || (nbyte == -1)) {
    4340           0 :                         if (zclient_debug)
    4341           0 :                                 zlog_debug(
    4342             :                                         "zclient connection closed socket [%d].",
    4343             :                                         zclient->sock);
    4344           0 :                         zclient_failed(zclient);
    4345           0 :                         return;
    4346             :                 }
    4347         165 :                 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
    4348           0 :                         zclient_event(ZCLIENT_READ, zclient);
    4349           0 :                         return;
    4350             :                 }
    4351             :                 already = ZEBRA_HEADER_SIZE;
    4352             :         }
    4353             : 
    4354             :         /* Reset to read from the beginning of the incoming packet. */
    4355         165 :         stream_set_getp(zclient->ibuf, 0);
    4356             : 
    4357             :         /* Fetch header values. */
    4358         165 :         length = stream_getw(zclient->ibuf);
    4359         165 :         marker = stream_getc(zclient->ibuf);
    4360         165 :         version = stream_getc(zclient->ibuf);
    4361         165 :         vrf_id = stream_getl(zclient->ibuf);
    4362         165 :         command = stream_getw(zclient->ibuf);
    4363             : 
    4364         165 :         if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
    4365           0 :                 flog_err(
    4366             :                         EC_LIB_ZAPI_MISSMATCH,
    4367             :                         "%s: socket %d version mismatch, marker %d, version %d",
    4368             :                         __func__, zclient->sock, marker, version);
    4369           0 :                 zclient_failed(zclient);
    4370           0 :                 return;
    4371             :         }
    4372             : 
    4373         165 :         if (length < ZEBRA_HEADER_SIZE) {
    4374           0 :                 flog_err(EC_LIB_ZAPI_MISSMATCH,
    4375             :                          "%s: socket %d message length %u is less than %d ",
    4376             :                          __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
    4377           0 :                 zclient_failed(zclient);
    4378           0 :                 return;
    4379             :         }
    4380             : 
    4381             :         /* Length check. */
    4382         165 :         if (length > STREAM_SIZE(zclient->ibuf)) {
    4383           0 :                 struct stream *ns;
    4384           0 :                 flog_err(
    4385             :                         EC_LIB_ZAPI_ENCODE,
    4386             :                         "%s: message size %u exceeds buffer size %lu, expanding...",
    4387             :                         __func__, length,
    4388             :                         (unsigned long)STREAM_SIZE(zclient->ibuf));
    4389           0 :                 ns = stream_new(length);
    4390           0 :                 stream_copy(ns, zclient->ibuf);
    4391           0 :                 stream_free(zclient->ibuf);
    4392           0 :                 zclient->ibuf = ns;
    4393             :         }
    4394             : 
    4395             :         /* Read rest of zebra packet. */
    4396         165 :         if (already < length) {
    4397         165 :                 ssize_t nbyte;
    4398         165 :                 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
    4399             :                                               length - already))
    4400             :                      == 0)
    4401         165 :                     || (nbyte == -1)) {
    4402           0 :                         if (zclient_debug)
    4403           0 :                                 zlog_debug(
    4404             :                                         "zclient connection closed socket [%d].",
    4405             :                                         zclient->sock);
    4406           0 :                         zclient_failed(zclient);
    4407           0 :                         return;
    4408             :                 }
    4409         165 :                 if (nbyte != (ssize_t)(length - already)) {
    4410             :                         /* Try again later. */
    4411           0 :                         zclient_event(ZCLIENT_READ, zclient);
    4412           0 :                         return;
    4413             :                 }
    4414             :         }
    4415             : 
    4416         165 :         length -= ZEBRA_HEADER_SIZE;
    4417             : 
    4418         165 :         if (zclient_debug)
    4419           0 :                 zlog_debug("zclient %p command %s VRF %u", zclient,
    4420             :                            zserv_command_string(command), vrf_id);
    4421             : 
    4422         165 :         if (command < array_size(lib_handlers) && lib_handlers[command])
    4423          50 :                 lib_handlers[command](command, zclient, length, vrf_id);
    4424         165 :         if (command < zclient->n_handlers && zclient->handlers[command])
    4425          52 :                 zclient->handlers[command](command, zclient, length, vrf_id);
    4426             : 
    4427         165 :         if (zclient->sock < 0)
    4428             :                 /* Connection was closed during packet processing. */
    4429             :                 return;
    4430             : 
    4431             :         /* Register read thread. */
    4432         165 :         stream_reset(zclient->ibuf);
    4433         165 :         zclient_event(ZCLIENT_READ, zclient);
    4434             : }
    4435             : 
    4436           0 : void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
    4437             :                           int type, unsigned short instance, vrf_id_t vrf_id)
    4438             : {
    4439             : 
    4440           0 :         if (instance) {
    4441           0 :                 if (command == ZEBRA_REDISTRIBUTE_ADD) {
    4442           0 :                         if (redist_check_instance(
    4443             :                                     &zclient->mi_redist[afi][type], instance))
    4444             :                                 return;
    4445           0 :                         redist_add_instance(&zclient->mi_redist[afi][type],
    4446             :                                             instance);
    4447             :                 } else {
    4448           0 :                         if (!redist_check_instance(
    4449             :                                     &zclient->mi_redist[afi][type], instance))
    4450             :                                 return;
    4451           0 :                         redist_del_instance(&zclient->mi_redist[afi][type],
    4452             :                                             instance);
    4453             :                 }
    4454             : 
    4455             :         } else {
    4456           0 :                 if (command == ZEBRA_REDISTRIBUTE_ADD) {
    4457           0 :                         if (vrf_bitmap_check(&zclient->redist[afi][type],
    4458             :                                              vrf_id))
    4459             :                                 return;
    4460           0 :                         vrf_bitmap_set(&zclient->redist[afi][type], vrf_id);
    4461             :                 } else {
    4462           0 :                         if (!vrf_bitmap_check(&zclient->redist[afi][type],
    4463             :                                               vrf_id))
    4464             :                                 return;
    4465           0 :                         vrf_bitmap_unset(&zclient->redist[afi][type], vrf_id);
    4466             :                 }
    4467             :         }
    4468             : 
    4469           0 :         if (zclient->sock > 0)
    4470           0 :                 zebra_redistribute_send(command, zclient, afi, type, instance,
    4471             :                                         vrf_id);
    4472             : }
    4473             : 
    4474             : 
    4475           0 : void zclient_redistribute_default(int command, struct zclient *zclient,
    4476             :                                   afi_t afi, vrf_id_t vrf_id)
    4477             : {
    4478             : 
    4479           0 :         if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) {
    4480           0 :                 if (vrf_bitmap_check(&zclient->default_information[afi],
    4481             :                                      vrf_id))
    4482             :                         return;
    4483           0 :                 vrf_bitmap_set(&zclient->default_information[afi], vrf_id);
    4484             :         } else {
    4485           0 :                 if (!vrf_bitmap_check(&zclient->default_information[afi],
    4486             :                                       vrf_id))
    4487             :                         return;
    4488           0 :                 vrf_bitmap_unset(&zclient->default_information[afi], vrf_id);
    4489             :         }
    4490             : 
    4491           0 :         if (zclient->sock > 0)
    4492           0 :                 zebra_redistribute_default_send(command, zclient, afi, vrf_id);
    4493             : }
    4494             : 
    4495         173 : static void zclient_event(enum zclient_event event, struct zclient *zclient)
    4496             : {
    4497         173 :         switch (event) {
    4498           4 :         case ZCLIENT_SCHEDULE:
    4499           4 :                 event_add_event(zclient->master, zclient_connect, zclient, 0,
    4500             :                                 &zclient->t_connect);
    4501           4 :                 break;
    4502           0 :         case ZCLIENT_CONNECT:
    4503           0 :                 if (zclient_debug)
    4504           0 :                         zlog_debug(
    4505             :                                 "zclient connect failures: %d schedule interval is now %d",
    4506             :                                 zclient->fail, zclient->fail < 3 ? 10 : 60);
    4507           0 :                 event_add_timer(zclient->master, zclient_connect, zclient,
    4508             :                                 zclient->fail < 3 ? 10 : 60,
    4509             :                                 &zclient->t_connect);
    4510           0 :                 break;
    4511         169 :         case ZCLIENT_READ:
    4512         169 :                 zclient->t_read = NULL;
    4513         169 :                 event_add_read(zclient->master, zclient_read, zclient,
    4514             :                                zclient->sock, &zclient->t_read);
    4515         169 :                 break;
    4516             :         }
    4517         173 : }
    4518             : 
    4519           0 : enum zclient_send_status zclient_interface_set_master(struct zclient *client,
    4520             :                                                       struct interface *master,
    4521             :                                                       struct interface *slave)
    4522             : {
    4523           0 :         struct stream *s;
    4524             : 
    4525           0 :         s = client->obuf;
    4526           0 :         stream_reset(s);
    4527             : 
    4528           0 :         zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER,
    4529           0 :                               master->vrf->vrf_id);
    4530             : 
    4531           0 :         stream_putl(s, master->vrf->vrf_id);
    4532           0 :         stream_putl(s, master->ifindex);
    4533           0 :         stream_putl(s, slave->vrf->vrf_id);
    4534           0 :         stream_putl(s, slave->ifindex);
    4535             : 
    4536           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4537           0 :         return zclient_send_message(client);
    4538             : }
    4539             : 
    4540             : /*
    4541             :  * Send capabilities message to zebra
    4542             :  */
    4543          88 : enum zclient_send_status zclient_capabilities_send(uint32_t cmd,
    4544             :                                                    struct zclient *zclient,
    4545             :                                                    struct zapi_cap *api)
    4546             : {
    4547             : 
    4548          88 :         struct stream *s;
    4549             : 
    4550          88 :         if (zclient == NULL)
    4551             :                 return ZCLIENT_SEND_FAILURE;
    4552             : 
    4553          88 :         s = zclient->obuf;
    4554          88 :         stream_reset(s);
    4555          88 :         zclient_create_header(s, cmd, 0);
    4556          88 :         stream_putl(s, api->cap);
    4557             : 
    4558          88 :         switch (api->cap) {
    4559           0 :         case ZEBRA_CLIENT_GR_CAPABILITIES:
    4560             :         case ZEBRA_CLIENT_RIB_STALE_TIME:
    4561           0 :                 stream_putl(s, api->stale_removal_time);
    4562           0 :                 stream_putl(s, api->vrf_id);
    4563           0 :                 break;
    4564          88 :         case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
    4565             :         case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
    4566          88 :                 stream_putl(s, api->afi);
    4567          88 :                 stream_putl(s, api->safi);
    4568          88 :                 stream_putl(s, api->vrf_id);
    4569          88 :                 break;
    4570           0 :         case ZEBRA_CLIENT_GR_DISABLE:
    4571           0 :                 stream_putl(s, api->vrf_id);
    4572           0 :                 break;
    4573             :         }
    4574             : 
    4575             :         /* Put length at the first point of the stream */
    4576          88 :         stream_putw_at(s, 0, stream_get_endp(s));
    4577             : 
    4578          88 :         return zclient_send_message(zclient);
    4579             : }
    4580             : 
    4581             : /*
    4582             :  * Process capabilities message from zebra
    4583             :  */
    4584          88 : int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
    4585             : {
    4586             : 
    4587          88 :         memset(api, 0, sizeof(*api));
    4588             : 
    4589          88 :         api->safi = SAFI_UNICAST;
    4590             : 
    4591          88 :         STREAM_GETL(s, api->cap);
    4592          88 :         switch (api->cap) {
    4593           0 :         case ZEBRA_CLIENT_GR_CAPABILITIES:
    4594             :         case ZEBRA_CLIENT_RIB_STALE_TIME:
    4595           0 :                 STREAM_GETL(s, api->stale_removal_time);
    4596           0 :                 STREAM_GETL(s, api->vrf_id);
    4597           0 :                 break;
    4598          88 :         case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
    4599             :         case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
    4600          88 :                 STREAM_GETL(s, api->afi);
    4601          88 :                 STREAM_GETL(s, api->safi);
    4602          88 :                 STREAM_GETL(s, api->vrf_id);
    4603          88 :                 break;
    4604           0 :         case ZEBRA_CLIENT_GR_DISABLE:
    4605           0 :                 STREAM_GETL(s, api->vrf_id);
    4606           0 :                 break;
    4607             :         }
    4608          88 : stream_failure:
    4609          88 :         return 0;
    4610             : }
    4611             : 
    4612             : enum zclient_send_status
    4613           0 : zclient_send_neigh_discovery_req(struct zclient *zclient,
    4614             :                                  const struct interface *ifp,
    4615             :                                  const struct prefix *p)
    4616             : {
    4617           0 :         struct stream *s;
    4618             : 
    4619           0 :         s = zclient->obuf;
    4620           0 :         stream_reset(s);
    4621             : 
    4622           0 :         zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf->vrf_id);
    4623           0 :         stream_putl(s, ifp->ifindex);
    4624             : 
    4625           0 :         stream_putc(s, p->family);
    4626           0 :         stream_putc(s, p->prefixlen);
    4627           0 :         stream_put(s, &p->u.prefix, prefix_blen(p));
    4628             : 
    4629           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4630           0 :         return zclient_send_message(zclient);
    4631             : }
    4632             : 
    4633             : /*
    4634             :  * Get a starting nhg point for a routing protocol
    4635             :  */
    4636           0 : uint32_t zclient_get_nhg_start(uint32_t proto)
    4637             : {
    4638           0 :         assert(proto < ZEBRA_ROUTE_MAX);
    4639             : 
    4640           0 :         return ZEBRA_NHG_PROTO_SPACING * proto;
    4641             : }
    4642             : 
    4643           0 : char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len)
    4644             : {
    4645           0 :         if (flags == 0) {
    4646           0 :                 snprintfrr(buf, len, "None ");
    4647           0 :                 return buf;
    4648             :         }
    4649             : 
    4650           0 :         snprintfrr(
    4651             :                 buf, len, "%s%s%s%s%s%s%s%s%s%s",
    4652           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
    4653             :                                                               : "",
    4654           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
    4655           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
    4656           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
    4657           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
    4658           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
    4659           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
    4660             :                                                               : "",
    4661           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
    4662           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
    4663           0 :                 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed "
    4664             :                                                              : "");
    4665           0 :         return buf;
    4666             : }
    4667             : 
    4668           0 : char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len)
    4669             : {
    4670           0 :         if (flags == 0) {
    4671           0 :                 snprintfrr(buf, len, "None ");
    4672           0 :                 return buf;
    4673             :         }
    4674             : 
    4675           0 :         snprintfrr(
    4676             :                 buf, len, "%s%s%s%s%s%s%s",
    4677             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? "Sticky MAC " : "",
    4678             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? "Gateway MAC " : "",
    4679             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? "Router "
    4680             :                                                                 : "",
    4681             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_OVERRIDE_FLAG) ? "Override "
    4682             :                                                                   : "",
    4683             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP) ? "SVI MAC " : "",
    4684             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT) ? "Proxy "
    4685             :                                                                  : "",
    4686             :                 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH) ? "Sync " : "");
    4687             : 
    4688           0 :         return buf;
    4689             : }
    4690             : 
    4691           0 : static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add)
    4692             : {
    4693           0 :         uint8_t family;
    4694             : 
    4695           0 :         STREAM_GETC(s, family);
    4696           0 :         if (family != AF_INET && family != AF_INET6)
    4697             :                 return -1;
    4698             : 
    4699           0 :         STREAM_GET(&add->ip.addr, s, family2addrsize(family));
    4700           0 :         add->ipa_type = family;
    4701           0 :         return 0;
    4702             :  stream_failure:
    4703             :         return -1;
    4704             : }
    4705             : 
    4706           0 : int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
    4707             :                             union sockunion *out, struct interface *ifp,
    4708             :                             int ndm_state)
    4709             : {
    4710           0 :         int ret = 0;
    4711             : 
    4712           0 :         zclient_create_header(s, cmd, ifp->vrf->vrf_id);
    4713           0 :         stream_putc(s, sockunion_family(in));
    4714           0 :         stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
    4715           0 :         if (out && sockunion_family(out) != AF_UNSPEC) {
    4716           0 :                 stream_putc(s, sockunion_family(out));
    4717           0 :                 stream_write(s, sockunion_get_addr(out),
    4718             :                              sockunion_get_addrlen(out));
    4719             :         } else
    4720           0 :                 stream_putc(s, AF_UNSPEC);
    4721           0 :         stream_putl(s, ifp->ifindex);
    4722           0 :         if (out)
    4723           0 :                 stream_putl(s, ndm_state);
    4724             :         else
    4725           0 :                 stream_putl(s, ZEBRA_NEIGH_STATE_FAILED);
    4726           0 :         return ret;
    4727             : }
    4728             : 
    4729           0 : int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
    4730             : {
    4731           0 :         int ret;
    4732             : 
    4733           0 :         ret = zclient_neigh_ip_read_entry(s, &api->ip_in);
    4734           0 :         if (ret < 0)
    4735             :                 return -1;
    4736           0 :         zclient_neigh_ip_read_entry(s, &api->ip_out);
    4737             : 
    4738           0 :         STREAM_GETL(s, api->index);
    4739           0 :         STREAM_GETL(s, api->ndm_state);
    4740           0 :         return 0;
    4741             :  stream_failure:
    4742             :         return -1;
    4743             : }
    4744             : 
    4745           0 : int zclient_send_zebra_gre_request(struct zclient *client,
    4746             :                                    struct interface *ifp)
    4747             : {
    4748           0 :         struct stream *s;
    4749             : 
    4750           0 :         if (!client || client->sock < 0) {
    4751           0 :                 zlog_err("%s : zclient not ready", __func__);
    4752           0 :                 return -1;
    4753             :         }
    4754           0 :         s = client->obuf;
    4755           0 :         stream_reset(s);
    4756           0 :         zclient_create_header(s, ZEBRA_GRE_GET, ifp->vrf->vrf_id);
    4757           0 :         stream_putl(s, ifp->ifindex);
    4758           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4759           0 :         zclient_send_message(client);
    4760           0 :         return 0;
    4761             : }
    4762             : 
    4763             : 
    4764             : /*
    4765             :  * Opaque notification features
    4766             :  */
    4767             : 
    4768             : /*
    4769             :  * Common encode helper for opaque notifications, both registration
    4770             :  * and async notification messages.
    4771             :  */
    4772           0 : static int opaque_notif_encode_common(struct stream *s, uint32_t msg_type,
    4773             :                                       bool request, bool reg, uint8_t proto,
    4774             :                                       uint16_t instance, uint32_t session_id)
    4775             : {
    4776           0 :         int ret = 0;
    4777           0 :         uint8_t val = 0;
    4778             : 
    4779           0 :         stream_reset(s);
    4780             : 
    4781           0 :         zclient_create_header(s, ZEBRA_OPAQUE_NOTIFY, VRF_DEFAULT);
    4782             : 
    4783             :         /* Notification or request */
    4784           0 :         if (request)
    4785           0 :                 val = 1;
    4786           0 :         stream_putc(s, val);
    4787             : 
    4788           0 :         if (reg)
    4789             :                 val = 1;
    4790             :         else
    4791           0 :                 val = 0;
    4792           0 :         stream_putc(s, val);
    4793             : 
    4794           0 :         stream_putl(s, msg_type);
    4795             : 
    4796           0 :         stream_putc(s, proto);
    4797           0 :         stream_putw(s, instance);
    4798           0 :         stream_putl(s, session_id);
    4799             : 
    4800             :         /* And capture message length */
    4801           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    4802             : 
    4803           0 :         return ret;
    4804             : }
    4805             : 
    4806             : /*
    4807             :  * Encode a zapi opaque message type notification into buffer 's'
    4808             :  */
    4809           0 : int zclient_opaque_notif_encode(struct stream *s, uint32_t msg_type, bool reg,
    4810             :                                 uint8_t proto, uint16_t instance,
    4811             :                                 uint32_t session_id)
    4812             : {
    4813           0 :         return opaque_notif_encode_common(s, msg_type, false /* !request */,
    4814             :                                           reg, proto, instance, session_id);
    4815             : }
    4816             : 
    4817             : /*
    4818             :  * Decode an incoming zapi opaque message type notification
    4819             :  */
    4820           0 : int zclient_opaque_notif_decode(struct stream *s,
    4821             :                                 struct zapi_opaque_notif_info *info)
    4822             : {
    4823           0 :         uint8_t val;
    4824             : 
    4825           0 :         memset(info, 0, sizeof(*info));
    4826             : 
    4827           0 :         STREAM_GETC(s, val); /* Registration or notification */
    4828           0 :         info->request = (val != 0);
    4829             : 
    4830           0 :         STREAM_GETC(s, val);
    4831           0 :         info->reg = (val != 0);
    4832             : 
    4833           0 :         STREAM_GETL(s, info->msg_type);
    4834             : 
    4835           0 :         STREAM_GETC(s, info->proto);
    4836           0 :         STREAM_GETW(s, info->instance);
    4837           0 :         STREAM_GETL(s, info->session_id);
    4838             : 
    4839           0 :         return 0;
    4840             : 
    4841             : stream_failure:
    4842             :         return -1;
    4843             : }
    4844             : 
    4845             : /*
    4846             :  * Encode and send a zapi opaque message type notification request to zebra
    4847             :  */
    4848           0 : enum zclient_send_status zclient_opaque_request_notify(struct zclient *zclient,
    4849             :                                                        uint32_t msgtype)
    4850             : {
    4851           0 :         struct stream *s;
    4852             : 
    4853           0 :         if (!zclient || zclient->sock < 0)
    4854             :                 return ZCLIENT_SEND_FAILURE;
    4855             : 
    4856           0 :         s = zclient->obuf;
    4857             : 
    4858           0 :         opaque_notif_encode_common(s, msgtype, true /* request */,
    4859           0 :                                    true /* register */, zclient->redist_default,
    4860           0 :                                    zclient->instance, zclient->session_id);
    4861             : 
    4862           0 :         return zclient_send_message(zclient);
    4863             : }
    4864             : 
    4865             : /*
    4866             :  * Encode and send a request to drop notifications for an opaque message type.
    4867             :  */
    4868           0 : enum zclient_send_status zclient_opaque_drop_notify(struct zclient *zclient,
    4869             :                                                     uint32_t msgtype)
    4870             : {
    4871           0 :         struct stream *s;
    4872             : 
    4873           0 :         if (!zclient || zclient->sock < 0)
    4874             :                 return ZCLIENT_SEND_FAILURE;
    4875             : 
    4876           0 :         s = zclient->obuf;
    4877             : 
    4878           0 :         opaque_notif_encode_common(s, msgtype, true /* req */,
    4879           0 :                                    false /* unreg */, zclient->redist_default,
    4880           0 :                                    zclient->instance, zclient->session_id);
    4881             : 
    4882           0 :         return zclient_send_message(zclient);
    4883             : }

Generated by: LCOV version v1.16-topotato