back to topotato report
topotato coverage report
Current view: top level - lib - zclient.c (source / functions) Hit Total Coverage
Test: test_rip.py::RIPBasic Lines: 586 2057 28.5 %
Date: 2023-02-24 18:39:46 Functions: 44 129 34.1 %

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

Generated by: LCOV version v1.16-topotato