back to topotato report
topotato coverage report
Current view: top level - zebra - zapi_msg.c (source / functions) Hit Total Coverage
Test: test_pim_basic2.py::PIMTopo2Test Lines: 212 2037 10.4 %
Date: 2023-02-24 18:39:36 Functions: 21 105 20.0 %

          Line data    Source code
       1             : /*
       2             :  * Zebra API message creation & consumption.
       3             :  * Portions:
       4             :  *   Copyright (C) 1997-1999  Kunihiro Ishiguro
       5             :  *   Copyright (C) 2015-2018  Cumulus Networks, Inc.
       6             :  *   et al.
       7             :  *
       8             :  * This program is free software; you can redistribute it and/or modify it
       9             :  * under the terms of the GNU General Public License as published by the Free
      10             :  * Software Foundation; either version 2 of the License, or (at your option)
      11             :  * any later version.
      12             :  *
      13             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      14             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      16             :  * more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License along
      19             :  * with this program; see the file COPYING; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : #include <libgen.h>
      25             : 
      26             : #include "lib/prefix.h"
      27             : #include "lib/stream.h"
      28             : #include "lib/memory.h"
      29             : #include "lib/table.h"
      30             : #include "lib/network.h"
      31             : #include "lib/log.h"
      32             : #include "lib/zclient.h"
      33             : #include "lib/privs.h"
      34             : #include "lib/nexthop.h"
      35             : #include "lib/vrf.h"
      36             : #include "lib/libfrr.h"
      37             : #include "lib/lib_errors.h"
      38             : 
      39             : #include "zebra/zebra_router.h"
      40             : #include "zebra/rib.h"
      41             : #include "zebra/zebra_ns.h"
      42             : #include "zebra/zebra_vrf.h"
      43             : #include "zebra/router-id.h"
      44             : #include "zebra/redistribute.h"
      45             : #include "zebra/debug.h"
      46             : #include "zebra/zebra_rnh.h"
      47             : #include "zebra/interface.h"
      48             : #include "zebra/zebra_ptm.h"
      49             : #include "zebra/rtadv.h"
      50             : #include "zebra/zebra_mpls.h"
      51             : #include "zebra/zebra_mroute.h"
      52             : #include "zebra/zebra_vxlan.h"
      53             : #include "zebra/zebra_evpn_mh.h"
      54             : #include "zebra/rt.h"
      55             : #include "zebra/zebra_pbr.h"
      56             : #include "zebra/zebra_tc.h"
      57             : #include "zebra/table_manager.h"
      58             : #include "zebra/zapi_msg.h"
      59             : #include "zebra/zebra_errors.h"
      60             : #include "zebra/zebra_mlag.h"
      61             : #include "zebra/connected.h"
      62             : #include "zebra/zebra_opaque.h"
      63             : #include "zebra/zebra_srte.h"
      64             : #include "zebra/zebra_srv6.h"
      65             : 
      66          12 : DEFINE_MTYPE_STATIC(ZEBRA, RE_OPAQUE, "Route Opaque Data");
      67             : 
      68             : static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg);
      69             : 
      70             : /* Encoding helpers -------------------------------------------------------- */
      71             : 
      72         100 : static void zserv_encode_interface(struct stream *s, struct interface *ifp)
      73             : {
      74             :         /* Interface information. */
      75         100 :         struct zebra_if *zif = ifp->info;
      76             : 
      77         100 :         stream_put(s, ifp->name, INTERFACE_NAMSIZ);
      78         100 :         stream_putl(s, ifp->ifindex);
      79         100 :         stream_putc(s, ifp->status);
      80         100 :         stream_putq(s, ifp->flags);
      81         100 :         stream_putc(s, ifp->ptm_enable);
      82         100 :         stream_putc(s, ifp->ptm_status);
      83         100 :         stream_putl(s, ifp->metric);
      84         100 :         stream_putl(s, ifp->speed);
      85         100 :         stream_putl(s, ifp->mtu);
      86         100 :         stream_putl(s, ifp->mtu6);
      87         100 :         stream_putl(s, ifp->bandwidth);
      88         100 :         stream_putl(s, zif->link_ifindex);
      89         100 :         stream_putl(s, ifp->ll_type);
      90         100 :         stream_putl(s, ifp->hw_addr_len);
      91         100 :         if (ifp->hw_addr_len)
      92          52 :                 stream_put(s, ifp->hw_addr, ifp->hw_addr_len);
      93             : 
      94             :         /* Then, Traffic Engineering parameters if any */
      95         100 :         if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) {
      96           0 :                 stream_putc(s, 1);
      97           0 :                 zebra_interface_link_params_write(s, ifp);
      98             :         } else
      99         100 :                 stream_putc(s, 0);
     100             : 
     101             :         /* Write packet size. */
     102         100 :         stream_putw_at(s, 0, stream_get_endp(s));
     103         100 : }
     104             : 
     105           8 : static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
     106             : {
     107           8 :         struct vrf_data data;
     108           8 :         const char *netns_name = zvrf_ns_name(zvrf);
     109             : 
     110           8 :         memset(&data, 0, sizeof(data));
     111           8 :         data.l.table_id = zvrf->table_id;
     112             : 
     113           8 :         if (netns_name)
     114           0 :                 strlcpy(data.l.netns_name, basename((char *)netns_name),
     115             :                         NS_NAMSIZ);
     116             :         else
     117           8 :                 memset(data.l.netns_name, 0, NS_NAMSIZ);
     118             :         /* Pass the tableid and the netns NAME */
     119           8 :         stream_put(s, &data, sizeof(struct vrf_data));
     120             :         /* Interface information. */
     121          16 :         stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ);
     122             :         /* Write packet size. */
     123           8 :         stream_putw_at(s, 0, stream_get_endp(s));
     124           8 : }
     125             : 
     126           0 : static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop)
     127             : {
     128           0 :         stream_putl(s, nexthop->vrf_id);
     129           0 :         stream_putc(s, nexthop->type);
     130           0 :         switch (nexthop->type) {
     131           0 :         case NEXTHOP_TYPE_IPV4:
     132             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
     133           0 :                 stream_put_in_addr(s, &nexthop->gate.ipv4);
     134           0 :                 stream_putl(s, nexthop->ifindex);
     135           0 :                 break;
     136           0 :         case NEXTHOP_TYPE_IPV6:
     137           0 :                 stream_put(s, &nexthop->gate.ipv6, 16);
     138           0 :                 break;
     139           0 :         case NEXTHOP_TYPE_IPV6_IFINDEX:
     140           0 :                 stream_put(s, &nexthop->gate.ipv6, 16);
     141           0 :                 stream_putl(s, nexthop->ifindex);
     142           0 :                 break;
     143           0 :         case NEXTHOP_TYPE_IFINDEX:
     144           0 :                 stream_putl(s, nexthop->ifindex);
     145           0 :                 break;
     146             :         case NEXTHOP_TYPE_BLACKHOLE:
     147             :                 /* do nothing */
     148             :                 break;
     149             :         }
     150           0 :         return 1;
     151             : }
     152             : 
     153             : /*
     154             :  * Zebra error addition adds error type.
     155             :  *
     156             :  *
     157             :  *  0                   1
     158             :  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
     159             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     160             :  * |      enum zebra_error_types   |
     161             :  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     162             :  *
     163             :  */
     164           0 : static void zserv_encode_error(struct stream *s, enum zebra_error_types error)
     165             : {
     166           0 :         stream_put(s, &error, sizeof(error));
     167             : 
     168             :         /* Write packet size. */
     169           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     170           0 : }
     171             : 
     172             : /* Send handlers ----------------------------------------------------------- */
     173             : 
     174             : /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
     175             : /*
     176             :  * This function is called in the following situations:
     177             :  * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
     178             :  *   from the client.
     179             :  * - at startup, when zebra figures out the available interfaces
     180             :  * - when an interface is added (where support for
     181             :  *   RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
     182             :  *   an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
     183             :  *   received)
     184             :  */
     185          48 : int zsend_interface_add(struct zserv *client, struct interface *ifp)
     186             : {
     187          48 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     188             : 
     189          48 :         zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf->vrf_id);
     190          48 :         zserv_encode_interface(s, ifp);
     191             : 
     192          48 :         client->ifadd_cnt++;
     193          48 :         return zserv_send_message(client, s);
     194             : }
     195             : 
     196             : /* Interface deletion from zebra daemon. */
     197           8 : int zsend_interface_delete(struct zserv *client, struct interface *ifp)
     198             : {
     199           8 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     200             : 
     201           8 :         zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf->vrf_id);
     202           8 :         zserv_encode_interface(s, ifp);
     203             : 
     204           8 :         client->ifdel_cnt++;
     205           8 :         return zserv_send_message(client, s);
     206             : }
     207             : 
     208           8 : int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf)
     209             : {
     210           8 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     211             : 
     212          16 :         zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf));
     213           8 :         zserv_encode_vrf(s, zvrf);
     214             : 
     215           8 :         client->vrfadd_cnt++;
     216           8 :         return zserv_send_message(client, s);
     217             : }
     218             : 
     219             : /* VRF deletion from zebra daemon. */
     220           0 : int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf)
     221             : 
     222             : {
     223           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     224             : 
     225           0 :         zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf));
     226           0 :         zserv_encode_vrf(s, zvrf);
     227             : 
     228           0 :         client->vrfdel_cnt++;
     229           0 :         return zserv_send_message(client, s);
     230             : }
     231             : 
     232          70 : int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
     233             : {
     234          70 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     235             : 
     236          70 :         zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf->vrf_id);
     237             : 
     238             :         /* Add Interface Index */
     239          70 :         stream_putl(s, ifp->ifindex);
     240             : 
     241             :         /* Then TE Link Parameters */
     242          70 :         if (zebra_interface_link_params_write(s, ifp) == 0) {
     243           0 :                 stream_free(s);
     244           0 :                 return 0;
     245             :         }
     246             : 
     247             :         /* Write packet size. */
     248          70 :         stream_putw_at(s, 0, stream_get_endp(s));
     249             : 
     250          70 :         return zserv_send_message(client, s);
     251             : }
     252             : 
     253             : /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
     254             :  * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
     255             :  *
     256             :  * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
     257             :  * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
     258             :  *   from the client, after the ZEBRA_INTERFACE_ADD has been
     259             :  *   sent from zebra to the client
     260             :  * - redistribute new address info to all clients in the following situations
     261             :  *    - at startup, when zebra figures out the available interfaces
     262             :  *    - when an interface is added (where support for
     263             :  *      RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
     264             :  *      an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
     265             :  *      received)
     266             :  *    - for the vty commands "ip address A.B.C.D/M [<label LINE>]"
     267             :  *      and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
     268             :  *    - when an RTM_NEWADDR message is received from the kernel,
     269             :  *
     270             :  * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
     271             :  *
     272             :  *                   zsend_interface_address(DELETE)
     273             :  *                           ^
     274             :  *                           |
     275             :  *          zebra_interface_address_delete_update
     276             :  *             ^                        ^      ^
     277             :  *             |                        |      if_delete_update
     278             :  *             |                        |
     279             :  *         ip_address_uninstall        connected_delete_ipv4
     280             :  *         [ipv6_addresss_uninstall]   [connected_delete_ipv6]
     281             :  *             ^                        ^
     282             :  *             |                        |
     283             :  *             |                  RTM_NEWADDR on routing/netlink socket
     284             :  *             |
     285             :  *         vty commands:
     286             :  *     "no ip address A.B.C.D/M [label LINE]"
     287             :  *     "no ip address A.B.C.D/M"
     288             :  *     ["no ipv6 address X:X::X:X/M"]
     289             :  *
     290             :  */
     291         152 : int zsend_interface_address(int cmd, struct zserv *client,
     292             :                             struct interface *ifp, struct connected *ifc)
     293             : {
     294         152 :         int blen;
     295         152 :         struct prefix *p;
     296         152 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     297             : 
     298         152 :         zclient_create_header(s, cmd, ifp->vrf->vrf_id);
     299         152 :         stream_putl(s, ifp->ifindex);
     300             : 
     301             :         /* Interface address flag. */
     302         152 :         stream_putc(s, ifc->flags);
     303             : 
     304             :         /* Prefix information. */
     305         152 :         p = ifc->address;
     306         152 :         stream_putc(s, p->family);
     307         152 :         blen = prefix_blen(p);
     308         152 :         stream_put(s, &p->u.prefix, blen);
     309             : 
     310             :         /*
     311             :          * XXX gnu version does not send prefixlen for
     312             :          * ZEBRA_INTERFACE_ADDRESS_DELETE
     313             :          * but zebra_interface_address_delete_read() in the gnu version
     314             :          * expects to find it
     315             :          */
     316         152 :         stream_putc(s, p->prefixlen);
     317             : 
     318             :         /* Destination. */
     319         152 :         p = ifc->destination;
     320         152 :         if (p)
     321           0 :                 stream_put(s, &p->u.prefix, blen);
     322             :         else
     323         152 :                 stream_put(s, NULL, blen);
     324             : 
     325             :         /* Write packet size. */
     326         152 :         stream_putw_at(s, 0, stream_get_endp(s));
     327             : 
     328         152 :         client->connected_rt_add_cnt++;
     329         152 :         return zserv_send_message(client, s);
     330             : }
     331             : 
     332           0 : static int zsend_interface_nbr_address(int cmd, struct zserv *client,
     333             :                                        struct interface *ifp,
     334             :                                        struct nbr_connected *ifc)
     335             : {
     336           0 :         int blen;
     337           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     338           0 :         struct prefix *p;
     339             : 
     340           0 :         zclient_create_header(s, cmd, ifp->vrf->vrf_id);
     341           0 :         stream_putl(s, ifp->ifindex);
     342             : 
     343             :         /* Prefix information. */
     344           0 :         p = ifc->address;
     345           0 :         stream_putc(s, p->family);
     346           0 :         blen = prefix_blen(p);
     347           0 :         stream_put(s, &p->u.prefix, blen);
     348             : 
     349             :         /*
     350             :          * XXX gnu version does not send prefixlen for
     351             :          * ZEBRA_INTERFACE_ADDRESS_DELETE
     352             :          * but zebra_interface_address_delete_read() in the gnu version
     353             :          * expects to find it
     354             :          */
     355           0 :         stream_putc(s, p->prefixlen);
     356             : 
     357             :         /* Write packet size. */
     358           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     359             : 
     360           0 :         return zserv_send_message(client, s);
     361             : }
     362             : 
     363             : /* Interface address addition. */
     364           0 : static void zebra_interface_nbr_address_add_update(struct interface *ifp,
     365             :                                                    struct nbr_connected *ifc)
     366             : {
     367           0 :         struct listnode *node, *nnode;
     368           0 :         struct zserv *client;
     369           0 :         struct prefix *p;
     370             : 
     371           0 :         if (IS_ZEBRA_DEBUG_EVENT) {
     372           0 :                 char buf[INET6_ADDRSTRLEN];
     373             : 
     374           0 :                 p = ifc->address;
     375           0 :                 zlog_debug(
     376             :                         "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s",
     377             :                         inet_ntop(p->family, &p->u.prefix, buf,
     378             :                                   INET6_ADDRSTRLEN),
     379             :                         p->prefixlen, ifc->ifp->name);
     380             :         }
     381             : 
     382           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     383             :                 /* Do not send unsolicited messages to synchronous clients. */
     384           0 :                 if (client->synchronous)
     385           0 :                         continue;
     386             : 
     387           0 :                 zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
     388             :                                             client, ifp, ifc);
     389             :         }
     390           0 : }
     391             : 
     392             : /* Interface address deletion. */
     393           0 : static void zebra_interface_nbr_address_delete_update(struct interface *ifp,
     394             :                                                       struct nbr_connected *ifc)
     395             : {
     396           0 :         struct listnode *node, *nnode;
     397           0 :         struct zserv *client;
     398           0 :         struct prefix *p;
     399             : 
     400           0 :         if (IS_ZEBRA_DEBUG_EVENT) {
     401           0 :                 char buf[INET6_ADDRSTRLEN];
     402             : 
     403           0 :                 p = ifc->address;
     404           0 :                 zlog_debug(
     405             :                         "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s",
     406             :                         inet_ntop(p->family, &p->u.prefix, buf,
     407             :                                   INET6_ADDRSTRLEN),
     408             :                         p->prefixlen, ifc->ifp->name);
     409             :         }
     410             : 
     411           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
     412             :                 /* Do not send unsolicited messages to synchronous clients. */
     413           0 :                 if (client->synchronous)
     414           0 :                         continue;
     415             : 
     416           0 :                 zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
     417             :                                             client, ifp, ifc);
     418             :         }
     419           0 : }
     420             : 
     421             : /* Send addresses on interface to client */
     422          40 : int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
     423             : {
     424          40 :         struct listnode *cnode, *cnnode;
     425          40 :         struct connected *c;
     426          40 :         struct nbr_connected *nc;
     427             : 
     428             :         /* Send interface addresses. */
     429         160 :         for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
     430          80 :                 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
     431           0 :                         continue;
     432             : 
     433          80 :                 if (zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, client,
     434             :                                             ifp, c)
     435             :                     < 0)
     436             :                         return -1;
     437             :         }
     438             : 
     439             :         /* Send interface neighbors. */
     440          80 :         for (ALL_LIST_ELEMENTS(ifp->nbr_connected, cnode, cnnode, nc)) {
     441           0 :                 if (zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
     442             :                                                 client, ifp, nc)
     443             :                     < 0)
     444             :                         return -1;
     445             :         }
     446             : 
     447             :         return 0;
     448             : }
     449             : 
     450             : /* Notify client about interface moving from one VRF to another.
     451             :  * Whether client is interested in old and new VRF is checked by caller.
     452             :  */
     453           0 : int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
     454             :                                vrf_id_t vrf_id)
     455             : {
     456           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     457             : 
     458           0 :         zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf->vrf_id);
     459             : 
     460             :         /* Fill in the name of the interface and its new VRF (id) */
     461           0 :         stream_put(s, ifp->name, INTERFACE_NAMSIZ);
     462           0 :         stream_putl(s, vrf_id);
     463             : 
     464             :         /* Write packet size. */
     465           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     466             : 
     467           0 :         client->if_vrfchg_cnt++;
     468           0 :         return zserv_send_message(client, s);
     469             : }
     470             : 
     471             : /* Add new nbr connected IPv6 address */
     472           0 : void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address)
     473             : {
     474           0 :         struct nbr_connected *ifc;
     475           0 :         struct prefix p;
     476             : 
     477           0 :         p.family = AF_INET6;
     478           0 :         IPV6_ADDR_COPY(&p.u.prefix6, address);
     479           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     480             : 
     481           0 :         ifc = listnode_head(ifp->nbr_connected);
     482           0 :         if (!ifc) {
     483             :                 /* new addition */
     484           0 :                 ifc = nbr_connected_new();
     485           0 :                 ifc->address = prefix_new();
     486           0 :                 ifc->ifp = ifp;
     487           0 :                 listnode_add(ifp->nbr_connected, ifc);
     488             :         }
     489             : 
     490           0 :         prefix_copy(ifc->address, &p);
     491             : 
     492           0 :         zebra_interface_nbr_address_add_update(ifp, ifc);
     493             : 
     494           0 :         if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 1);
     495           0 : }
     496             : 
     497           0 : void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address)
     498             : {
     499           0 :         struct nbr_connected *ifc;
     500           0 :         struct prefix p;
     501             : 
     502           0 :         p.family = AF_INET6;
     503           0 :         IPV6_ADDR_COPY(&p.u.prefix6, address);
     504           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     505             : 
     506           0 :         ifc = nbr_connected_check(ifp, &p);
     507           0 :         if (!ifc)
     508           0 :                 return;
     509             : 
     510           0 :         listnode_delete(ifp->nbr_connected, ifc);
     511             : 
     512           0 :         zebra_interface_nbr_address_delete_update(ifp, ifc);
     513             : 
     514           0 :         if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 0);
     515             : 
     516           0 :         nbr_connected_free(ifc);
     517             : }
     518             : 
     519             : /*
     520             :  * The cmd passed to zsend_interface_update  may be ZEBRA_INTERFACE_UP or
     521             :  * ZEBRA_INTERFACE_DOWN.
     522             :  *
     523             :  * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
     524             :  * the clients in one of 2 situations:
     525             :  *   - an if_up is detected e.g., as a result of an RTM_IFINFO message
     526             :  *   - a vty command modifying the bandwidth of an interface is received.
     527             :  * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
     528             :  */
     529          44 : int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
     530             : {
     531          44 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     532             : 
     533          44 :         zclient_create_header(s, cmd, ifp->vrf->vrf_id);
     534          44 :         zserv_encode_interface(s, ifp);
     535             : 
     536          44 :         if (cmd == ZEBRA_INTERFACE_UP)
     537          22 :                 client->ifup_cnt++;
     538             :         else
     539          22 :                 client->ifdown_cnt++;
     540             : 
     541          44 :         return zserv_send_message(client, s);
     542             : }
     543             : 
     544           0 : int zsend_redistribute_route(int cmd, struct zserv *client,
     545             :                              const struct route_node *rn,
     546             :                              const struct route_entry *re)
     547             : {
     548           0 :         struct zapi_route api;
     549           0 :         struct zapi_nexthop *api_nh;
     550           0 :         struct nexthop *nexthop;
     551           0 :         const struct prefix *p, *src_p;
     552           0 :         uint8_t count = 0;
     553           0 :         afi_t afi;
     554           0 :         size_t stream_size =
     555             :                 MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
     556             : 
     557           0 :         srcdest_rnode_prefixes(rn, &p, &src_p);
     558           0 :         memset(&api, 0, sizeof(api));
     559           0 :         api.vrf_id = re->vrf_id;
     560           0 :         api.type = re->type;
     561           0 :         api.safi = SAFI_UNICAST;
     562           0 :         api.instance = re->instance;
     563           0 :         api.flags = re->flags;
     564             : 
     565           0 :         afi = family2afi(p->family);
     566           0 :         switch (afi) {
     567           0 :         case AFI_IP:
     568           0 :                 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
     569           0 :                         client->redist_v4_add_cnt++;
     570             :                 else
     571           0 :                         client->redist_v4_del_cnt++;
     572             :                 break;
     573           0 :         case AFI_IP6:
     574           0 :                 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
     575           0 :                         client->redist_v6_add_cnt++;
     576             :                 else
     577           0 :                         client->redist_v6_del_cnt++;
     578             :                 break;
     579             :         case AFI_L2VPN:
     580             :         case AFI_MAX:
     581             :         case AFI_UNSPEC:
     582             :                 break;
     583             :         }
     584             : 
     585             :         /* Prefix. */
     586           0 :         api.prefix = *p;
     587           0 :         if (src_p) {
     588           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
     589           0 :                 memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
     590             :         }
     591             : 
     592           0 :         for (nexthop = re->nhe->nhg.nexthop;
     593           0 :              nexthop; nexthop = nexthop->next) {
     594           0 :                 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
     595           0 :                         continue;
     596             : 
     597           0 :                 api_nh = &api.nexthops[count];
     598           0 :                 api_nh->vrf_id = nexthop->vrf_id;
     599           0 :                 api_nh->type = nexthop->type;
     600           0 :                 api_nh->weight = nexthop->weight;
     601           0 :                 switch (nexthop->type) {
     602           0 :                 case NEXTHOP_TYPE_BLACKHOLE:
     603           0 :                         api_nh->bh_type = nexthop->bh_type;
     604           0 :                         break;
     605           0 :                 case NEXTHOP_TYPE_IPV4:
     606             :                 case NEXTHOP_TYPE_IPV4_IFINDEX:
     607           0 :                         api_nh->gate.ipv4 = nexthop->gate.ipv4;
     608           0 :                         api_nh->ifindex = nexthop->ifindex;
     609           0 :                         break;
     610           0 :                 case NEXTHOP_TYPE_IFINDEX:
     611           0 :                         api_nh->ifindex = nexthop->ifindex;
     612           0 :                         break;
     613           0 :                 case NEXTHOP_TYPE_IPV6:
     614             :                 case NEXTHOP_TYPE_IPV6_IFINDEX:
     615           0 :                         api_nh->gate.ipv6 = nexthop->gate.ipv6;
     616           0 :                         api_nh->ifindex = nexthop->ifindex;
     617             :                 }
     618           0 :                 count++;
     619             :         }
     620             : 
     621             :         /* Nexthops. */
     622           0 :         if (count) {
     623           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
     624           0 :                 api.nexthop_num = count;
     625             :         }
     626             : 
     627             :         /* Attributes. */
     628           0 :         SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
     629           0 :         api.distance = re->distance;
     630           0 :         SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
     631           0 :         api.metric = re->metric;
     632           0 :         if (re->tag) {
     633           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
     634           0 :                 api.tag = re->tag;
     635             :         }
     636           0 :         SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
     637           0 :         api.mtu = re->mtu;
     638             : 
     639           0 :         struct stream *s = stream_new(stream_size);
     640             : 
     641             :         /* Encode route and send. */
     642           0 :         if (zapi_route_encode(cmd, s, &api) < 0) {
     643           0 :                 stream_free(s);
     644           0 :                 return -1;
     645             :         }
     646             : 
     647           0 :         if (IS_ZEBRA_DEBUG_SEND)
     648           0 :                 zlog_debug("%s: %s to client %s: type %s, vrf_id %d, p %pFX",
     649             :                            __func__, zserv_command_string(cmd),
     650             :                            zebra_route_string(client->proto),
     651             :                            zebra_route_string(api.type), api.vrf_id,
     652             :                            &api.prefix);
     653           0 :         return zserv_send_message(client, s);
     654             : }
     655             : 
     656             : /*
     657             :  * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if
     658             :  * nexthop is not found on mrib. Returns both route metric and protocol
     659             :  * distance.
     660             :  *
     661             :  * *XXX* this ZAPI call is slated to be removed at some point in the future
     662             :  * since MRIB support in PIM is hopelessly broken in its interactions with NHT.
     663             :  * The plan is to make pimd use NHT to receive URIB and MRIB in parallel and
     664             :  * make the decision there, which will obsolete this ZAPI op.
     665             :  * (Otherwise we would need to implement sending NHT updates for the result of
     666             :  * this "URIB-MRIB-combined" table, but we only decide that here on the fly,
     667             :  * so it'd be rather complex to do NHT for.)
     668             :  */
     669           0 : static int zsend_nexthop_lookup_mrib(struct zserv *client, struct ipaddr *addr,
     670             :                                      struct route_entry *re,
     671             :                                      struct zebra_vrf *zvrf)
     672             : {
     673           0 :         struct stream *s;
     674           0 :         unsigned long nump;
     675           0 :         uint8_t num;
     676           0 :         struct nexthop *nexthop;
     677             : 
     678             :         /* Get output stream. */
     679           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     680           0 :         stream_reset(s);
     681             : 
     682             :         /* Fill in result. */
     683           0 :         zclient_create_header(s, ZEBRA_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
     684           0 :         stream_put_ipaddr(s, addr);
     685             : 
     686           0 :         if (re) {
     687           0 :                 struct nexthop_group *nhg;
     688             : 
     689           0 :                 stream_putc(s, re->distance);
     690           0 :                 stream_putl(s, re->metric);
     691           0 :                 num = 0;
     692             :                 /* remember position for nexthop_num */
     693           0 :                 nump = stream_get_endp(s);
     694             :                 /* reserve room for nexthop_num */
     695           0 :                 stream_putc(s, 0);
     696           0 :                 nhg = rib_get_fib_nhg(re);
     697           0 :                 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
     698           0 :                         if (rnh_nexthop_valid(re, nexthop))
     699           0 :                                 num += zserv_encode_nexthop(s, nexthop);
     700             :                 }
     701             : 
     702             :                 /* store nexthop_num */
     703           0 :                 stream_putc_at(s, nump, num);
     704             :         } else {
     705           0 :                 stream_putc(s, 0); /* distance */
     706           0 :                 stream_putl(s, 0); /* metric */
     707           0 :                 stream_putc(s, 0); /* nexthop_num */
     708             :         }
     709             : 
     710           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     711             : 
     712           0 :         return zserv_send_message(client, s);
     713             : }
     714             : 
     715           0 : int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
     716             :                      uint32_t id, enum zapi_nhg_notify_owner note)
     717             : {
     718           0 :         struct zserv *client;
     719           0 :         struct stream *s;
     720             : 
     721           0 :         client = zserv_find_client_session(type, instance, session_id);
     722           0 :         if (!client) {
     723           0 :                 if (IS_ZEBRA_DEBUG_PACKET) {
     724           0 :                         zlog_debug("Not Notifying Owner: %u(%u) about %u(%d)",
     725             :                                    type, instance, id, note);
     726             :                 }
     727           0 :                 return 0;
     728             :         }
     729             : 
     730           0 :         if (IS_ZEBRA_DEBUG_SEND)
     731           0 :                 zlog_debug("%s: type %d, id %d, note %s",
     732             :                            __func__, type, id, zapi_nhg_notify_owner2str(note));
     733             : 
     734           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     735           0 :         stream_reset(s);
     736             : 
     737           0 :         zclient_create_header(s, ZEBRA_NHG_NOTIFY_OWNER, VRF_DEFAULT);
     738             : 
     739           0 :         stream_put(s, &note, sizeof(note));
     740           0 :         stream_putl(s, id);
     741             : 
     742           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     743             : 
     744           0 :         return zserv_send_message(client, s);
     745             : }
     746             : 
     747             : /*
     748             :  * Common utility send route notification, called from a path using a
     749             :  * route_entry and from a path using a dataplane context.
     750             :  */
     751          56 : static int route_notify_internal(const struct route_node *rn, int type,
     752             :                                  uint16_t instance, vrf_id_t vrf_id,
     753             :                                  uint32_t table_id,
     754             :                                  enum zapi_route_notify_owner note, afi_t afi,
     755             :                                  safi_t safi)
     756             : {
     757          56 :         struct zserv *client;
     758          56 :         struct stream *s;
     759          56 :         uint8_t blen;
     760             : 
     761          56 :         client = zserv_find_client(type, instance);
     762          56 :         if (!client || !client->notify_owner) {
     763          56 :                 if (IS_ZEBRA_DEBUG_PACKET)
     764           0 :                         zlog_debug(
     765             :                                 "Not Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u",
     766             :                                 zebra_route_string(type), rn, table_id, note,
     767             :                                 vrf_id);
     768          56 :                 return 0;
     769             :         }
     770             : 
     771           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     772           0 :                 zlog_debug(
     773             :                         "Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u",
     774             :                         zebra_route_string(type), rn, table_id, note, vrf_id);
     775             : 
     776             :         /* We're just allocating a small-ish buffer here, since we only
     777             :          * encode a small amount of data.
     778             :          */
     779           0 :         s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
     780             : 
     781           0 :         stream_reset(s);
     782             : 
     783           0 :         zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id);
     784             : 
     785           0 :         stream_put(s, &note, sizeof(note));
     786             : 
     787           0 :         stream_putc(s, rn->p.family);
     788             : 
     789           0 :         blen = prefix_blen(&rn->p);
     790           0 :         stream_putc(s, rn->p.prefixlen);
     791           0 :         stream_put(s, &rn->p.u.prefix, blen);
     792             : 
     793           0 :         stream_putl(s, table_id);
     794             : 
     795             :         /* Encode AFI, SAFI in the message */
     796           0 :         stream_putc(s, afi);
     797           0 :         stream_putc(s, safi);
     798             : 
     799           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     800             : 
     801           0 :         return zserv_send_message(client, s);
     802             : }
     803             : 
     804           0 : int zsend_route_notify_owner(const struct route_node *rn,
     805             :                              struct route_entry *re,
     806             :                              enum zapi_route_notify_owner note, afi_t afi,
     807             :                              safi_t safi)
     808             : {
     809           0 :         return (route_notify_internal(rn, re->type, re->instance, re->vrf_id,
     810             :                                       re->table, note, afi, safi));
     811             : }
     812             : 
     813             : /*
     814             :  * Route-owner notification using info from dataplane update context.
     815             :  */
     816          56 : int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
     817             :                                  enum zapi_route_notify_owner note)
     818             : {
     819         168 :         return (route_notify_internal(
     820          56 :                 rib_find_rn_from_ctx(ctx), dplane_ctx_get_type(ctx),
     821          56 :                 dplane_ctx_get_instance(ctx), dplane_ctx_get_vrf(ctx),
     822             :                 dplane_ctx_get_table(ctx), note, dplane_ctx_get_afi(ctx),
     823             :                 dplane_ctx_get_safi(ctx)));
     824             : }
     825             : 
     826           0 : static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
     827             : {
     828           0 :         uint8_t notify;
     829             : 
     830           0 :         STREAM_GETC(msg, notify);
     831           0 :         client->notify_owner = notify;
     832           0 : stream_failure:
     833           0 :         return;
     834             : }
     835             : 
     836           0 : void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
     837             :                              enum zapi_rule_notify_owner note)
     838             : {
     839           0 :         struct listnode *node;
     840           0 :         struct zserv *client;
     841           0 :         struct stream *s;
     842             : 
     843           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     844           0 :                 zlog_debug("%s: Notifying %u", __func__,
     845             :                            dplane_ctx_rule_get_unique(ctx));
     846             : 
     847           0 :         for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
     848           0 :                 if (dplane_ctx_rule_get_sock(ctx) == client->sock)
     849             :                         break;
     850             :         }
     851             : 
     852           0 :         if (!client)
     853             :                 return;
     854             : 
     855           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     856             : 
     857           0 :         zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
     858           0 :         stream_put(s, &note, sizeof(note));
     859           0 :         stream_putl(s, dplane_ctx_rule_get_seq(ctx));
     860           0 :         stream_putl(s, dplane_ctx_rule_get_priority(ctx));
     861           0 :         stream_putl(s, dplane_ctx_rule_get_unique(ctx));
     862           0 :         stream_put(s, dplane_ctx_rule_get_ifname(ctx), INTERFACE_NAMSIZ);
     863             : 
     864           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     865             : 
     866           0 :         zserv_send_message(client, s);
     867             : }
     868             : 
     869           0 : void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
     870             :                                 enum zapi_iptable_notify_owner note)
     871             : {
     872           0 :         struct listnode *node;
     873           0 :         struct zserv *client;
     874           0 :         struct stream *s;
     875           0 :         struct zebra_pbr_iptable ipt;
     876           0 :         uint16_t cmd = ZEBRA_IPTABLE_NOTIFY_OWNER;
     877           0 :         struct zebra_pbr_iptable *ipt_hash;
     878           0 :         enum dplane_op_e op = dplane_ctx_get_op(ctx);
     879             : 
     880           0 :         dplane_ctx_get_pbr_iptable(ctx, &ipt);
     881             : 
     882           0 :         ipt_hash = hash_lookup(zrouter.iptable_hash, &ipt);
     883           0 :         if (ipt_hash) {
     884           0 :                 if (op == DPLANE_OP_IPTABLE_ADD &&
     885           0 :                     CHECK_FLAG(ipt_hash->internal_flags,
     886             :                                IPTABLE_INSTALL_QUEUED))
     887           0 :                         UNSET_FLAG(ipt_hash->internal_flags,
     888             :                                    IPTABLE_INSTALL_QUEUED);
     889           0 :                 else if (op == DPLANE_OP_IPTABLE_DELETE &&
     890           0 :                          CHECK_FLAG(ipt_hash->internal_flags,
     891             :                                     IPTABLE_UNINSTALL_QUEUED))
     892           0 :                         UNSET_FLAG(ipt_hash->internal_flags,
     893             :                                    IPTABLE_UNINSTALL_QUEUED);
     894             :         }
     895           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     896           0 :                 zlog_debug("%s: Notifying %s id %u note %u", __func__,
     897             :                            zserv_command_string(cmd), ipt.unique, note);
     898             : 
     899           0 :         for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
     900           0 :                 if (ipt.sock == client->sock)
     901             :                         break;
     902             :         }
     903             : 
     904           0 :         if (!client)
     905           0 :                 return;
     906             : 
     907           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     908             : 
     909           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
     910           0 :         stream_putw(s, note);
     911           0 :         stream_putl(s, ipt.unique);
     912           0 :         stream_put(s, ipt.ipset_name, ZEBRA_IPSET_NAME_SIZE);
     913           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     914             : 
     915           0 :         zserv_send_message(client, s);
     916             : }
     917             : 
     918           0 : void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx,
     919             :                               enum zapi_ipset_notify_owner note)
     920             : {
     921           0 :         struct listnode *node;
     922           0 :         struct zserv *client;
     923           0 :         struct stream *s;
     924           0 :         struct zebra_pbr_ipset ipset;
     925           0 :         uint16_t cmd = ZEBRA_IPSET_NOTIFY_OWNER;
     926             : 
     927           0 :         dplane_ctx_get_pbr_ipset(ctx, &ipset);
     928             : 
     929           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     930           0 :                 zlog_debug("%s: Notifying %s id %u note %u", __func__,
     931             :                            zserv_command_string(cmd), ipset.unique, note);
     932             : 
     933           0 :         for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
     934           0 :                 if (ipset.sock == client->sock)
     935             :                         break;
     936             :         }
     937             : 
     938           0 :         if (!client)
     939           0 :                 return;
     940             : 
     941           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     942             : 
     943           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
     944           0 :         stream_putw(s, note);
     945           0 :         stream_putl(s, ipset.unique);
     946           0 :         stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
     947           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     948             : 
     949           0 :         zserv_send_message(client, s);
     950             : }
     951             : 
     952           0 : void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
     953             :                                     enum zapi_ipset_entry_notify_owner note)
     954             : {
     955           0 :         struct listnode *node;
     956           0 :         struct zserv *client;
     957           0 :         struct stream *s;
     958           0 :         struct zebra_pbr_ipset_entry ipent;
     959           0 :         struct zebra_pbr_ipset ipset;
     960           0 :         uint16_t cmd = ZEBRA_IPSET_ENTRY_NOTIFY_OWNER;
     961             : 
     962           0 :         dplane_ctx_get_pbr_ipset_entry(ctx, &ipent);
     963           0 :         dplane_ctx_get_pbr_ipset(ctx, &ipset);
     964             : 
     965           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     966           0 :                 zlog_debug("%s: Notifying %s id %u note %u", __func__,
     967             :                            zserv_command_string(cmd), ipent.unique, note);
     968             : 
     969           0 :         for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
     970           0 :                 if (ipent.sock == client->sock)
     971             :                         break;
     972             :         }
     973             : 
     974           0 :         if (!client)
     975           0 :                 return;
     976             : 
     977           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
     978             : 
     979           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
     980           0 :         stream_putw(s, note);
     981           0 :         stream_putl(s, ipent.unique);
     982           0 :         stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
     983           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     984             : 
     985           0 :         zserv_send_message(client, s);
     986             : }
     987             : 
     988           0 : void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
     989             :                                 struct ipaddr *ipaddr, int ndm_state,
     990             :                                 union sockunion *link_layer_ipv4)
     991             : {
     992           0 :         struct stream *s;
     993           0 :         struct listnode *node, *nnode;
     994           0 :         struct zserv *client;
     995           0 :         afi_t afi;
     996           0 :         union sockunion ip;
     997             : 
     998           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     999           0 :                 zlog_debug("%s: Notifying Neighbor entry (%u)", __func__, cmd);
    1000             : 
    1001           0 :         sockunion_family(&ip) = ipaddr_family(ipaddr);
    1002           0 :         afi = family2afi(sockunion_family(&ip));
    1003           0 :         memcpy((char *)sockunion_get_addr(&ip), &ipaddr->ip.addr,
    1004           0 :                family2addrsize(sockunion_family(&ip)));
    1005             : 
    1006           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
    1007           0 :                 if (!vrf_bitmap_check(client->nhrp_neighinfo[afi],
    1008           0 :                                       ifp->vrf->vrf_id))
    1009           0 :                         continue;
    1010             : 
    1011           0 :                 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1012           0 :                 zclient_neigh_ip_encode(s, cmd, &ip, link_layer_ipv4, ifp,
    1013             :                                         ndm_state);
    1014           0 :                 stream_putw_at(s, 0, stream_get_endp(s));
    1015           0 :                 zserv_send_message(client, s);
    1016             :         }
    1017           0 : }
    1018             : 
    1019             : 
    1020             : /* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
    1021           4 : int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
    1022             :                            vrf_id_t vrf_id)
    1023             : {
    1024           4 :         int blen;
    1025           4 :         struct stream *s;
    1026             : 
    1027             :         /* Check this client need interface information. */
    1028           4 :         if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id))
    1029             :                 return 0;
    1030             : 
    1031           4 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1032             : 
    1033             :         /* Message type. */
    1034           4 :         zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
    1035             : 
    1036             :         /* Prefix information. */
    1037           4 :         stream_putc(s, p->family);
    1038           4 :         blen = prefix_blen(p);
    1039           4 :         stream_put(s, &p->u.prefix, blen);
    1040           4 :         stream_putc(s, p->prefixlen);
    1041             : 
    1042             :         /* Write packet size. */
    1043           4 :         stream_putw_at(s, 0, stream_get_endp(s));
    1044             : 
    1045           4 :         return zserv_send_message(client, s);
    1046             : }
    1047             : 
    1048             : /*
    1049             :  * Function used by Zebra to send a PW status update to LDP daemon
    1050             :  */
    1051           0 : int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
    1052             : {
    1053           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1054             : 
    1055           0 :         zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
    1056           0 :         stream_write(s, pw->ifname, INTERFACE_NAMSIZ);
    1057           0 :         stream_putl(s, pw->ifindex);
    1058           0 :         stream_putl(s, pw->status);
    1059             : 
    1060             :         /* Put length at the first point of the stream. */
    1061           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1062             : 
    1063           0 :         return zserv_send_message(client, s);
    1064             : }
    1065             : 
    1066             : /* Send response to a get label chunk request to client */
    1067           0 : int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id,
    1068             :                                       struct label_manager_chunk *lmc)
    1069             : {
    1070           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1071             : 
    1072           0 :         zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
    1073             :         /* proto */
    1074           0 :         stream_putc(s, client->proto);
    1075             :         /* instance */
    1076           0 :         stream_putw(s, client->instance);
    1077             : 
    1078           0 :         if (lmc) {
    1079             :                 /* keep */
    1080           0 :                 stream_putc(s, lmc->keep);
    1081             :                 /* start and end labels */
    1082           0 :                 stream_putl(s, lmc->start);
    1083           0 :                 stream_putl(s, lmc->end);
    1084             :         }
    1085             : 
    1086             :         /* Write packet size. */
    1087           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1088             : 
    1089           0 :         return zserv_send_message(client, s);
    1090             : }
    1091             : 
    1092             : /* Send response to a label manager connect request to client */
    1093           0 : int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id,
    1094             :                                          unsigned short result)
    1095             : {
    1096           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1097             : 
    1098           0 :         zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
    1099             : 
    1100             :         /* proto */
    1101           0 :         stream_putc(s, client->proto);
    1102             : 
    1103             :         /* instance */
    1104           0 :         stream_putw(s, client->instance);
    1105             : 
    1106             :         /* result */
    1107           0 :         stream_putc(s, result);
    1108             : 
    1109             :         /* Write packet size. */
    1110           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1111             : 
    1112           0 :         return zserv_send_message(client, s);
    1113             : }
    1114             : 
    1115             : /* Send response to a get table chunk request to client */
    1116           0 : static int zsend_assign_table_chunk_response(struct zserv *client,
    1117             :                                              vrf_id_t vrf_id,
    1118             :                                              struct table_manager_chunk *tmc)
    1119             : {
    1120           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1121             : 
    1122           0 :         zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, vrf_id);
    1123             : 
    1124           0 :         if (tmc) {
    1125             :                 /* start and end labels */
    1126           0 :                 stream_putl(s, tmc->start);
    1127           0 :                 stream_putl(s, tmc->end);
    1128             :         }
    1129             : 
    1130             :         /* Write packet size. */
    1131           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1132             : 
    1133           0 :         return zserv_send_message(client, s);
    1134             : }
    1135             : 
    1136           0 : static int zsend_table_manager_connect_response(struct zserv *client,
    1137             :                                                 vrf_id_t vrf_id,
    1138             :                                                 uint16_t result)
    1139             : {
    1140           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1141             : 
    1142           0 :         zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, vrf_id);
    1143             : 
    1144             :         /* result */
    1145           0 :         stream_putc(s, result);
    1146             : 
    1147           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1148             : 
    1149           0 :         return zserv_send_message(client, s);
    1150             : }
    1151             : 
    1152             : /* SRv6 locator add notification from zebra daemon. */
    1153           0 : int zsend_zebra_srv6_locator_add(struct zserv *client, struct srv6_locator *loc)
    1154             : {
    1155           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1156             : 
    1157           0 :         zclient_create_header(s, ZEBRA_SRV6_LOCATOR_ADD, VRF_DEFAULT);
    1158           0 :         zapi_srv6_locator_encode(s, loc);
    1159           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1160             : 
    1161           0 :         return zserv_send_message(client, s);
    1162             : }
    1163             : 
    1164             : /* SRv6 locator delete notification from zebra daemon. */
    1165           0 : int zsend_zebra_srv6_locator_delete(struct zserv *client,
    1166             :                                     struct srv6_locator *loc)
    1167             : {
    1168           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1169             : 
    1170           0 :         zclient_create_header(s, ZEBRA_SRV6_LOCATOR_DELETE, VRF_DEFAULT);
    1171           0 :         zapi_srv6_locator_encode(s, loc);
    1172           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1173             : 
    1174           0 :         return zserv_send_message(client, s);
    1175             : }
    1176             : 
    1177             : /* Inbound message handling ------------------------------------------------ */
    1178             : 
    1179             : /* Nexthop register */
    1180           0 : static void zread_rnh_register(ZAPI_HANDLER_ARGS)
    1181             : {
    1182           0 :         struct rnh *rnh;
    1183           0 :         struct stream *s;
    1184           0 :         struct prefix p;
    1185           0 :         unsigned short l = 0;
    1186           0 :         uint8_t connected = 0;
    1187           0 :         uint8_t resolve_via_default;
    1188           0 :         bool exist;
    1189           0 :         bool flag_changed = false;
    1190           0 :         uint8_t orig_flags;
    1191           0 :         safi_t safi;
    1192             : 
    1193           0 :         if (IS_ZEBRA_DEBUG_NHT)
    1194           0 :                 zlog_debug(
    1195             :                         "rnh_register msg from client %s: hdr->length=%d vrf=%u",
    1196             :                         zebra_route_string(client->proto), hdr->length,
    1197             :                         zvrf->vrf->vrf_id);
    1198             : 
    1199           0 :         s = msg;
    1200             : 
    1201           0 :         if (!client->nh_reg_time)
    1202           0 :                 client->nh_reg_time = monotime(NULL);
    1203             : 
    1204           0 :         while (l < hdr->length) {
    1205           0 :                 STREAM_GETC(s, connected);
    1206           0 :                 STREAM_GETC(s, resolve_via_default);
    1207           0 :                 STREAM_GETW(s, safi);
    1208           0 :                 STREAM_GETW(s, p.family);
    1209           0 :                 STREAM_GETC(s, p.prefixlen);
    1210           0 :                 l += 7;
    1211           0 :                 if (p.family == AF_INET) {
    1212           0 :                         client->v4_nh_watch_add_cnt++;
    1213           0 :                         if (p.prefixlen > IPV4_MAX_BITLEN) {
    1214           0 :                                 zlog_debug(
    1215             :                                         "%s: Specified prefix hdr->length %d is too large for a v4 address",
    1216             :                                         __func__, p.prefixlen);
    1217           0 :                                 return;
    1218             :                         }
    1219           0 :                         STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
    1220           0 :                         l += IPV4_MAX_BYTELEN;
    1221           0 :                 } else if (p.family == AF_INET6) {
    1222           0 :                         client->v6_nh_watch_add_cnt++;
    1223           0 :                         if (p.prefixlen > IPV6_MAX_BITLEN) {
    1224           0 :                                 zlog_debug(
    1225             :                                         "%s: Specified prefix hdr->length %d is to large for a v6 address",
    1226             :                                         __func__, p.prefixlen);
    1227           0 :                                 return;
    1228             :                         }
    1229           0 :                         STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
    1230           0 :                         l += IPV6_MAX_BYTELEN;
    1231             :                 } else {
    1232           0 :                         flog_err(
    1233             :                                 EC_ZEBRA_UNKNOWN_FAMILY,
    1234             :                                 "rnh_register: Received unknown family type %d",
    1235             :                                 p.family);
    1236           0 :                         return;
    1237             :                 }
    1238           0 :                 rnh = zebra_add_rnh(&p, zvrf_id(zvrf), safi, &exist);
    1239           0 :                 if (!rnh)
    1240             :                         return;
    1241             : 
    1242           0 :                 orig_flags = rnh->flags;
    1243           0 :                 if (connected && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
    1244           0 :                         SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
    1245             :                 else if (!connected
    1246           0 :                          && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
    1247           0 :                         UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
    1248             : 
    1249           0 :                 if (resolve_via_default)
    1250           0 :                         SET_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT);
    1251             : 
    1252           0 :                 if (orig_flags != rnh->flags)
    1253           0 :                         flag_changed = true;
    1254             : 
    1255             :                 /* Anything not AF_INET/INET6 has been filtered out above */
    1256           0 :                 if (!exist || flag_changed)
    1257           0 :                         zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p,
    1258             :                                            safi);
    1259             : 
    1260           0 :                 zebra_add_rnh_client(rnh, client, zvrf_id(zvrf));
    1261             :         }
    1262             : 
    1263           0 : stream_failure:
    1264             :         return;
    1265             : }
    1266             : 
    1267             : /* Nexthop register */
    1268           0 : static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
    1269             : {
    1270           0 :         struct rnh *rnh;
    1271           0 :         struct stream *s;
    1272           0 :         struct prefix p;
    1273           0 :         unsigned short l = 0;
    1274           0 :         safi_t safi;
    1275             : 
    1276           0 :         if (IS_ZEBRA_DEBUG_NHT)
    1277           0 :                 zlog_debug(
    1278             :                         "rnh_unregister msg from client %s: hdr->length=%d vrf: %u",
    1279             :                         zebra_route_string(client->proto), hdr->length,
    1280             :                         zvrf->vrf->vrf_id);
    1281             : 
    1282             :         s = msg;
    1283             : 
    1284           0 :         while (l < hdr->length) {
    1285           0 :                 uint8_t ignore;
    1286             : 
    1287           0 :                 STREAM_GETC(s, ignore);
    1288           0 :                 if (ignore != 0)
    1289           0 :                         goto stream_failure;
    1290           0 :                 STREAM_GETC(s, ignore);
    1291           0 :                 if (ignore != 0)
    1292           0 :                         goto stream_failure;
    1293             : 
    1294           0 :                 STREAM_GETW(s, safi);
    1295           0 :                 STREAM_GETW(s, p.family);
    1296           0 :                 STREAM_GETC(s, p.prefixlen);
    1297           0 :                 l += 7;
    1298           0 :                 if (p.family == AF_INET) {
    1299           0 :                         client->v4_nh_watch_rem_cnt++;
    1300           0 :                         if (p.prefixlen > IPV4_MAX_BITLEN) {
    1301           0 :                                 zlog_debug(
    1302             :                                         "%s: Specified prefix hdr->length %d is to large for a v4 address",
    1303             :                                         __func__, p.prefixlen);
    1304           0 :                                 return;
    1305             :                         }
    1306           0 :                         STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
    1307           0 :                         l += IPV4_MAX_BYTELEN;
    1308           0 :                 } else if (p.family == AF_INET6) {
    1309           0 :                         client->v6_nh_watch_rem_cnt++;
    1310           0 :                         if (p.prefixlen > IPV6_MAX_BITLEN) {
    1311           0 :                                 zlog_debug(
    1312             :                                         "%s: Specified prefix hdr->length %d is to large for a v6 address",
    1313             :                                         __func__, p.prefixlen);
    1314           0 :                                 return;
    1315             :                         }
    1316           0 :                         STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
    1317           0 :                         l += IPV6_MAX_BYTELEN;
    1318             :                 } else {
    1319           0 :                         flog_err(
    1320             :                                 EC_ZEBRA_UNKNOWN_FAMILY,
    1321             :                                 "rnh_register: Received unknown family type %d",
    1322             :                                 p.family);
    1323           0 :                         return;
    1324             :                 }
    1325           0 :                 rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), safi);
    1326           0 :                 if (rnh) {
    1327           0 :                         client->nh_dereg_time = monotime(NULL);
    1328           0 :                         zebra_remove_rnh_client(rnh, client);
    1329             :                 }
    1330             :         }
    1331           0 : stream_failure:
    1332             :         return;
    1333             : }
    1334             : 
    1335             : #define ZEBRA_MIN_FEC_LENGTH 5
    1336             : 
    1337             : /* FEC register */
    1338           0 : static void zread_fec_register(ZAPI_HANDLER_ARGS)
    1339             : {
    1340           0 :         struct stream *s;
    1341           0 :         unsigned short l = 0;
    1342           0 :         struct prefix p;
    1343           0 :         uint16_t flags;
    1344           0 :         uint32_t label = MPLS_INVALID_LABEL;
    1345           0 :         uint32_t label_index = MPLS_INVALID_LABEL_INDEX;
    1346             : 
    1347           0 :         s = msg;
    1348           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    1349           0 :         if (!zvrf)
    1350             :                 return;
    1351             : 
    1352             :         /*
    1353             :          * The minimum amount of data that can be sent for one fec
    1354             :          * registration
    1355             :          */
    1356           0 :         if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
    1357           0 :                 flog_err(
    1358             :                         EC_ZEBRA_IRDP_LEN_MISMATCH,
    1359             :                         "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode",
    1360             :                         hdr->length);
    1361           0 :                 return;
    1362             :         }
    1363             : 
    1364           0 :         while (l < hdr->length) {
    1365           0 :                 STREAM_GETW(s, flags);
    1366           0 :                 memset(&p, 0, sizeof(p));
    1367           0 :                 STREAM_GETW(s, p.family);
    1368           0 :                 if (p.family != AF_INET && p.family != AF_INET6) {
    1369           0 :                         flog_err(
    1370             :                                 EC_ZEBRA_UNKNOWN_FAMILY,
    1371             :                                 "fec_register: Received unknown family type %d",
    1372             :                                 p.family);
    1373           0 :                         return;
    1374             :                 }
    1375           0 :                 STREAM_GETC(s, p.prefixlen);
    1376           0 :                 if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
    1377           0 :                     || (p.family == AF_INET6
    1378           0 :                         && p.prefixlen > IPV6_MAX_BITLEN)) {
    1379           0 :                         zlog_debug(
    1380             :                                 "%s: Specified prefix hdr->length: %d is to long for %d",
    1381             :                                 __func__, p.prefixlen, p.family);
    1382           0 :                         return;
    1383             :                 }
    1384           0 :                 l += 5;
    1385           0 :                 STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
    1386           0 :                 l += PSIZE(p.prefixlen);
    1387           0 :                 if (flags & ZEBRA_FEC_REGISTER_LABEL) {
    1388           0 :                         STREAM_GETL(s, label);
    1389           0 :                         l += 4;
    1390           0 :                 } else if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) {
    1391           0 :                         STREAM_GETL(s, label_index);
    1392           0 :                         l += 4;
    1393             :                 }
    1394             : 
    1395           0 :                 zebra_mpls_fec_register(zvrf, &p, label, label_index, client);
    1396             :         }
    1397             : 
    1398           0 : stream_failure:
    1399             :         return;
    1400             : }
    1401             : 
    1402             : /* FEC unregister */
    1403           0 : static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
    1404             : {
    1405           0 :         struct stream *s;
    1406           0 :         unsigned short l = 0;
    1407           0 :         struct prefix p;
    1408           0 :         uint16_t flags;
    1409             : 
    1410           0 :         s = msg;
    1411           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    1412           0 :         if (!zvrf)
    1413             :                 return;
    1414             : 
    1415             :         /*
    1416             :          * The minimum amount of data that can be sent for one
    1417             :          * fec unregistration
    1418             :          */
    1419           0 :         if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
    1420           0 :                 flog_err(
    1421             :                         EC_ZEBRA_IRDP_LEN_MISMATCH,
    1422             :                         "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode",
    1423             :                         hdr->length);
    1424           0 :                 return;
    1425             :         }
    1426             : 
    1427           0 :         while (l < hdr->length) {
    1428           0 :                 STREAM_GETW(s, flags);
    1429           0 :                 if (flags != 0)
    1430           0 :                         goto stream_failure;
    1431             : 
    1432           0 :                 memset(&p, 0, sizeof(p));
    1433           0 :                 STREAM_GETW(s, p.family);
    1434           0 :                 if (p.family != AF_INET && p.family != AF_INET6) {
    1435           0 :                         flog_err(
    1436             :                                 EC_ZEBRA_UNKNOWN_FAMILY,
    1437             :                                 "fec_unregister: Received unknown family type %d",
    1438             :                                 p.family);
    1439           0 :                         return;
    1440             :                 }
    1441           0 :                 STREAM_GETC(s, p.prefixlen);
    1442           0 :                 if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
    1443           0 :                     || (p.family == AF_INET6
    1444           0 :                         && p.prefixlen > IPV6_MAX_BITLEN)) {
    1445           0 :                         zlog_debug(
    1446             :                                 "%s: Received prefix hdr->length %d which is greater than %d can support",
    1447             :                                 __func__, p.prefixlen, p.family);
    1448           0 :                         return;
    1449             :                 }
    1450           0 :                 l += 5;
    1451           0 :                 STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
    1452           0 :                 l += PSIZE(p.prefixlen);
    1453           0 :                 zebra_mpls_fec_unregister(zvrf, &p, client);
    1454             :         }
    1455             : 
    1456           0 : stream_failure:
    1457             :         return;
    1458             : }
    1459             : 
    1460             : 
    1461             : /*
    1462             :  * Register zebra server interface information.
    1463             :  * Send current all interface and address information.
    1464             :  */
    1465          16 : static void zread_interface_add(ZAPI_HANDLER_ARGS)
    1466             : {
    1467          16 :         struct vrf *vrf;
    1468          16 :         struct interface *ifp;
    1469             : 
    1470          16 :         vrf_id_t vrf_id = zvrf_id(zvrf);
    1471          16 :         if (vrf_id != VRF_DEFAULT && vrf_id != VRF_UNKNOWN) {
    1472           0 :                 FOR_ALL_INTERFACES (zvrf->vrf, ifp) {
    1473             :                         /* Skip pseudo interface. */
    1474           0 :                         if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
    1475           0 :                                 continue;
    1476             : 
    1477           0 :                         zsend_interface_add(client, ifp);
    1478           0 :                         zsend_interface_link_params(client, ifp);
    1479           0 :                         zsend_interface_addresses(client, ifp);
    1480             :                 }
    1481           0 :                 return;
    1482             :         }
    1483             : 
    1484          48 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
    1485          72 :                 FOR_ALL_INTERFACES (vrf, ifp) {
    1486             :                         /* Skip pseudo interface. */
    1487          40 :                         if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
    1488           0 :                                 continue;
    1489             : 
    1490          40 :                         zsend_interface_add(client, ifp);
    1491          40 :                         zsend_interface_link_params(client, ifp);
    1492          40 :                         zsend_interface_addresses(client, ifp);
    1493             :                 }
    1494             :         }
    1495             : }
    1496             : 
    1497             : /* Unregister zebra server interface information. */
    1498           0 : static void zread_interface_delete(ZAPI_HANDLER_ARGS)
    1499             : {
    1500           0 : }
    1501             : 
    1502             : /*
    1503             :  * Handle message requesting interface be set up or down.
    1504             :  */
    1505           0 : static void zread_interface_set_protodown(ZAPI_HANDLER_ARGS)
    1506             : {
    1507           0 :         ifindex_t ifindex;
    1508           0 :         struct interface *ifp;
    1509           0 :         char down;
    1510           0 :         enum protodown_reasons reason;
    1511             : 
    1512           0 :         STREAM_GETL(msg, ifindex);
    1513           0 :         STREAM_GETC(msg, down);
    1514             : 
    1515             :         /* set ifdown */
    1516           0 :         ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
    1517             : 
    1518           0 :         if (!ifp) {
    1519           0 :                 zlog_warn(
    1520             :                         "Cannot set protodown %s for interface %u; does not exist",
    1521             :                         down ? "on" : "off", ifindex);
    1522             : 
    1523           0 :                 return;
    1524             :         }
    1525             : 
    1526           0 :         switch (client->proto) {
    1527             :         case ZEBRA_ROUTE_VRRP:
    1528             :                 reason = ZEBRA_PROTODOWN_VRRP;
    1529             :                 break;
    1530           0 :         case ZEBRA_ROUTE_SHARP:
    1531           0 :                 reason = ZEBRA_PROTODOWN_SHARP;
    1532           0 :                 break;
    1533           0 :         default:
    1534           0 :                 reason = 0;
    1535           0 :                 break;
    1536             :         }
    1537             : 
    1538           0 :         zebra_if_set_protodown(ifp, down, reason);
    1539             : 
    1540           0 : stream_failure:
    1541             :         return;
    1542             : }
    1543             : 
    1544           0 : bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
    1545             :                             const unsigned int nexthop_num)
    1546             : {
    1547           0 :         if (nexthop_num > zrouter.multipath_num) {
    1548           0 :                 char buff[PREFIX2STR_BUFFER];
    1549             : 
    1550           0 :                 if (p)
    1551           0 :                         prefix2str(p, buff, sizeof(buff));
    1552             : 
    1553           0 :                 flog_warn(
    1554             :                         EC_ZEBRA_MORE_NH_THAN_MULTIPATH,
    1555             :                         "%s: Prefix %s has %d nexthops, but we can only use the first %d",
    1556             :                         caller, (p ? buff : "(NULL)"), nexthop_num,
    1557             :                         zrouter.multipath_num);
    1558           0 :                 return true;
    1559             :         }
    1560             : 
    1561             :         return false;
    1562             : }
    1563             : 
    1564             : /*
    1565             :  * Create a new nexthop based on a zapi nexthop.
    1566             :  */
    1567           0 : static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
    1568             :                                          uint32_t flags, struct prefix *p,
    1569             :                                          uint16_t backup_nexthop_num)
    1570             : {
    1571           0 :         struct nexthop *nexthop = NULL;
    1572           0 :         struct ipaddr vtep_ip;
    1573           0 :         struct interface *ifp;
    1574           0 :         int i;
    1575           0 :         char nhbuf[INET6_ADDRSTRLEN] = "";
    1576             : 
    1577           0 :         switch (api_nh->type) {
    1578           0 :         case NEXTHOP_TYPE_IFINDEX:
    1579           0 :                 nexthop = nexthop_from_ifindex(api_nh->ifindex, api_nh->vrf_id);
    1580           0 :                 break;
    1581           0 :         case NEXTHOP_TYPE_IPV4:
    1582           0 :                 if (IS_ZEBRA_DEBUG_RECV) {
    1583           0 :                         inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf,
    1584             :                                   sizeof(nhbuf));
    1585           0 :                         zlog_debug("%s: nh=%s, vrf_id=%d", __func__,
    1586             :                                    nhbuf, api_nh->vrf_id);
    1587             :                 }
    1588           0 :                 nexthop = nexthop_from_ipv4(&api_nh->gate.ipv4, NULL,
    1589           0 :                                             api_nh->vrf_id);
    1590           0 :                 break;
    1591           0 :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1592           0 :                 if (IS_ZEBRA_DEBUG_RECV) {
    1593           0 :                         inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf,
    1594             :                                   sizeof(nhbuf));
    1595           0 :                         zlog_debug("%s: nh=%s, vrf_id=%d, ifindex=%d",
    1596             :                                    __func__, nhbuf, api_nh->vrf_id,
    1597             :                                    api_nh->ifindex);
    1598             :                 }
    1599             : 
    1600           0 :                 nexthop = nexthop_from_ipv4_ifindex(
    1601           0 :                         &api_nh->gate.ipv4, NULL, api_nh->ifindex,
    1602           0 :                         api_nh->vrf_id);
    1603             : 
    1604             :                 /* Special handling for IPv4 routes sourced from EVPN:
    1605             :                  * the nexthop and associated MAC need to be installed.
    1606             :                  */
    1607           0 :                 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
    1608           0 :                         memset(&vtep_ip, 0, sizeof(vtep_ip));
    1609           0 :                         vtep_ip.ipa_type = IPADDR_V4;
    1610           0 :                         memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4),
    1611             :                                sizeof(struct in_addr));
    1612           0 :                         zebra_rib_queue_evpn_route_add(
    1613           0 :                                 api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
    1614           0 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN);
    1615             :                 }
    1616             :                 break;
    1617           0 :         case NEXTHOP_TYPE_IPV6:
    1618           0 :                 if (IS_ZEBRA_DEBUG_RECV) {
    1619           0 :                         inet_ntop(AF_INET6, &api_nh->gate.ipv6, nhbuf,
    1620             :                                   sizeof(nhbuf));
    1621           0 :                         zlog_debug("%s: nh=%s, vrf_id=%d", __func__,
    1622             :                                    nhbuf, api_nh->vrf_id);
    1623             :                 }
    1624           0 :                 nexthop = nexthop_from_ipv6(&api_nh->gate.ipv6, api_nh->vrf_id);
    1625           0 :                 break;
    1626           0 :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1627           0 :                 if (IS_ZEBRA_DEBUG_RECV) {
    1628           0 :                         inet_ntop(AF_INET6, &api_nh->gate.ipv6, nhbuf,
    1629             :                                   sizeof(nhbuf));
    1630           0 :                         zlog_debug("%s: nh=%s, vrf_id=%d, ifindex=%d",
    1631             :                                    __func__, nhbuf, api_nh->vrf_id,
    1632             :                                    api_nh->ifindex);
    1633             :                 }
    1634           0 :                 nexthop = nexthop_from_ipv6_ifindex(&api_nh->gate.ipv6,
    1635           0 :                                                     api_nh->ifindex,
    1636           0 :                                                     api_nh->vrf_id);
    1637             : 
    1638             :                 /* Special handling for IPv6 routes sourced from EVPN:
    1639             :                  * the nexthop and associated MAC need to be installed.
    1640             :                  */
    1641           0 :                 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) {
    1642           0 :                         memset(&vtep_ip, 0, sizeof(vtep_ip));
    1643           0 :                         vtep_ip.ipa_type = IPADDR_V6;
    1644           0 :                         memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
    1645             :                                sizeof(struct in6_addr));
    1646           0 :                         zebra_rib_queue_evpn_route_add(
    1647           0 :                                 api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
    1648           0 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN);
    1649             :                 }
    1650             :                 break;
    1651           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    1652           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    1653           0 :                         zlog_debug("%s: nh blackhole %d",
    1654             :                                    __func__, api_nh->bh_type);
    1655             : 
    1656           0 :                 nexthop =
    1657           0 :                         nexthop_from_blackhole(api_nh->bh_type, api_nh->vrf_id);
    1658           0 :                 break;
    1659             :         }
    1660             : 
    1661             :         /* Return early if we couldn't process the zapi nexthop */
    1662           0 :         if (nexthop == NULL) {
    1663           0 :                 goto done;
    1664             :         }
    1665             : 
    1666             :         /* Mark nexthop as onlink either if client has explicitly told us
    1667             :          * to or if the nexthop is on an 'unnumbered' interface.
    1668             :          */
    1669           0 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK))
    1670           0 :                 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
    1671           0 :         else if (api_nh->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
    1672           0 :                 ifp = if_lookup_by_index(api_nh->ifindex, api_nh->vrf_id);
    1673           0 :                 if (ifp && connected_is_unnumbered(ifp))
    1674           0 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
    1675             :         }
    1676             : 
    1677           0 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
    1678           0 :                 nexthop->weight = api_nh->weight;
    1679             : 
    1680           0 :         if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
    1681             :                 /* Validate count */
    1682           0 :                 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
    1683           0 :                         if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
    1684           0 :                                 zlog_debug("%s: invalid backup nh count %d",
    1685             :                                            __func__, api_nh->backup_num);
    1686           0 :                         nexthop_free(nexthop);
    1687           0 :                         nexthop = NULL;
    1688           0 :                         goto done;
    1689             :                 }
    1690             : 
    1691             :                 /* Copy backup info */
    1692           0 :                 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
    1693           0 :                 nexthop->backup_num = api_nh->backup_num;
    1694             : 
    1695           0 :                 for (i = 0; i < api_nh->backup_num; i++) {
    1696             :                         /* Validate backup index */
    1697           0 :                         if (api_nh->backup_idx[i] < backup_nexthop_num) {
    1698           0 :                                 nexthop->backup_idx[i] = api_nh->backup_idx[i];
    1699             :                         } else {
    1700           0 :                                 if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
    1701           0 :                                         zlog_debug("%s: invalid backup nh idx %d",
    1702             :                                                    __func__,
    1703             :                                                    api_nh->backup_idx[i]);
    1704           0 :                                 nexthop_free(nexthop);
    1705           0 :                                 nexthop = NULL;
    1706           0 :                                 goto done;
    1707             :                         }
    1708             :                 }
    1709             :         }
    1710             : 
    1711           0 : done:
    1712           0 :         return nexthop;
    1713             : }
    1714             : 
    1715           0 : static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
    1716             :                                struct zapi_nexthop *nhops, uint32_t flags,
    1717             :                                uint32_t message, uint16_t nexthop_num,
    1718             :                                uint16_t backup_nh_num,
    1719             :                                struct nexthop_group **png,
    1720             :                                struct nhg_backup_info **pbnhg)
    1721             : {
    1722           0 :         struct nexthop_group *ng = NULL;
    1723           0 :         struct nhg_backup_info *bnhg = NULL;
    1724           0 :         uint16_t i;
    1725           0 :         struct nexthop *last_nh = NULL;
    1726             : 
    1727           0 :         assert(!(png && pbnhg));
    1728             : 
    1729           0 :         if (png)
    1730           0 :                 ng = nexthop_group_new();
    1731             : 
    1732           0 :         if (pbnhg && backup_nh_num > 0) {
    1733           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    1734           0 :                         zlog_debug("%s: adding %d backup nexthops", __func__,
    1735             :                                    backup_nh_num);
    1736             : 
    1737           0 :                 bnhg = zebra_nhg_backup_alloc();
    1738             :         }
    1739             : 
    1740             :         /*
    1741             :          * TBD should _all_ of the nexthop add operations use
    1742             :          * api_nh->vrf_id instead of re->vrf_id ? I only changed
    1743             :          * for cases NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6.
    1744             :          */
    1745           0 :         for (i = 0; i < nexthop_num; i++) {
    1746           0 :                 struct nexthop *nexthop;
    1747           0 :                 enum lsp_types_t label_type;
    1748           0 :                 char nhbuf[NEXTHOP_STRLEN];
    1749           0 :                 char labelbuf[MPLS_LABEL_STRLEN];
    1750           0 :                 struct zapi_nexthop *api_nh = &nhops[i];
    1751             : 
    1752             :                 /* Convert zapi nexthop */
    1753           0 :                 nexthop = nexthop_from_zapi(api_nh, flags, p, backup_nh_num);
    1754           0 :                 if (!nexthop) {
    1755           0 :                         flog_warn(
    1756             :                                 EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1757             :                                 "%s: Nexthops Specified: %u(%u) but we failed to properly create one",
    1758             :                                 __func__, nexthop_num, i);
    1759           0 :                         if (ng)
    1760           0 :                                 nexthop_group_delete(&ng);
    1761           0 :                         if (bnhg)
    1762           0 :                                 zebra_nhg_backup_free(&bnhg);
    1763           0 :                         return false;
    1764             :                 }
    1765             : 
    1766           0 :                 if (bnhg
    1767           0 :                     && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
    1768           0 :                         if (IS_ZEBRA_DEBUG_RECV) {
    1769           0 :                                 nexthop2str(nexthop, nhbuf, sizeof(nhbuf));
    1770           0 :                                 zlog_debug("%s: backup nh %s with BACKUP flag!",
    1771             :                                            __func__, nhbuf);
    1772             :                         }
    1773           0 :                         UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
    1774           0 :                         nexthop->backup_num = 0;
    1775             :                 }
    1776             : 
    1777           0 :                 if (CHECK_FLAG(message, ZAPI_MESSAGE_SRTE)) {
    1778           0 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
    1779           0 :                         nexthop->srte_color = api_nh->srte_color;
    1780             :                 }
    1781             : 
    1782             :                 /* MPLS labels for BGP-LU or Segment Routing */
    1783           0 :                 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
    1784           0 :                     && api_nh->type != NEXTHOP_TYPE_IFINDEX
    1785           0 :                     && api_nh->type != NEXTHOP_TYPE_BLACKHOLE
    1786           0 :                     && api_nh->label_num > 0) {
    1787             : 
    1788           0 :                         label_type = lsp_type_from_re_type(client->proto);
    1789           0 :                         nexthop_add_labels(nexthop, label_type,
    1790             :                                            api_nh->label_num,
    1791           0 :                                            &api_nh->labels[0]);
    1792             :                 }
    1793             : 
    1794           0 :                 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)
    1795           0 :                     && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
    1796           0 :                         if (IS_ZEBRA_DEBUG_RECV)
    1797           0 :                                 zlog_debug("%s: adding seg6local action %s",
    1798             :                                            __func__,
    1799             :                                            seg6local_action2str(
    1800             :                                                    api_nh->seg6local_action));
    1801             : 
    1802           0 :                         nexthop_add_srv6_seg6local(nexthop,
    1803             :                                                    api_nh->seg6local_action,
    1804           0 :                                                    &api_nh->seg6local_ctx);
    1805             :                 }
    1806             : 
    1807           0 :                 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6)
    1808           0 :                     && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
    1809           0 :                         if (IS_ZEBRA_DEBUG_RECV)
    1810           0 :                                 zlog_debug("%s: adding seg6", __func__);
    1811             : 
    1812           0 :                         nexthop_add_srv6_seg6(nexthop, &api_nh->seg6_segs);
    1813             :                 }
    1814             : 
    1815           0 :                 if (IS_ZEBRA_DEBUG_RECV) {
    1816           0 :                         labelbuf[0] = '\0';
    1817           0 :                         nhbuf[0] = '\0';
    1818             : 
    1819           0 :                         nexthop2str(nexthop, nhbuf, sizeof(nhbuf));
    1820             : 
    1821           0 :                         if (nexthop->nh_label &&
    1822           0 :                             nexthop->nh_label->num_labels > 0) {
    1823           0 :                                 mpls_label2str(nexthop->nh_label->num_labels,
    1824           0 :                                                nexthop->nh_label->label,
    1825             :                                                labelbuf, sizeof(labelbuf),
    1826             :                                                false);
    1827             :                         }
    1828             : 
    1829           0 :                         zlog_debug("%s: nh=%s, vrf_id=%d %s",
    1830             :                                    __func__, nhbuf, api_nh->vrf_id, labelbuf);
    1831             :                 }
    1832             : 
    1833           0 :                 if (ng) {
    1834             :                         /* Add new nexthop to temporary list. This list is
    1835             :                          * canonicalized - sorted - so that it can be hashed
    1836             :                          * later in route processing. We expect that the sender
    1837             :                          * has sent the list sorted, and the zapi client api
    1838             :                          * attempts to enforce that, so this should be
    1839             :                          * inexpensive - but it is necessary to support shared
    1840             :                          * nexthop-groups.
    1841             :                          */
    1842           0 :                         nexthop_group_add_sorted(ng, nexthop);
    1843             :                 }
    1844           0 :                 if (bnhg) {
    1845             :                         /* Note that the order of the backup nexthops is
    1846             :                          * significant, so we don't sort this list as we do the
    1847             :                          * primary nexthops, we just append.
    1848             :                          */
    1849           0 :                         if (last_nh)
    1850           0 :                                 NEXTHOP_APPEND(last_nh, nexthop);
    1851             :                         else
    1852           0 :                                 bnhg->nhe->nhg.nexthop = nexthop;
    1853             : 
    1854             :                         last_nh = nexthop;
    1855             :                 }
    1856             :         }
    1857             : 
    1858             : 
    1859             :         /* succesfully read, set caller pointers now */
    1860           0 :         if (png)
    1861           0 :                 *png = ng;
    1862             : 
    1863           0 :         if (pbnhg)
    1864           0 :                 *pbnhg = bnhg;
    1865             : 
    1866             :         return true;
    1867             : }
    1868             : 
    1869           0 : static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
    1870             : {
    1871           0 :         uint16_t i;
    1872           0 :         struct zapi_nexthop *znh;
    1873             : 
    1874           0 :         STREAM_GETW(s, api_nhg->proto);
    1875           0 :         STREAM_GETL(s, api_nhg->id);
    1876             : 
    1877           0 :         if (cmd == ZEBRA_NHG_DEL)
    1878           0 :                 goto done;
    1879             : 
    1880           0 :         STREAM_GETW(s, api_nhg->resilience.buckets);
    1881           0 :         STREAM_GETL(s, api_nhg->resilience.idle_timer);
    1882           0 :         STREAM_GETL(s, api_nhg->resilience.unbalanced_timer);
    1883             : 
    1884             :         /* Nexthops */
    1885           0 :         STREAM_GETW(s, api_nhg->nexthop_num);
    1886             : 
    1887           0 :         if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->nexthop_num))
    1888             :                 return -1;
    1889             : 
    1890           0 :         if (api_nhg->nexthop_num <= 0) {
    1891           0 :                 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1892             :                           "%s: No nexthops sent", __func__);
    1893           0 :                 return -1;
    1894             :         }
    1895             : 
    1896           0 :         for (i = 0; i < api_nhg->nexthop_num; i++) {
    1897           0 :                 znh = &((api_nhg->nexthops)[i]);
    1898             : 
    1899           0 :                 if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
    1900           0 :                         flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1901             :                                   "%s: Nexthop creation failed", __func__);
    1902           0 :                         return -1;
    1903             :                 }
    1904             :         }
    1905             : 
    1906             :         /* Backup Nexthops */
    1907           0 :         STREAM_GETW(s, api_nhg->backup_nexthop_num);
    1908             : 
    1909           0 :         if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->backup_nexthop_num))
    1910             :                 return -1;
    1911             : 
    1912           0 :         for (i = 0; i < api_nhg->backup_nexthop_num; i++) {
    1913           0 :                 znh = &((api_nhg->backup_nexthops)[i]);
    1914             : 
    1915           0 :                 if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
    1916           0 :                         flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1917             :                                   "%s: Backup Nexthop creation failed",
    1918             :                                   __func__);
    1919           0 :                         return -1;
    1920             :                 }
    1921             :         }
    1922             : 
    1923           0 : done:
    1924             :         return 0;
    1925             : 
    1926           0 : stream_failure:
    1927           0 :         flog_warn(
    1928             :                 EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1929             :                 "%s: Nexthop Group decode failed with some sort of stream read failure",
    1930             :                 __func__);
    1931           0 :         return -1;
    1932             : }
    1933             : 
    1934           0 : static void zread_nhg_del(ZAPI_HANDLER_ARGS)
    1935             : {
    1936           0 :         struct stream *s;
    1937           0 :         struct zapi_nhg api_nhg = {};
    1938           0 :         struct nhg_hash_entry *nhe;
    1939             : 
    1940           0 :         s = msg;
    1941           0 :         if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
    1942           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    1943           0 :                         zlog_debug("%s: Unable to decode zapi_nhg sent",
    1944             :                                    __func__);
    1945           0 :                 return;
    1946             :         }
    1947             : 
    1948             :         /*
    1949             :          * Delete the received nhg id
    1950             :          */
    1951           0 :         nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto);
    1952             : 
    1953           0 :         if (nhe) {
    1954           0 :                 zebra_nhg_decrement_ref(nhe);
    1955           0 :                 zsend_nhg_notify(api_nhg.proto, client->instance,
    1956             :                                  client->session_id, api_nhg.id,
    1957             :                                  ZAPI_NHG_REMOVED);
    1958             :         } else
    1959           0 :                 zsend_nhg_notify(api_nhg.proto, client->instance,
    1960             :                                  client->session_id, api_nhg.id,
    1961             :                                  ZAPI_NHG_REMOVE_FAIL);
    1962             : }
    1963             : 
    1964           0 : static void zread_nhg_add(ZAPI_HANDLER_ARGS)
    1965             : {
    1966           0 :         struct stream *s;
    1967           0 :         struct zapi_nhg api_nhg = {};
    1968           0 :         struct nexthop_group *nhg = NULL;
    1969           0 :         struct nhg_backup_info *bnhg = NULL;
    1970           0 :         struct nhg_hash_entry *nhe;
    1971             : 
    1972           0 :         s = msg;
    1973           0 :         if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
    1974           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    1975           0 :                         zlog_debug("%s: Unable to decode zapi_nhg sent",
    1976             :                                    __func__);
    1977           0 :                 return;
    1978             :         }
    1979             : 
    1980           0 :         if ((!zapi_read_nexthops(client, NULL, api_nhg.nexthops, 0, 0,
    1981           0 :                                  api_nhg.nexthop_num,
    1982           0 :                                  api_nhg.backup_nexthop_num, &nhg, NULL))
    1983           0 :             || (!zapi_read_nexthops(client, NULL, api_nhg.backup_nexthops, 0, 0,
    1984             :                                     api_nhg.backup_nexthop_num,
    1985           0 :                                     api_nhg.backup_nexthop_num, NULL, &bnhg))) {
    1986             : 
    1987           0 :                 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
    1988             :                           "%s: Nexthop Group Creation failed", __func__);
    1989             : 
    1990             :                 /* Free any local allocations */
    1991           0 :                 nexthop_group_delete(&nhg);
    1992           0 :                 zebra_nhg_backup_free(&bnhg);
    1993             : 
    1994           0 :                 return;
    1995             :         }
    1996             : 
    1997             :         /* Create a temporary nhe */
    1998           0 :         nhe = zebra_nhg_alloc();
    1999           0 :         nhe->id = api_nhg.id;
    2000           0 :         nhe->type = api_nhg.proto;
    2001           0 :         nhe->zapi_instance = client->instance;
    2002           0 :         nhe->zapi_session = client->session_id;
    2003             : 
    2004             :         /* Take over the list(s) of nexthops */
    2005           0 :         nhe->nhg.nexthop = nhg->nexthop;
    2006           0 :         nhg->nexthop = NULL;
    2007             : 
    2008           0 :         nhe->nhg.nhgr = api_nhg.resilience;
    2009             : 
    2010           0 :         if (bnhg) {
    2011           0 :                 nhe->backup_info = bnhg;
    2012           0 :                 bnhg = NULL;
    2013             :         }
    2014             : 
    2015             :         /*
    2016             :          * TODO:
    2017             :          * Assume fully resolved for now and install.
    2018             :          * Resolution is going to need some more work.
    2019             :          */
    2020             : 
    2021             :         /* Enqueue to workqueue for processing */
    2022           0 :         rib_queue_nhe_add(nhe);
    2023             : 
    2024             :         /* Free any local allocations */
    2025           0 :         nexthop_group_delete(&nhg);
    2026           0 :         zebra_nhg_backup_free(&bnhg);
    2027             : 
    2028             : }
    2029             : 
    2030           0 : static void zread_route_add(ZAPI_HANDLER_ARGS)
    2031             : {
    2032           0 :         struct stream *s;
    2033           0 :         struct zapi_route api;
    2034           0 :         afi_t afi;
    2035           0 :         struct prefix_ipv6 *src_p = NULL;
    2036           0 :         struct route_entry *re;
    2037           0 :         struct nexthop_group *ng = NULL;
    2038           0 :         struct nhg_backup_info *bnhg = NULL;
    2039           0 :         int ret;
    2040           0 :         vrf_id_t vrf_id;
    2041           0 :         struct nhg_hash_entry nhe, *n = NULL;
    2042             : 
    2043           0 :         s = msg;
    2044           0 :         if (zapi_route_decode(s, &api) < 0) {
    2045           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2046           0 :                         zlog_debug("%s: Unable to decode zapi_route sent",
    2047             :                                    __func__);
    2048           0 :                 return;
    2049             :         }
    2050             : 
    2051           0 :         vrf_id = zvrf_id(zvrf);
    2052             : 
    2053           0 :         if (IS_ZEBRA_DEBUG_RECV)
    2054           0 :                 zlog_debug("%s: p=(%u:%u)%pFX, msg flags=0x%x, flags=0x%x",
    2055             :                            __func__, vrf_id, api.tableid, &api.prefix,
    2056             :                            (int)api.message, api.flags);
    2057             : 
    2058             :         /* Allocate new route. */
    2059           0 :         re = zebra_rib_route_entry_new(
    2060           0 :                 vrf_id, api.type, api.instance, api.flags, api.nhgid,
    2061           0 :                 api.tableid ? api.tableid : zvrf->table_id, api.metric, api.mtu,
    2062           0 :                 api.distance, api.tag);
    2063             : 
    2064           0 :         if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG)
    2065           0 :             && (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)
    2066           0 :                 || api.nexthop_num == 0)) {
    2067           0 :                 flog_warn(
    2068             :                         EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS,
    2069             :                         "%s: received a route without nexthops for prefix %pFX from client %s",
    2070             :                         __func__, &api.prefix,
    2071             :                         zebra_route_string(client->proto));
    2072             : 
    2073           0 :                 XFREE(MTYPE_RE, re);
    2074           0 :                 return;
    2075             :         }
    2076             : 
    2077             :         /* Report misuse of the backup flag */
    2078           0 :         if (CHECK_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)
    2079           0 :             && api.backup_nexthop_num == 0) {
    2080           0 :                 if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
    2081           0 :                         zlog_debug(
    2082             :                                 "%s: client %s: BACKUP flag set but no backup nexthops, prefix %pFX",
    2083             :                                 __func__, zebra_route_string(client->proto),
    2084             :                                 &api.prefix);
    2085             :         }
    2086             : 
    2087           0 :         if (!re->nhe_id
    2088           0 :             && (!zapi_read_nexthops(client, &api.prefix, api.nexthops,
    2089           0 :                                     api.flags, api.message, api.nexthop_num,
    2090           0 :                                     api.backup_nexthop_num, &ng, NULL)
    2091           0 :                 || !zapi_read_nexthops(client, &api.prefix, api.backup_nexthops,
    2092             :                                        api.flags, api.message,
    2093             :                                        api.backup_nexthop_num,
    2094           0 :                                        api.backup_nexthop_num, NULL, &bnhg))) {
    2095             : 
    2096           0 :                 nexthop_group_delete(&ng);
    2097           0 :                 zebra_nhg_backup_free(&bnhg);
    2098           0 :                 XFREE(MTYPE_RE, re);
    2099           0 :                 return;
    2100             :         }
    2101             : 
    2102           0 :         if (CHECK_FLAG(api.message, ZAPI_MESSAGE_OPAQUE)) {
    2103           0 :                 re->opaque =
    2104           0 :                         XMALLOC(MTYPE_RE_OPAQUE,
    2105             :                                 sizeof(struct re_opaque) + api.opaque.length);
    2106           0 :                 re->opaque->length = api.opaque.length;
    2107           0 :                 memcpy(re->opaque->data, api.opaque.data, re->opaque->length);
    2108             :         }
    2109             : 
    2110           0 :         afi = family2afi(api.prefix.family);
    2111           0 :         if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
    2112           0 :                 flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI,
    2113             :                           "%s: Received SRC Prefix but afi is not v6",
    2114             :                           __func__);
    2115           0 :                 nexthop_group_delete(&ng);
    2116           0 :                 zebra_nhg_backup_free(&bnhg);
    2117           0 :                 XFREE(MTYPE_RE_OPAQUE, re->opaque);
    2118           0 :                 XFREE(MTYPE_RE, re);
    2119           0 :                 return;
    2120             :         }
    2121           0 :         if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
    2122           0 :                 src_p = &api.src_prefix;
    2123             : 
    2124           0 :         if (api.safi != SAFI_UNICAST && api.safi != SAFI_MULTICAST) {
    2125           0 :                 flog_warn(EC_LIB_ZAPI_MISSMATCH,
    2126             :                           "%s: Received safi: %d but we can only accept UNICAST or MULTICAST",
    2127             :                           __func__, api.safi);
    2128           0 :                 nexthop_group_delete(&ng);
    2129           0 :                 zebra_nhg_backup_free(&bnhg);
    2130           0 :                 XFREE(MTYPE_RE_OPAQUE, re->opaque);
    2131           0 :                 XFREE(MTYPE_RE, re);
    2132           0 :                 return;
    2133             :         }
    2134             : 
    2135             :         /*
    2136             :          * If we have an ID, this proto owns the NHG it sent along with the
    2137             :          * route, so we just send the ID into rib code with it.
    2138             :          *
    2139             :          * Havent figured out how to handle backup NHs with this yet, so lets
    2140             :          * keep that separate.
    2141             :          * Include backup info with the route. We use a temporary nhe here;
    2142             :          * if this is a new/unknown nhe, a new copy will be allocated
    2143             :          * and stored.
    2144             :          */
    2145           0 :         if (!re->nhe_id) {
    2146           0 :                 zebra_nhe_init(&nhe, afi, ng->nexthop);
    2147           0 :                 nhe.nhg.nexthop = ng->nexthop;
    2148           0 :                 nhe.backup_info = bnhg;
    2149           0 :                 n = zebra_nhe_copy(&nhe, 0);
    2150             :         }
    2151           0 :         ret = rib_add_multipath_nhe(afi, api.safi, &api.prefix, src_p, re, n,
    2152             :                                     false);
    2153             : 
    2154             :         /*
    2155             :          * rib_add_multipath_nhe only fails in a couple spots
    2156             :          * and in those spots we have not freed memory
    2157             :          */
    2158           0 :         if (ret == -1) {
    2159           0 :                 client->error_cnt++;
    2160           0 :                 XFREE(MTYPE_RE_OPAQUE, re->opaque);
    2161           0 :                 XFREE(MTYPE_RE, re);
    2162             :         }
    2163             : 
    2164             :         /* At this point, these allocations are not needed: 're' has been
    2165             :          * retained or freed, and if 're' still exists, it is using
    2166             :          * a reference to a shared group object.
    2167             :          */
    2168           0 :         nexthop_group_delete(&ng);
    2169           0 :         if (bnhg)
    2170           0 :                 zebra_nhg_backup_free(&bnhg);
    2171             : 
    2172             :         /* Stats */
    2173           0 :         switch (api.prefix.family) {
    2174           0 :         case AF_INET:
    2175           0 :                 if (ret == 0)
    2176           0 :                         client->v4_route_add_cnt++;
    2177           0 :                 else if (ret == 1)
    2178           0 :                         client->v4_route_upd8_cnt++;
    2179             :                 break;
    2180           0 :         case AF_INET6:
    2181           0 :                 if (ret == 0)
    2182           0 :                         client->v6_route_add_cnt++;
    2183           0 :                 else if (ret == 1)
    2184           0 :                         client->v6_route_upd8_cnt++;
    2185             :                 break;
    2186             :         }
    2187             : }
    2188             : 
    2189          82 : void zapi_re_opaque_free(struct re_opaque *opaque)
    2190             : {
    2191          82 :         XFREE(MTYPE_RE_OPAQUE, opaque);
    2192          82 : }
    2193             : 
    2194           0 : static void zread_route_del(ZAPI_HANDLER_ARGS)
    2195             : {
    2196           0 :         struct stream *s;
    2197           0 :         struct zapi_route api;
    2198           0 :         afi_t afi;
    2199           0 :         struct prefix_ipv6 *src_p = NULL;
    2200           0 :         uint32_t table_id;
    2201             : 
    2202           0 :         s = msg;
    2203           0 :         if (zapi_route_decode(s, &api) < 0)
    2204           0 :                 return;
    2205             : 
    2206           0 :         afi = family2afi(api.prefix.family);
    2207           0 :         if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
    2208           0 :                 flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI,
    2209             :                           "%s: Received a src prefix while afi is not v6",
    2210             :                           __func__);
    2211           0 :                 return;
    2212             :         }
    2213           0 :         if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
    2214           0 :                 src_p = &api.src_prefix;
    2215             : 
    2216           0 :         if (api.tableid)
    2217             :                 table_id = api.tableid;
    2218             :         else
    2219           0 :                 table_id = zvrf->table_id;
    2220             : 
    2221           0 :         if (IS_ZEBRA_DEBUG_RECV)
    2222           0 :                 zlog_debug("%s: p=(%u:%u)%pFX, msg flags=0x%x, flags=0x%x",
    2223             :                            __func__, zvrf_id(zvrf), table_id, &api.prefix,
    2224             :                            (int)api.message, api.flags);
    2225             : 
    2226           0 :         rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
    2227             :                    api.flags, &api.prefix, src_p, NULL, 0, table_id, api.metric,
    2228           0 :                    api.distance, false);
    2229             : 
    2230             :         /* Stats */
    2231           0 :         switch (api.prefix.family) {
    2232           0 :         case AF_INET:
    2233           0 :                 client->v4_route_del_cnt++;
    2234           0 :                 break;
    2235           0 :         case AF_INET6:
    2236           0 :                 client->v6_route_del_cnt++;
    2237           0 :                 break;
    2238             :         }
    2239             : }
    2240             : 
    2241             : /* MRIB Nexthop lookup for IPv4. */
    2242           0 : static void zread_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
    2243             : {
    2244           0 :         struct ipaddr addr;
    2245           0 :         struct route_entry *re = NULL;
    2246             : 
    2247           0 :         STREAM_GET_IPADDR(msg, &addr);
    2248             : 
    2249           0 :         switch (addr.ipa_type) {
    2250             :         case IPADDR_V4:
    2251           0 :                 re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr.ipaddr_v4,
    2252             :                                               NULL);
    2253           0 :                 break;
    2254             :         case IPADDR_V6:
    2255           0 :                 re = rib_match_ipv6_multicast(zvrf_id(zvrf), addr.ipaddr_v6,
    2256             :                                               NULL);
    2257           0 :                 break;
    2258           0 :         case IPADDR_NONE:
    2259             :                 /* ??? */
    2260           0 :                 goto stream_failure;
    2261             :         }
    2262             : 
    2263           0 :         zsend_nexthop_lookup_mrib(client, &addr, re, zvrf);
    2264             : 
    2265           0 : stream_failure:
    2266           0 :         return;
    2267             : }
    2268             : 
    2269             : /* Register zebra server router-id information.  Send current router-id */
    2270           4 : static void zread_router_id_add(ZAPI_HANDLER_ARGS)
    2271             : {
    2272           4 :         afi_t afi;
    2273           4 :         struct prefix p;
    2274           4 :         struct prefix zero;
    2275             : 
    2276           4 :         STREAM_GETW(msg, afi);
    2277             : 
    2278           4 :         if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
    2279           0 :                 zlog_warn(
    2280             :                         "Invalid AFI %u while registering for router ID notifications",
    2281             :                         afi);
    2282           0 :                 goto stream_failure;
    2283             :         }
    2284             : 
    2285             :         /* Router-id information is needed. */
    2286           8 :         vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf));
    2287             : 
    2288           4 :         router_id_get(afi, &p, zvrf);
    2289             : 
    2290             :         /*
    2291             :          * If we have not officially setup a router-id let's not
    2292             :          * tell the upper level protocol about it yet.
    2293             :          */
    2294           4 :         memset(&zero, 0, sizeof(zero));
    2295           4 :         if ((p.family == AF_INET && p.u.prefix4.s_addr == INADDR_ANY)
    2296           4 :             || (p.family == AF_INET6
    2297           0 :                 && memcmp(&p.u.prefix6, &zero.u.prefix6,
    2298             :                           sizeof(struct in6_addr))
    2299             :                            == 0))
    2300             :                 return;
    2301             : 
    2302           8 :         zsend_router_id_update(client, afi, &p, zvrf_id(zvrf));
    2303             : 
    2304           4 : stream_failure:
    2305             :         return;
    2306             : }
    2307             : 
    2308             : /* Unregister zebra server router-id information. */
    2309           0 : static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
    2310             : {
    2311           0 :         afi_t afi;
    2312             : 
    2313           0 :         STREAM_GETW(msg, afi);
    2314             : 
    2315           0 :         if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
    2316           0 :                 zlog_warn(
    2317             :                         "Invalid AFI %u while unregistering from router ID notifications",
    2318             :                         afi);
    2319           0 :                 goto stream_failure;
    2320             :         }
    2321             : 
    2322           0 :         vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
    2323             : 
    2324           0 : stream_failure:
    2325           0 :         return;
    2326             : }
    2327             : 
    2328           8 : static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
    2329             : {
    2330           8 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2331             : 
    2332           8 :         zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id);
    2333           8 :         stream_putl(s, vrf_get_backend());
    2334           8 :         stream_putc(s, mpls_enabled);
    2335           8 :         stream_putl(s, zrouter.multipath_num);
    2336           8 :         stream_putc(s, zebra_mlag_get_role());
    2337             : 
    2338           8 :         stream_putw_at(s, 0, stream_get_endp(s));
    2339           8 :         zserv_send_message(client, s);
    2340           8 : }
    2341             : 
    2342           0 : void zsend_capabilities_all_clients(void)
    2343             : {
    2344           0 :         struct listnode *node, *nnode;
    2345           0 :         struct zebra_vrf *zvrf;
    2346           0 :         struct zserv *client;
    2347             : 
    2348           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    2349           0 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
    2350             :                 /* Do not send unsolicited messages to synchronous clients. */
    2351           0 :                 if (client->synchronous)
    2352           0 :                         continue;
    2353             : 
    2354           0 :                 zsend_capabilities(client, zvrf);
    2355             :         }
    2356           0 : }
    2357             : 
    2358             : /* Tie up route-type and client->sock */
    2359          12 : static void zread_hello(ZAPI_HANDLER_ARGS)
    2360             : {
    2361             :         /* type of protocol (lib/zebra.h) */
    2362          12 :         uint8_t proto;
    2363          12 :         unsigned short instance;
    2364          12 :         uint8_t notify;
    2365          12 :         uint8_t synchronous;
    2366          12 :         uint32_t session_id;
    2367             : 
    2368          12 :         STREAM_GETC(msg, proto);
    2369          12 :         STREAM_GETW(msg, instance);
    2370          12 :         STREAM_GETL(msg, session_id);
    2371          12 :         STREAM_GETC(msg, notify);
    2372          12 :         STREAM_GETC(msg, synchronous);
    2373          12 :         if (notify)
    2374           0 :                 client->notify_owner = true;
    2375             : 
    2376          12 :         if (synchronous)
    2377           4 :                 client->synchronous = true;
    2378             : 
    2379             :         /* accept only dynamic routing protocols */
    2380          12 :         if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_CONNECT)) {
    2381           8 :                 zlog_notice(
    2382             :                         "client %d says hello and bids fair to announce only %s routes vrf=%u",
    2383             :                         client->sock, zebra_route_string(proto),
    2384             :                         zvrf->vrf->vrf_id);
    2385           8 :                 if (instance)
    2386           0 :                         zlog_notice("client protocol instance %d", instance);
    2387             : 
    2388           8 :                 client->proto = proto;
    2389           8 :                 client->instance = instance;
    2390           8 :                 client->session_id = session_id;
    2391             : 
    2392             :                 /* Graceful restart processing for client connect */
    2393           8 :                 zebra_gr_client_reconnect(client);
    2394             :         }
    2395             : 
    2396          12 :         if (!client->synchronous) {
    2397           8 :                 zsend_capabilities(client, zvrf);
    2398           8 :                 zebra_vrf_update_all(client);
    2399             :         }
    2400           4 : stream_failure:
    2401          12 :         return;
    2402             : }
    2403             : 
    2404             : /* Unregister all information in a VRF. */
    2405           0 : static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
    2406             : {
    2407           0 :         int i;
    2408           0 :         afi_t afi;
    2409             : 
    2410           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    2411           0 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
    2412           0 :                         vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
    2413           0 :                 vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
    2414           0 :                 vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
    2415           0 :                 vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
    2416             :         }
    2417           0 : }
    2418             : 
    2419             : /*
    2420             :  * Validate incoming zapi mpls lsp / labels message
    2421             :  */
    2422           0 : static int zapi_labels_validate(const struct zapi_labels *zl)
    2423             : {
    2424           0 :         int ret = -1;
    2425           0 :         int i, j, idx;
    2426           0 :         uint32_t bits[8];
    2427           0 :         uint32_t ival;
    2428           0 :         const struct zapi_nexthop *znh;
    2429             : 
    2430             :         /* Validate backup info: no duplicates for a single primary */
    2431           0 :         if (zl->backup_nexthop_num == 0) {
    2432           0 :                 ret = 0;
    2433           0 :                 goto done;
    2434             :         }
    2435             : 
    2436           0 :         for (j = 0; j < zl->nexthop_num; j++) {
    2437           0 :                 znh = &zl->nexthops[j];
    2438             : 
    2439           0 :                 memset(bits, 0, sizeof(bits));
    2440             : 
    2441           0 :                 for (i = 0; i < znh->backup_num; i++) {
    2442           0 :                         idx = znh->backup_idx[i] / 32;
    2443             : 
    2444           0 :                         ival = 1 << znh->backup_idx[i] % 32;
    2445             : 
    2446             :                         /* Check whether value is already used */
    2447           0 :                         if (ival & bits[idx]) {
    2448             :                                 /* Fail */
    2449             : 
    2450           0 :                                 if (IS_ZEBRA_DEBUG_RECV)
    2451           0 :                                         zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d",
    2452             :                                                    __func__,
    2453             :                                                    znh->backup_idx[i]);
    2454           0 :                                 goto done;
    2455             :                         }
    2456             : 
    2457             :                         /* Mark index value */
    2458           0 :                         bits[idx] |= ival;
    2459             :                 }
    2460             :         }
    2461             : 
    2462             :         ret = 0;
    2463             : 
    2464           0 : done:
    2465             : 
    2466           0 :         return ret;
    2467             : }
    2468             : 
    2469             : /*
    2470             :  * Handle request to create an MPLS LSP.
    2471             :  *
    2472             :  * A single message can fully specify an LSP with multiple nexthops.
    2473             :  *
    2474             :  * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
    2475             :  * updated to use the received label(s).
    2476             :  */
    2477           0 : static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
    2478             : {
    2479           0 :         struct stream *s;
    2480           0 :         struct zapi_labels zl;
    2481             : 
    2482             :         /* Get input stream.  */
    2483           0 :         s = msg;
    2484           0 :         if (zapi_labels_decode(s, &zl) < 0) {
    2485           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2486           0 :                         zlog_debug("%s: Unable to decode zapi_labels sent",
    2487             :                                    __func__);
    2488           0 :                 return;
    2489             :         }
    2490             : 
    2491           0 :         if (!mpls_enabled)
    2492             :                 return;
    2493             : 
    2494             :         /* Validate; will debug on failure */
    2495           0 :         if (zapi_labels_validate(&zl) < 0)
    2496             :                 return;
    2497             : 
    2498           0 :         mpls_zapi_labels_process(true, zvrf, &zl);
    2499             : }
    2500             : 
    2501             : /*
    2502             :  * Handle request to delete an MPLS LSP.
    2503             :  *
    2504             :  * An LSP is identified by its type and local label. When the received message
    2505             :  * doesn't contain any nexthop, the whole LSP is deleted. Otherwise, only the
    2506             :  * listed LSP nexthops (aka NHLFEs) are deleted.
    2507             :  *
    2508             :  * When the optional ZAPI_LABELS_FTN flag is set, the labels of the specified
    2509             :  * FEC (route) nexthops are deleted.
    2510             :  */
    2511           0 : static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
    2512             : {
    2513           0 :         struct stream *s;
    2514           0 :         struct zapi_labels zl;
    2515             : 
    2516             :         /* Get input stream.  */
    2517           0 :         s = msg;
    2518           0 :         if (zapi_labels_decode(s, &zl) < 0) {
    2519           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2520           0 :                         zlog_debug("%s: Unable to decode zapi_labels sent",
    2521             :                                    __func__);
    2522           0 :                 return;
    2523             :         }
    2524             : 
    2525           0 :         if (!mpls_enabled)
    2526             :                 return;
    2527             : 
    2528           0 :         if (zl.nexthop_num > 0) {
    2529           0 :                 mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
    2530             :         } else {
    2531           0 :                 mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
    2532             : 
    2533           0 :                 if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
    2534           0 :                         mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
    2535           0 :                                            zl.route.type, zl.route.instance);
    2536             :         }
    2537             : }
    2538             : 
    2539             : /*
    2540             :  * Handle request to add an MPLS LSP or change an existing one.
    2541             :  *
    2542             :  * A single message can fully specify an LSP with multiple nexthops.
    2543             :  *
    2544             :  * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
    2545             :  * updated to use the received label(s).
    2546             :  *
    2547             :  * NOTE: zebra will use route replace semantics (make-before-break) to update
    2548             :  * the LSP in the forwarding plane if that's supported by the underlying
    2549             :  * platform.
    2550             :  */
    2551           0 : static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
    2552             : {
    2553           0 :         struct stream *s;
    2554           0 :         struct zapi_labels zl;
    2555             : 
    2556             :         /* Get input stream.  */
    2557           0 :         s = msg;
    2558           0 :         if (zapi_labels_decode(s, &zl) < 0) {
    2559           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2560           0 :                         zlog_debug("%s: Unable to decode zapi_labels sent",
    2561             :                                    __func__);
    2562           0 :                 return;
    2563             :         }
    2564             : 
    2565           0 :         if (!mpls_enabled)
    2566             :                 return;
    2567             : 
    2568             :         /* Validate; will debug on failure */
    2569           0 :         if (zapi_labels_validate(&zl) < 0)
    2570             :                 return;
    2571             : 
    2572             :         /* This removes everything, then re-adds from the client's
    2573             :          * zapi message. Since the LSP will be processed later, on this
    2574             :          * this same pthread, all of the changes will 'appear' at once.
    2575             :          */
    2576           0 :         mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
    2577           0 :         if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
    2578           0 :                 mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
    2579           0 :                                    zl.route.type, zl.route.instance);
    2580             : 
    2581           0 :         mpls_zapi_labels_process(true, zvrf, &zl);
    2582             : }
    2583             : 
    2584           0 : static void zread_sr_policy_set(ZAPI_HANDLER_ARGS)
    2585             : {
    2586           0 :         struct stream *s;
    2587           0 :         struct zapi_sr_policy zp;
    2588           0 :         struct zapi_srte_tunnel *zt;
    2589           0 :         struct zebra_sr_policy *policy;
    2590             : 
    2591             :         /* Get input stream.  */
    2592           0 :         s = msg;
    2593           0 :         if (zapi_sr_policy_decode(s, &zp) < 0) {
    2594           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2595           0 :                         zlog_debug("%s: Unable to decode zapi_sr_policy sent",
    2596             :                                    __func__);
    2597           0 :                 return;
    2598             :         }
    2599           0 :         zt = &zp.segment_list;
    2600           0 :         if (zt->label_num < 1) {
    2601           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2602           0 :                         zlog_debug(
    2603             :                                 "%s: SR-TE tunnel must contain at least one label",
    2604             :                                 __func__);
    2605           0 :                 return;
    2606             :         }
    2607             : 
    2608           0 :         if (!mpls_enabled)
    2609             :                 return;
    2610             : 
    2611           0 :         policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
    2612           0 :         if (!policy) {
    2613           0 :                 policy = zebra_sr_policy_add(zp.color, &zp.endpoint, zp.name);
    2614           0 :                 policy->sock = client->sock;
    2615             :         }
    2616             :         /* TODO: per-VRF list of SR-TE policies. */
    2617           0 :         policy->zvrf = zvrf;
    2618             : 
    2619           0 :         zebra_sr_policy_validate(policy, &zp.segment_list);
    2620             : }
    2621             : 
    2622           0 : static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS)
    2623             : {
    2624           0 :         struct stream *s;
    2625           0 :         struct zapi_sr_policy zp;
    2626           0 :         struct zebra_sr_policy *policy;
    2627             : 
    2628             :         /* Get input stream.  */
    2629           0 :         s = msg;
    2630           0 :         if (zapi_sr_policy_decode(s, &zp) < 0) {
    2631           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2632           0 :                         zlog_debug("%s: Unable to decode zapi_sr_policy sent",
    2633             :                                    __func__);
    2634           0 :                 return;
    2635             :         }
    2636             : 
    2637           0 :         if (!mpls_enabled)
    2638             :                 return;
    2639             : 
    2640           0 :         policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
    2641           0 :         if (!policy) {
    2642           0 :                 if (IS_ZEBRA_DEBUG_RECV)
    2643           0 :                         zlog_debug("%s: Unable to find SR-TE policy", __func__);
    2644           0 :                 return;
    2645             :         }
    2646             : 
    2647           0 :         zebra_sr_policy_del(policy);
    2648             : }
    2649             : 
    2650           0 : int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
    2651             :                                   char *name, int status)
    2652             : {
    2653           0 :         struct zserv *client;
    2654           0 :         struct stream *s;
    2655             : 
    2656           0 :         client = zserv_find_client(ZEBRA_ROUTE_SRTE, 0);
    2657           0 :         if (!client) {
    2658           0 :                 if (IS_ZEBRA_DEBUG_PACKET)
    2659           0 :                         zlog_debug(
    2660             :                                 "Not notifying pathd about policy %s"
    2661             :                                 " status change to %d",
    2662             :                                 name, status);
    2663           0 :                 return 0;
    2664             :         }
    2665             : 
    2666           0 :         if (IS_ZEBRA_DEBUG_PACKET)
    2667           0 :                 zlog_debug(
    2668             :                         "Notifying pathd about policy %s status change"
    2669             :                         " to %d",
    2670             :                         name, status);
    2671             : 
    2672           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2673           0 :         stream_reset(s);
    2674             : 
    2675           0 :         zclient_create_header(s, ZEBRA_SR_POLICY_NOTIFY_STATUS, VRF_DEFAULT);
    2676           0 :         stream_putl(s, color);
    2677           0 :         stream_put_ipaddr(s, endpoint);
    2678           0 :         stream_write(s, name, SRTE_POLICY_NAME_MAX_LENGTH);
    2679           0 :         stream_putl(s, status);
    2680             : 
    2681           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2682             : 
    2683           0 :         return zserv_send_message(client, s);
    2684             : }
    2685             : 
    2686             : /* Send client close notify to client */
    2687          12 : int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client)
    2688             : {
    2689          12 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2690             : 
    2691          12 :         zclient_create_header(s, ZEBRA_CLIENT_CLOSE_NOTIFY, VRF_DEFAULT);
    2692             : 
    2693          12 :         stream_putc(s, closed_client->proto);
    2694          12 :         stream_putw(s, closed_client->instance);
    2695          12 :         stream_putl(s, closed_client->session_id);
    2696             : 
    2697          12 :         stream_putw_at(s, 0, stream_get_endp(s));
    2698             : 
    2699          12 :         return zserv_send_message(client, s);
    2700             : }
    2701             : 
    2702           0 : int zsend_srv6_manager_get_locator_chunk_response(struct zserv *client,
    2703             :                                                   vrf_id_t vrf_id,
    2704             :                                                   struct srv6_locator *loc)
    2705             : {
    2706           0 :         struct srv6_locator_chunk chunk = {};
    2707           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2708             : 
    2709           0 :         strlcpy(chunk.locator_name, loc->name, sizeof(chunk.locator_name));
    2710           0 :         chunk.prefix = loc->prefix;
    2711           0 :         chunk.block_bits_length = loc->block_bits_length;
    2712           0 :         chunk.node_bits_length = loc->node_bits_length;
    2713           0 :         chunk.function_bits_length = loc->function_bits_length;
    2714           0 :         chunk.argument_bits_length = loc->argument_bits_length;
    2715           0 :         chunk.keep = 0;
    2716           0 :         chunk.proto = client->proto;
    2717           0 :         chunk.instance = client->instance;
    2718           0 :         chunk.flags = loc->flags;
    2719             : 
    2720           0 :         zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK, vrf_id);
    2721           0 :         zapi_srv6_locator_chunk_encode(s, &chunk);
    2722           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2723           0 :         return zserv_send_message(client, s);
    2724             : }
    2725             : 
    2726             : /* Send response to a table manager connect request to client */
    2727           0 : static void zread_table_manager_connect(struct zserv *client,
    2728             :                                         struct stream *msg, vrf_id_t vrf_id)
    2729             : {
    2730           0 :         struct stream *s;
    2731           0 :         uint8_t proto;
    2732           0 :         uint16_t instance;
    2733           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
    2734             : 
    2735           0 :         s = msg;
    2736             : 
    2737             :         /* Get data. */
    2738           0 :         STREAM_GETC(s, proto);
    2739           0 :         STREAM_GETW(s, instance);
    2740             : 
    2741             :         /* accept only dynamic routing protocols */
    2742           0 :         if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
    2743           0 :                 flog_err(EC_ZEBRA_TM_WRONG_PROTO,
    2744             :                          "client %d has wrong protocol %s", client->sock,
    2745             :                          zebra_route_string(proto));
    2746           0 :                 zsend_table_manager_connect_response(client, vrf_id, 1);
    2747           0 :                 return;
    2748             :         }
    2749           0 :         zlog_notice("client %d with vrf %s(%u) instance %u connected as %s",
    2750             :                     client->sock, VRF_LOGNAME(vrf), vrf_id, instance,
    2751             :                     zebra_route_string(proto));
    2752           0 :         client->proto = proto;
    2753           0 :         client->instance = instance;
    2754             : 
    2755             :         /*
    2756             :          * Release previous labels of same protocol and instance.
    2757             :          * This is done in case it restarted from an unexpected shutdown.
    2758             :          */
    2759           0 :         release_daemon_table_chunks(client);
    2760             : 
    2761           0 :         zsend_table_manager_connect_response(client, vrf_id, 0);
    2762             : 
    2763           0 : stream_failure:
    2764             :         return;
    2765             : }
    2766             : 
    2767           0 : static void zread_label_manager_connect(struct zserv *client,
    2768             :                                         struct stream *msg, vrf_id_t vrf_id)
    2769             : {
    2770           0 :         struct stream *s;
    2771             :         /* type of protocol (lib/zebra.h) */
    2772           0 :         uint8_t proto;
    2773           0 :         unsigned short instance;
    2774             : 
    2775             :         /* Get input stream.  */
    2776           0 :         s = msg;
    2777             : 
    2778             :         /* Get data. */
    2779           0 :         STREAM_GETC(s, proto);
    2780           0 :         STREAM_GETW(s, instance);
    2781             : 
    2782             :         /* accept only dynamic routing protocols */
    2783           0 :         if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
    2784           0 :                 flog_err(EC_ZEBRA_TM_WRONG_PROTO,
    2785             :                          "client %d has wrong protocol %s", client->sock,
    2786             :                          zebra_route_string(proto));
    2787           0 :                 zsend_label_manager_connect_response(client, vrf_id, 1);
    2788           0 :                 return;
    2789             :         }
    2790             : 
    2791             :         /* recall proto and instance in this socket */
    2792           0 :         client->proto = proto;
    2793           0 :         client->instance = instance;
    2794             : 
    2795             :         /* call hook for connection using wrapper */
    2796           0 :         lm_client_connect_call(client, vrf_id);
    2797             : 
    2798           0 : stream_failure:
    2799             :         return;
    2800             : }
    2801             : 
    2802           0 : static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
    2803             :                                   vrf_id_t vrf_id)
    2804             : {
    2805           0 :         struct stream *s;
    2806           0 :         uint8_t keep;
    2807           0 :         uint32_t size, base;
    2808           0 :         struct label_manager_chunk *lmc = NULL;
    2809           0 :         uint8_t proto;
    2810           0 :         unsigned short instance;
    2811             : 
    2812             :         /* Get input stream.  */
    2813           0 :         s = msg;
    2814             : 
    2815             :         /* Get data. */
    2816           0 :         STREAM_GETC(s, proto);
    2817           0 :         STREAM_GETW(s, instance);
    2818           0 :         STREAM_GETC(s, keep);
    2819           0 :         STREAM_GETL(s, size);
    2820           0 :         STREAM_GETL(s, base);
    2821             : 
    2822           0 :         assert(proto == client->proto && instance == client->instance);
    2823             : 
    2824             :         /* call hook to get a chunk using wrapper */
    2825           0 :         lm_get_chunk_call(&lmc, client, keep, size, base, vrf_id);
    2826             : 
    2827           0 : stream_failure:
    2828           0 :         return;
    2829             : }
    2830             : 
    2831           0 : static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
    2832             : {
    2833           0 :         struct stream *s;
    2834           0 :         uint32_t start, end;
    2835           0 :         uint8_t proto;
    2836           0 :         unsigned short instance;
    2837             : 
    2838             :         /* Get input stream.  */
    2839           0 :         s = msg;
    2840             : 
    2841             :         /* Get data. */
    2842           0 :         STREAM_GETC(s, proto);
    2843           0 :         STREAM_GETW(s, instance);
    2844           0 :         STREAM_GETL(s, start);
    2845           0 :         STREAM_GETL(s, end);
    2846             : 
    2847           0 :         assert(proto == client->proto && instance == client->instance);
    2848             : 
    2849             :         /* call hook to release a chunk using wrapper */
    2850           0 :         lm_release_chunk_call(client, start, end);
    2851             : 
    2852           0 : stream_failure:
    2853           0 :         return;
    2854             : }
    2855             : 
    2856           0 : static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
    2857             : {
    2858           0 :         if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT
    2859           0 :             || hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC)
    2860           0 :                 zread_label_manager_connect(client, msg, zvrf_id(zvrf));
    2861             :         else {
    2862           0 :                 if (hdr->command == ZEBRA_GET_LABEL_CHUNK)
    2863           0 :                         zread_get_label_chunk(client, msg, zvrf_id(zvrf));
    2864           0 :                 else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK)
    2865           0 :                         zread_release_label_chunk(client, msg);
    2866             :         }
    2867           0 : }
    2868             : 
    2869           0 : static void zread_get_table_chunk(struct zserv *client, struct stream *msg,
    2870             :                                   struct zebra_vrf *zvrf)
    2871             : {
    2872           0 :         struct stream *s;
    2873           0 :         uint32_t size;
    2874           0 :         struct table_manager_chunk *tmc;
    2875             : 
    2876             :         /* Get input stream.  */
    2877           0 :         s = msg;
    2878             : 
    2879             :         /* Get data. */
    2880           0 :         STREAM_GETL(s, size);
    2881             : 
    2882           0 :         tmc = assign_table_chunk(client->proto, client->instance, size, zvrf);
    2883           0 :         if (!tmc)
    2884           0 :                 flog_err(EC_ZEBRA_TM_CANNOT_ASSIGN_CHUNK,
    2885             :                          "%s: Unable to assign Table Chunk of size %u",
    2886             :                          __func__, size);
    2887             :         else
    2888           0 :                 zlog_debug("Assigned Table Chunk %u - %u", tmc->start,
    2889             :                            tmc->end);
    2890             :         /* send response back */
    2891           0 :         zsend_assign_table_chunk_response(client, zvrf_id(zvrf), tmc);
    2892             : 
    2893           0 : stream_failure:
    2894           0 :         return;
    2895             : }
    2896             : 
    2897           0 : static void zread_release_table_chunk(struct zserv *client, struct stream *msg,
    2898             :                                       struct zebra_vrf *zvrf)
    2899             : {
    2900           0 :         struct stream *s;
    2901           0 :         uint32_t start, end;
    2902             : 
    2903             :         /* Get input stream.  */
    2904           0 :         s = msg;
    2905             : 
    2906             :         /* Get data. */
    2907           0 :         STREAM_GETL(s, start);
    2908           0 :         STREAM_GETL(s, end);
    2909             : 
    2910           0 :         release_table_chunk(client->proto, client->instance, start, end, zvrf);
    2911             : 
    2912           0 : stream_failure:
    2913           0 :         return;
    2914             : }
    2915             : 
    2916           0 : static void zread_table_manager_request(ZAPI_HANDLER_ARGS)
    2917             : {
    2918             :         /* to avoid sending other messages like ZEBRA_INTERFACE_UP */
    2919           0 :         if (hdr->command == ZEBRA_TABLE_MANAGER_CONNECT)
    2920           0 :                 zread_table_manager_connect(client, msg, zvrf_id(zvrf));
    2921             :         else {
    2922             :                 /* Sanity: don't allow 'unidentified' requests */
    2923           0 :                 if (!client->proto) {
    2924           0 :                         flog_err(
    2925             :                                 EC_ZEBRA_TM_ALIENS,
    2926             :                                 "Got SRv6 request from an unidentified client");
    2927           0 :                         return;
    2928             :                 }
    2929           0 :                 if (hdr->command == ZEBRA_GET_TABLE_CHUNK)
    2930           0 :                         zread_get_table_chunk(client, msg, zvrf);
    2931           0 :                 else if (hdr->command == ZEBRA_RELEASE_TABLE_CHUNK)
    2932           0 :                         zread_release_table_chunk(client, msg, zvrf);
    2933             :         }
    2934             : }
    2935             : 
    2936           0 : static void zread_srv6_manager_get_locator_chunk(struct zserv *client,
    2937             :                                                  struct stream *msg,
    2938             :                                                  vrf_id_t vrf_id)
    2939             : {
    2940           0 :         struct stream *s = msg;
    2941           0 :         uint16_t len;
    2942           0 :         char locator_name[SRV6_LOCNAME_SIZE] = {0};
    2943             : 
    2944             :         /* Get data. */
    2945           0 :         STREAM_GETW(s, len);
    2946           0 :         STREAM_GET(locator_name, s, len);
    2947             : 
    2948             :         /* call hook to get a chunk using wrapper */
    2949           0 :         struct srv6_locator *loc = NULL;
    2950           0 :         srv6_manager_get_locator_chunk_call(&loc, client, locator_name, vrf_id);
    2951             : 
    2952           0 : stream_failure:
    2953           0 :         return;
    2954             : }
    2955             : 
    2956           0 : static void zread_srv6_manager_release_locator_chunk(struct zserv *client,
    2957             :                                                      struct stream *msg,
    2958             :                                                      vrf_id_t vrf_id)
    2959             : {
    2960           0 :         struct stream *s = msg;
    2961           0 :         uint16_t len;
    2962           0 :         char locator_name[SRV6_LOCNAME_SIZE] = {0};
    2963             : 
    2964             :         /* Get data. */
    2965           0 :         STREAM_GETW(s, len);
    2966           0 :         STREAM_GET(locator_name, s, len);
    2967             : 
    2968             :         /* call hook to release a chunk using wrapper */
    2969           0 :         srv6_manager_release_locator_chunk_call(client, locator_name, vrf_id);
    2970             : 
    2971           0 : stream_failure:
    2972           0 :         return;
    2973             : }
    2974             : 
    2975           0 : static void zread_srv6_manager_request(ZAPI_HANDLER_ARGS)
    2976             : {
    2977           0 :         switch (hdr->command) {
    2978             :         case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
    2979           0 :                 zread_srv6_manager_get_locator_chunk(client, msg,
    2980             :                                                      zvrf_id(zvrf));
    2981           0 :                 break;
    2982             :         case ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK:
    2983           0 :                 zread_srv6_manager_release_locator_chunk(client, msg,
    2984             :                                                          zvrf_id(zvrf));
    2985           0 :                 break;
    2986           0 :         default:
    2987           0 :                 zlog_err("%s: unknown SRv6 Manager command", __func__);
    2988           0 :                 break;
    2989             :         }
    2990           0 : }
    2991             : 
    2992           0 : static void zread_pseudowire(ZAPI_HANDLER_ARGS)
    2993             : {
    2994           0 :         struct stream *s;
    2995           0 :         char ifname[INTERFACE_NAMSIZ];
    2996           0 :         ifindex_t ifindex;
    2997           0 :         int type;
    2998           0 :         int af;
    2999           0 :         union g_addr nexthop;
    3000           0 :         uint32_t local_label;
    3001           0 :         uint32_t remote_label;
    3002           0 :         uint8_t flags;
    3003           0 :         union pw_protocol_fields data;
    3004           0 :         uint8_t protocol;
    3005           0 :         struct zebra_pw *pw;
    3006             : 
    3007             :         /* Get input stream.  */
    3008           0 :         s = msg;
    3009             : 
    3010             :         /* Get data. */
    3011           0 :         STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
    3012           0 :         ifname[INTERFACE_NAMSIZ - 1] = '\0';
    3013           0 :         STREAM_GETL(s, ifindex);
    3014           0 :         STREAM_GETL(s, type);
    3015           0 :         STREAM_GETL(s, af);
    3016           0 :         switch (af) {
    3017           0 :         case AF_INET:
    3018           0 :                 STREAM_GET(&nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
    3019             :                 break;
    3020           0 :         case AF_INET6:
    3021           0 :                 STREAM_GET(&nexthop.ipv6, s, 16);
    3022             :                 break;
    3023             :         default:
    3024             :                 return;
    3025             :         }
    3026           0 :         STREAM_GETL(s, local_label);
    3027           0 :         STREAM_GETL(s, remote_label);
    3028           0 :         STREAM_GETC(s, flags);
    3029           0 :         STREAM_GET(&data, s, sizeof(data));
    3030           0 :         protocol = client->proto;
    3031             : 
    3032           0 :         pw = zebra_pw_find(zvrf, ifname);
    3033           0 :         switch (hdr->command) {
    3034           0 :         case ZEBRA_PW_ADD:
    3035           0 :                 if (pw) {
    3036           0 :                         flog_warn(EC_ZEBRA_PSEUDOWIRE_EXISTS,
    3037             :                                   "%s: pseudowire %s already exists [%s]",
    3038             :                                   __func__, ifname,
    3039             :                                   zserv_command_string(hdr->command));
    3040           0 :                         return;
    3041             :                 }
    3042             : 
    3043           0 :                 zebra_pw_add(zvrf, ifname, protocol, client);
    3044           0 :                 break;
    3045           0 :         case ZEBRA_PW_DELETE:
    3046           0 :                 if (!pw) {
    3047           0 :                         flog_warn(EC_ZEBRA_PSEUDOWIRE_NONEXISTENT,
    3048             :                                   "%s: pseudowire %s not found [%s]", __func__,
    3049             :                                   ifname, zserv_command_string(hdr->command));
    3050           0 :                         return;
    3051             :                 }
    3052             : 
    3053           0 :                 zebra_pw_del(zvrf, pw);
    3054           0 :                 break;
    3055           0 :         case ZEBRA_PW_SET:
    3056             :         case ZEBRA_PW_UNSET:
    3057           0 :                 if (!pw) {
    3058           0 :                         flog_warn(EC_ZEBRA_PSEUDOWIRE_NONEXISTENT,
    3059             :                                   "%s: pseudowire %s not found [%s]", __func__,
    3060             :                                   ifname, zserv_command_string(hdr->command));
    3061           0 :                         return;
    3062             :                 }
    3063             : 
    3064           0 :                 switch (hdr->command) {
    3065           0 :                 case ZEBRA_PW_SET:
    3066           0 :                         pw->enabled = 1;
    3067           0 :                         break;
    3068           0 :                 case ZEBRA_PW_UNSET:
    3069           0 :                         pw->enabled = 0;
    3070           0 :                         break;
    3071             :                 }
    3072             : 
    3073           0 :                 zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label,
    3074             :                                 remote_label, flags, &data);
    3075           0 :                 break;
    3076             :         }
    3077             : 
    3078           0 : stream_failure:
    3079             :         return;
    3080             : }
    3081             : 
    3082           0 : static void zread_interface_set_master(ZAPI_HANDLER_ARGS)
    3083             : {
    3084           0 :         struct interface *master;
    3085           0 :         struct interface *slave;
    3086           0 :         struct stream *s = msg;
    3087           0 :         int ifindex;
    3088           0 :         vrf_id_t vrf_id;
    3089             : 
    3090           0 :         STREAM_GETL(s, vrf_id);
    3091           0 :         STREAM_GETL(s, ifindex);
    3092           0 :         master = if_lookup_by_index(ifindex, vrf_id);
    3093             : 
    3094           0 :         STREAM_GETL(s, vrf_id);
    3095           0 :         STREAM_GETL(s, ifindex);
    3096           0 :         slave = if_lookup_by_index(ifindex, vrf_id);
    3097             : 
    3098           0 :         if (!master || !slave)
    3099             :                 return;
    3100             : 
    3101           0 :         kernel_interface_set_master(master, slave);
    3102             : 
    3103           0 : stream_failure:
    3104             :         return;
    3105             : }
    3106             : 
    3107             : 
    3108           0 : static void zread_vrf_label(ZAPI_HANDLER_ARGS)
    3109             : {
    3110           0 :         struct interface *ifp;
    3111           0 :         mpls_label_t nlabel;
    3112           0 :         afi_t afi;
    3113           0 :         struct stream *s;
    3114           0 :         struct zebra_vrf *def_zvrf;
    3115           0 :         enum lsp_types_t ltype;
    3116             : 
    3117           0 :         s = msg;
    3118           0 :         STREAM_GETL(s, nlabel);
    3119           0 :         STREAM_GETC(s, afi);
    3120             : 
    3121           0 :         if (!(IS_VALID_AFI(afi))) {
    3122           0 :                 zlog_warn("Invalid AFI for VRF label: %u", afi);
    3123           0 :                 return;
    3124             :         }
    3125             : 
    3126           0 :         if (nlabel == zvrf->label[afi]) {
    3127             :                 /*
    3128             :                  * Nothing to do here move along
    3129             :                  */
    3130             :                 return;
    3131             :         }
    3132             : 
    3133           0 :         STREAM_GETC(s, ltype);
    3134             : 
    3135           0 :         if (zvrf->vrf->vrf_id != VRF_DEFAULT)
    3136           0 :                 ifp = if_lookup_by_name(zvrf->vrf->name, zvrf->vrf->vrf_id);
    3137             :         else
    3138           0 :                 ifp = if_lookup_by_name("lo", VRF_DEFAULT);
    3139             : 
    3140           0 :         if (!ifp) {
    3141           0 :                 zlog_debug("Unable to find specified Interface for %s",
    3142             :                            zvrf->vrf->name);
    3143           0 :                 return;
    3144             :         }
    3145             : 
    3146           0 :         def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
    3147             : 
    3148           0 :         if (zvrf->label[afi] != MPLS_LABEL_NONE) {
    3149             :                 afi_t scrubber;
    3150             :                 bool really_remove;
    3151             : 
    3152           0 :                 really_remove = true;
    3153           0 :                 for (scrubber = AFI_IP; scrubber < AFI_MAX; scrubber++) {
    3154           0 :                         if (scrubber == afi)
    3155           0 :                                 continue;
    3156             : 
    3157           0 :                         if (zvrf->label[scrubber] == MPLS_LABEL_NONE)
    3158           0 :                                 continue;
    3159             : 
    3160           0 :                         if (zvrf->label[afi] == zvrf->label[scrubber]) {
    3161             :                                 really_remove = false;
    3162             :                                 break;
    3163             :                         }
    3164             :                 }
    3165             : 
    3166           0 :                 if (really_remove)
    3167           0 :                         mpls_lsp_uninstall(def_zvrf, ltype, zvrf->label[afi],
    3168             :                                            NEXTHOP_TYPE_IFINDEX, NULL,
    3169             :                                            ifp->ifindex, false /*backup*/);
    3170             :         }
    3171             : 
    3172           0 :         if (nlabel != MPLS_LABEL_NONE) {
    3173           0 :                 mpls_label_t out_label = MPLS_LABEL_IMPLICIT_NULL;
    3174           0 :                 mpls_lsp_install(def_zvrf, ltype, nlabel, 1, &out_label,
    3175             :                                  NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex);
    3176             :         }
    3177             : 
    3178           0 :         zvrf->label[afi] = nlabel;
    3179           0 :         zvrf->label_proto[afi] = client->proto;
    3180             : 
    3181           0 : stream_failure:
    3182             :         return;
    3183             : }
    3184             : 
    3185           0 : static inline void zread_rule(ZAPI_HANDLER_ARGS)
    3186             : {
    3187           0 :         struct zebra_pbr_rule zpr;
    3188           0 :         struct stream *s;
    3189           0 :         uint32_t total, i;
    3190           0 :         char ifname[INTERFACE_NAMSIZ + 1] = {};
    3191             : 
    3192           0 :         s = msg;
    3193           0 :         STREAM_GETL(s, total);
    3194             : 
    3195           0 :         for (i = 0; i < total; i++) {
    3196           0 :                 memset(&zpr, 0, sizeof(zpr));
    3197             : 
    3198           0 :                 zpr.sock = client->sock;
    3199           0 :                 zpr.rule.vrf_id = hdr->vrf_id;
    3200           0 :                 STREAM_GETL(s, zpr.rule.seq);
    3201           0 :                 STREAM_GETL(s, zpr.rule.priority);
    3202           0 :                 STREAM_GETL(s, zpr.rule.unique);
    3203           0 :                 STREAM_GETC(s, zpr.rule.filter.ip_proto);
    3204           0 :                 STREAM_GETC(s, zpr.rule.filter.src_ip.family);
    3205           0 :                 STREAM_GETC(s, zpr.rule.filter.src_ip.prefixlen);
    3206           0 :                 STREAM_GET(&zpr.rule.filter.src_ip.u.prefix, s,
    3207             :                            prefix_blen(&zpr.rule.filter.src_ip));
    3208           0 :                 STREAM_GETW(s, zpr.rule.filter.src_port);
    3209           0 :                 STREAM_GETC(s, zpr.rule.filter.dst_ip.family);
    3210           0 :                 STREAM_GETC(s, zpr.rule.filter.dst_ip.prefixlen);
    3211           0 :                 STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s,
    3212             :                            prefix_blen(&zpr.rule.filter.dst_ip));
    3213           0 :                 STREAM_GETW(s, zpr.rule.filter.dst_port);
    3214           0 :                 STREAM_GETC(s, zpr.rule.filter.dsfield);
    3215           0 :                 STREAM_GETL(s, zpr.rule.filter.fwmark);
    3216             : 
    3217           0 :                 STREAM_GETL(s, zpr.rule.action.queue_id);
    3218           0 :                 STREAM_GETW(s, zpr.rule.action.vlan_id);
    3219           0 :                 STREAM_GETW(s, zpr.rule.action.vlan_flags);
    3220           0 :                 STREAM_GETW(s, zpr.rule.action.pcp);
    3221             : 
    3222           0 :                 STREAM_GETL(s, zpr.rule.action.table);
    3223           0 :                 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
    3224             : 
    3225           0 :                 strlcpy(zpr.ifname, ifname, sizeof(zpr.ifname));
    3226           0 :                 strlcpy(zpr.rule.ifname, ifname, sizeof(zpr.rule.ifname));
    3227             : 
    3228           0 :                 if (!is_default_prefix(&zpr.rule.filter.src_ip))
    3229           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
    3230             : 
    3231           0 :                 if (!is_default_prefix(&zpr.rule.filter.dst_ip))
    3232           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
    3233             : 
    3234           0 :                 if (zpr.rule.filter.src_port)
    3235           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_PORT;
    3236             : 
    3237           0 :                 if (zpr.rule.filter.dst_port)
    3238           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT;
    3239             : 
    3240           0 :                 if (zpr.rule.filter.dsfield)
    3241           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD;
    3242             : 
    3243           0 :                 if (zpr.rule.filter.ip_proto)
    3244           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_IP_PROTOCOL;
    3245             : 
    3246           0 :                 if (zpr.rule.filter.fwmark)
    3247           0 :                         zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK;
    3248             : 
    3249           0 :                 if (!(zpr.rule.filter.src_ip.family == AF_INET
    3250             :                       || zpr.rule.filter.src_ip.family == AF_INET6)) {
    3251           0 :                         zlog_warn(
    3252             :                                 "Unsupported PBR source IP family: %s (%hhu)",
    3253             :                                 family2str(zpr.rule.filter.src_ip.family),
    3254             :                                 zpr.rule.filter.src_ip.family);
    3255           0 :                         return;
    3256             :                 }
    3257           0 :                 if (!(zpr.rule.filter.dst_ip.family == AF_INET
    3258             :                       || zpr.rule.filter.dst_ip.family == AF_INET6)) {
    3259           0 :                         zlog_warn(
    3260             :                                 "Unsupported PBR destination IP family: %s (%hhu)",
    3261             :                                 family2str(zpr.rule.filter.dst_ip.family),
    3262             :                                 zpr.rule.filter.dst_ip.family);
    3263           0 :                         return;
    3264             :                 }
    3265             : 
    3266             : 
    3267           0 :                 zpr.vrf_id = zvrf->vrf->vrf_id;
    3268           0 :                 if (hdr->command == ZEBRA_RULE_ADD)
    3269           0 :                         zebra_pbr_add_rule(&zpr);
    3270             :                 else
    3271           0 :                         zebra_pbr_del_rule(&zpr);
    3272             :         }
    3273             : 
    3274           0 : stream_failure:
    3275             :         return;
    3276             : }
    3277             : 
    3278           0 : static inline void zread_tc_qdisc(ZAPI_HANDLER_ARGS)
    3279             : {
    3280           0 :         struct zebra_tc_qdisc qdisc;
    3281           0 :         struct stream *s;
    3282           0 :         uint32_t total, i;
    3283             : 
    3284           0 :         s = msg;
    3285           0 :         STREAM_GETL(s, total);
    3286             : 
    3287           0 :         for (i = 0; i < total; i++) {
    3288           0 :                 memset(&qdisc, 0, sizeof(qdisc));
    3289             : 
    3290           0 :                 qdisc.sock = client->sock;
    3291           0 :                 STREAM_GETL(s, qdisc.qdisc.ifindex);
    3292           0 :                 STREAM_GETL(s, qdisc.qdisc.kind);
    3293             : 
    3294           0 :                 if (hdr->command == ZEBRA_TC_QDISC_INSTALL)
    3295           0 :                         zebra_tc_qdisc_install(&qdisc);
    3296             :                 else
    3297           0 :                         zebra_tc_qdisc_uninstall(&qdisc);
    3298             :         }
    3299             : 
    3300           0 : stream_failure:
    3301           0 :         return;
    3302             : }
    3303             : 
    3304           0 : static inline void zread_tc_class(ZAPI_HANDLER_ARGS)
    3305             : {
    3306           0 :         struct zebra_tc_class class;
    3307           0 :         struct stream *s;
    3308           0 :         uint32_t total, i;
    3309             : 
    3310           0 :         s = msg;
    3311           0 :         STREAM_GETL(s, total);
    3312             : 
    3313           0 :         for (i = 0; i < total; i++) {
    3314           0 :                 memset(&class, 0, sizeof(class));
    3315             : 
    3316           0 :                 class.sock = client->sock;
    3317           0 :                 STREAM_GETL(s, class.class.ifindex);
    3318           0 :                 STREAM_GETL(s, class.class.handle);
    3319           0 :                 STREAM_GETL(s, class.class.kind);
    3320           0 :                 STREAM_GETQ(s, class.class.u.htb.rate);
    3321           0 :                 STREAM_GETQ(s, class.class.u.htb.ceil);
    3322             : 
    3323           0 :                 if (hdr->command == ZEBRA_TC_CLASS_ADD)
    3324           0 :                         zebra_tc_class_add(&class);
    3325             :                 else
    3326           0 :                         zebra_tc_class_delete(&class);
    3327             :         }
    3328             : 
    3329           0 : stream_failure:
    3330           0 :         return;
    3331             : }
    3332             : 
    3333           0 : static inline void zread_tc_filter(ZAPI_HANDLER_ARGS)
    3334             : {
    3335           0 :         struct zebra_tc_filter filter;
    3336           0 :         struct stream *s;
    3337           0 :         uint32_t total, i;
    3338             : 
    3339           0 :         s = msg;
    3340           0 :         STREAM_GETL(s, total);
    3341             : 
    3342           0 :         for (i = 0; i < total; i++) {
    3343           0 :                 memset(&filter, 0, sizeof(filter));
    3344             : 
    3345           0 :                 filter.sock = client->sock;
    3346           0 :                 STREAM_GETL(s, filter.filter.ifindex);
    3347           0 :                 STREAM_GETL(s, filter.filter.handle);
    3348           0 :                 STREAM_GETL(s, filter.filter.priority);
    3349           0 :                 STREAM_GETL(s, filter.filter.protocol);
    3350           0 :                 STREAM_GETL(s, filter.filter.kind);
    3351           0 :                 switch (filter.filter.kind) {
    3352           0 :                 case TC_FILTER_FLOWER: {
    3353           0 :                         STREAM_GETL(s, filter.filter.u.flower.filter_bm);
    3354           0 :                         uint32_t filter_bm = filter.filter.u.flower.filter_bm;
    3355             : 
    3356           0 :                         if (filter_bm & TC_FLOWER_IP_PROTOCOL)
    3357           0 :                                 STREAM_GETC(s, filter.filter.u.flower.ip_proto);
    3358           0 :                         if (filter_bm & TC_FLOWER_SRC_IP) {
    3359           0 :                                 STREAM_GETC(
    3360             :                                         s,
    3361             :                                         filter.filter.u.flower.src_ip.family);
    3362           0 :                                 STREAM_GETC(s, filter.filter.u.flower.src_ip
    3363             :                                                        .prefixlen);
    3364           0 :                                 STREAM_GET(
    3365             :                                         &filter.filter.u.flower.src_ip.u.prefix,
    3366             :                                         s,
    3367             :                                         prefix_blen(&filter.filter.u.flower
    3368             :                                                              .src_ip));
    3369             : 
    3370           0 :                                 if (!(filter.filter.u.flower.src_ip.family ==
    3371             :                                               AF_INET ||
    3372             :                                       filter.filter.u.flower.src_ip.family ==
    3373             :                                               AF_INET6)) {
    3374           0 :                                         zlog_warn(
    3375             :                                                 "Unsupported TC source IP family: %s (%hhu)",
    3376             :                                                 family2str(
    3377             :                                                         filter.filter.u.flower
    3378             :                                                                 .src_ip.family),
    3379             :                                                 filter.filter.u.flower.src_ip
    3380             :                                                         .family);
    3381           0 :                                         return;
    3382             :                                 }
    3383             :                         }
    3384           0 :                         if (filter_bm & TC_FLOWER_SRC_PORT) {
    3385           0 :                                 STREAM_GETW(
    3386             :                                         s, filter.filter.u.flower.src_port_min);
    3387           0 :                                 STREAM_GETW(
    3388             :                                         s, filter.filter.u.flower.src_port_max);
    3389             :                         }
    3390           0 :                         if (filter_bm & TC_FLOWER_DST_IP) {
    3391           0 :                                 STREAM_GETC(
    3392             :                                         s,
    3393             :                                         filter.filter.u.flower.dst_ip.family);
    3394           0 :                                 STREAM_GETC(s, filter.filter.u.flower.dst_ip
    3395             :                                                        .prefixlen);
    3396           0 :                                 STREAM_GET(
    3397             :                                         &filter.filter.u.flower.dst_ip.u.prefix,
    3398             :                                         s,
    3399             :                                         prefix_blen(&filter.filter.u.flower
    3400             :                                                              .dst_ip));
    3401           0 :                                 if (!(filter.filter.u.flower.dst_ip.family ==
    3402             :                                               AF_INET ||
    3403             :                                       filter.filter.u.flower.dst_ip.family ==
    3404             :                                               AF_INET6)) {
    3405           0 :                                         zlog_warn(
    3406             :                                                 "Unsupported TC destination IP family: %s (%hhu)",
    3407             :                                                 family2str(
    3408             :                                                         filter.filter.u.flower
    3409             :                                                                 .dst_ip.family),
    3410             :                                                 filter.filter.u.flower.dst_ip
    3411             :                                                         .family);
    3412           0 :                                         return;
    3413             :                                 }
    3414             :                         }
    3415           0 :                         if (filter_bm & TC_FLOWER_DST_PORT) {
    3416           0 :                                 STREAM_GETW(
    3417             :                                         s, filter.filter.u.flower.dst_port_min);
    3418           0 :                                 STREAM_GETW(
    3419             :                                         s, filter.filter.u.flower.dst_port_max);
    3420             :                         }
    3421           0 :                         if (filter_bm & TC_FLOWER_DSFIELD) {
    3422           0 :                                 STREAM_GETC(s, filter.filter.u.flower.dsfield);
    3423           0 :                                 STREAM_GETC(
    3424             :                                         s, filter.filter.u.flower.dsfield_mask);
    3425             :                         }
    3426           0 :                         STREAM_GETL(s, filter.filter.u.flower.classid);
    3427           0 :                         break;
    3428             :                 }
    3429             :                 case TC_FILTER_BPF:
    3430             :                 case TC_FILTER_FLOW:
    3431             :                 case TC_FILTER_U32:
    3432             :                 case TC_FILTER_UNSPEC:
    3433             :                         break;
    3434             :                 }
    3435             : 
    3436           0 :                 if (hdr->command == ZEBRA_TC_FILTER_ADD)
    3437           0 :                         zebra_tc_filter_add(&filter);
    3438             :                 else
    3439           0 :                         zebra_tc_filter_delete(&filter);
    3440             :         }
    3441             : 
    3442           0 : stream_failure:
    3443             :         return;
    3444             : }
    3445             : 
    3446           0 : static inline void zread_ipset(ZAPI_HANDLER_ARGS)
    3447             : {
    3448           0 :         struct zebra_pbr_ipset zpi;
    3449           0 :         struct stream *s;
    3450           0 :         uint32_t total, i;
    3451             : 
    3452           0 :         s = msg;
    3453           0 :         STREAM_GETL(s, total);
    3454             : 
    3455           0 :         for (i = 0; i < total; i++) {
    3456           0 :                 memset(&zpi, 0, sizeof(zpi));
    3457             : 
    3458           0 :                 zpi.sock = client->sock;
    3459           0 :                 zpi.vrf_id = zvrf->vrf->vrf_id;
    3460           0 :                 STREAM_GETL(s, zpi.unique);
    3461           0 :                 STREAM_GETL(s, zpi.type);
    3462           0 :                 STREAM_GETC(s, zpi.family);
    3463           0 :                 STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
    3464             : 
    3465           0 :                 if (hdr->command == ZEBRA_IPSET_CREATE)
    3466           0 :                         zebra_pbr_create_ipset(&zpi);
    3467             :                 else
    3468           0 :                         zebra_pbr_destroy_ipset(&zpi);
    3469             :         }
    3470             : 
    3471           0 : stream_failure:
    3472           0 :         return;
    3473             : }
    3474             : 
    3475           0 : static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
    3476             : {
    3477           0 :         struct zebra_pbr_ipset_entry zpi;
    3478           0 :         struct zebra_pbr_ipset ipset;
    3479           0 :         struct stream *s;
    3480           0 :         uint32_t total, i;
    3481             : 
    3482           0 :         s = msg;
    3483           0 :         STREAM_GETL(s, total);
    3484             : 
    3485           0 :         for (i = 0; i < total; i++) {
    3486           0 :                 memset(&zpi, 0, sizeof(zpi));
    3487           0 :                 memset(&ipset, 0, sizeof(ipset));
    3488             : 
    3489           0 :                 zpi.sock = client->sock;
    3490           0 :                 STREAM_GETL(s, zpi.unique);
    3491           0 :                 STREAM_GET(&ipset.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
    3492           0 :                 ipset.ipset_name[ZEBRA_IPSET_NAME_SIZE - 1] = '\0';
    3493           0 :                 STREAM_GETC(s, zpi.src.family);
    3494           0 :                 STREAM_GETC(s, zpi.src.prefixlen);
    3495           0 :                 STREAM_GET(&zpi.src.u.prefix, s, prefix_blen(&zpi.src));
    3496           0 :                 STREAM_GETC(s, zpi.dst.family);
    3497           0 :                 STREAM_GETC(s, zpi.dst.prefixlen);
    3498           0 :                 STREAM_GET(&zpi.dst.u.prefix, s, prefix_blen(&zpi.dst));
    3499             : 
    3500           0 :                 STREAM_GETW(s, zpi.src_port_min);
    3501           0 :                 STREAM_GETW(s, zpi.src_port_max);
    3502           0 :                 STREAM_GETW(s, zpi.dst_port_min);
    3503           0 :                 STREAM_GETW(s, zpi.dst_port_max);
    3504           0 :                 STREAM_GETC(s, zpi.proto);
    3505           0 :                 if (!is_default_prefix(&zpi.src))
    3506           0 :                         zpi.filter_bm |= PBR_FILTER_SRC_IP;
    3507             : 
    3508           0 :                 if (!is_default_prefix(&zpi.dst))
    3509           0 :                         zpi.filter_bm |= PBR_FILTER_DST_IP;
    3510           0 :                 if (zpi.dst_port_min != 0 || zpi.proto == IPPROTO_ICMP)
    3511           0 :                         zpi.filter_bm |= PBR_FILTER_DST_PORT;
    3512           0 :                 if (zpi.src_port_min != 0 || zpi.proto == IPPROTO_ICMP)
    3513           0 :                         zpi.filter_bm |= PBR_FILTER_SRC_PORT;
    3514           0 :                 if (zpi.dst_port_max != 0)
    3515           0 :                         zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
    3516           0 :                 if (zpi.src_port_max != 0)
    3517           0 :                         zpi.filter_bm |= PBR_FILTER_SRC_PORT_RANGE;
    3518           0 :                 if (zpi.proto != 0)
    3519           0 :                         zpi.filter_bm |= PBR_FILTER_PROTO;
    3520             : 
    3521           0 :                 if (!(zpi.dst.family == AF_INET
    3522             :                       || zpi.dst.family == AF_INET6)) {
    3523           0 :                         zlog_warn(
    3524             :                                 "Unsupported PBR destination IP family: %s (%hhu)",
    3525             :                                 family2str(zpi.dst.family), zpi.dst.family);
    3526           0 :                         goto stream_failure;
    3527             :                 }
    3528           0 :                 if (!(zpi.src.family == AF_INET
    3529             :                       || zpi.src.family == AF_INET6)) {
    3530           0 :                         zlog_warn(
    3531             :                                 "Unsupported PBR source IP family: %s (%hhu)",
    3532             :                                 family2str(zpi.src.family), zpi.src.family);
    3533           0 :                         goto stream_failure;
    3534             :                 }
    3535             : 
    3536             :                 /* calculate backpointer */
    3537           0 :                 zpi.backpointer =
    3538           0 :                         zebra_pbr_lookup_ipset_pername(ipset.ipset_name);
    3539             : 
    3540           0 :                 if (!zpi.backpointer) {
    3541           0 :                         zlog_warn("ipset name specified: %s does not exist",
    3542             :                                   ipset.ipset_name);
    3543           0 :                         goto stream_failure;
    3544             :                 }
    3545             : 
    3546           0 :                 if (hdr->command == ZEBRA_IPSET_ENTRY_ADD)
    3547           0 :                         zebra_pbr_add_ipset_entry(&zpi);
    3548             :                 else
    3549           0 :                         zebra_pbr_del_ipset_entry(&zpi);
    3550             :         }
    3551             : 
    3552           0 : stream_failure:
    3553           0 :         return;
    3554             : }
    3555             : 
    3556             : 
    3557           0 : static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS)
    3558             : {
    3559           0 :         afi_t afi;
    3560             : 
    3561           0 :         STREAM_GETW(msg, afi);
    3562           0 :         if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
    3563           0 :                 zlog_warn(
    3564             :                         "Invalid AFI %u while registering for neighbors notifications",
    3565             :                         afi);
    3566           0 :                 goto stream_failure;
    3567             :         }
    3568           0 :         vrf_bitmap_set(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
    3569           0 : stream_failure:
    3570           0 :         return;
    3571             : }
    3572             : 
    3573           0 : static inline void zebra_neigh_unregister(ZAPI_HANDLER_ARGS)
    3574             : {
    3575           0 :         afi_t afi;
    3576             : 
    3577           0 :         STREAM_GETW(msg, afi);
    3578           0 :         if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
    3579           0 :                 zlog_warn(
    3580             :                         "Invalid AFI %u while unregistering from neighbor notifications",
    3581             :                         afi);
    3582           0 :                 goto stream_failure;
    3583             :         }
    3584           0 :         vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
    3585           0 : stream_failure:
    3586           0 :         return;
    3587             : }
    3588             : 
    3589           0 : static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)
    3590             : {
    3591           0 :         struct stream *s;
    3592           0 :         ifindex_t idx;
    3593           0 :         struct interface *ifp;
    3594           0 :         struct zebra_if *zebra_if = NULL;
    3595           0 :         struct zebra_l2info_gre *gre_info;
    3596           0 :         struct interface *ifp_link = NULL;
    3597           0 :         vrf_id_t vrf_id_link = VRF_UNKNOWN;
    3598           0 :         vrf_id_t vrf_id = zvrf->vrf->vrf_id;
    3599             : 
    3600           0 :         s = msg;
    3601           0 :         STREAM_GETL(s, idx);
    3602           0 :         ifp  = if_lookup_by_index(idx, vrf_id);
    3603             : 
    3604           0 :         if (ifp)
    3605           0 :                 zebra_if = ifp->info;
    3606             : 
    3607           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    3608             : 
    3609           0 :         zclient_create_header(s, ZEBRA_GRE_UPDATE, vrf_id);
    3610             : 
    3611           0 :         if (ifp  && IS_ZEBRA_IF_GRE(ifp) && zebra_if) {
    3612           0 :                 gre_info = &zebra_if->l2info.gre;
    3613             : 
    3614           0 :                 stream_putl(s, idx);
    3615           0 :                 stream_putl(s, gre_info->ikey);
    3616           0 :                 stream_putl(s, gre_info->ikey);
    3617           0 :                 stream_putl(s, gre_info->ifindex_link);
    3618             : 
    3619           0 :                 ifp_link = if_lookup_by_index_per_ns(
    3620             :                                         zebra_ns_lookup(gre_info->link_nsid),
    3621           0 :                                         gre_info->ifindex_link);
    3622           0 :                 if (ifp_link)
    3623           0 :                         vrf_id_link = ifp_link->vrf->vrf_id;
    3624           0 :                 stream_putl(s, vrf_id_link);
    3625           0 :                 stream_putl(s, gre_info->vtep_ip.s_addr);
    3626           0 :                 stream_putl(s, gre_info->vtep_ip_remote.s_addr);
    3627             :         } else {
    3628           0 :                 stream_putl(s, idx);
    3629           0 :                 stream_putl(s, 0);
    3630           0 :                 stream_putl(s, 0);
    3631           0 :                 stream_putl(s, IFINDEX_INTERNAL);
    3632           0 :                 stream_putl(s, VRF_UNKNOWN);
    3633           0 :                 stream_putl(s, 0);
    3634           0 :                 stream_putl(s, 0);
    3635             :         }
    3636             :         /* Write packet size. */
    3637           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    3638           0 :         zserv_send_message(client, s);
    3639             : 
    3640           0 :         return;
    3641           0 :  stream_failure:
    3642             :         return;
    3643             : }
    3644             : 
    3645           0 : static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
    3646             : {
    3647           0 :         struct stream *s;
    3648           0 :         uint8_t fam;
    3649           0 :         ifindex_t idx;
    3650           0 :         struct interface *ifp;
    3651             : 
    3652           0 :         s = msg;
    3653           0 :         STREAM_GETC(s, fam);
    3654           0 :         if (fam != AF_INET && fam != AF_INET6)
    3655             :                 return;
    3656           0 :         STREAM_GETL(s, idx);
    3657           0 :         ifp = if_lookup_by_index_per_ns(zvrf->zns, idx);
    3658           0 :         if (!ifp)
    3659             :                 return;
    3660           0 :         dplane_neigh_table_update(ifp, fam, 1, 0, 0);
    3661           0 : stream_failure:
    3662             :         return;
    3663             : }
    3664             : 
    3665           0 : static inline void zebra_neigh_ip_add(ZAPI_HANDLER_ARGS)
    3666             : {
    3667           0 :         struct stream *s;
    3668           0 :         struct zapi_neigh_ip api = {};
    3669           0 :         int ret;
    3670           0 :         const struct interface *ifp;
    3671             : 
    3672           0 :         s = msg;
    3673           0 :         ret = zclient_neigh_ip_decode(s, &api);
    3674           0 :         if (ret < 0)
    3675           0 :                 return;
    3676           0 :         ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
    3677           0 :         if (!ifp)
    3678             :                 return;
    3679           0 :         dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_INSTALL, ifp, &api.ip_out,
    3680           0 :                                &api.ip_in, api.ndm_state, client->proto);
    3681             : }
    3682             : 
    3683             : 
    3684           0 : static inline void zebra_neigh_ip_del(ZAPI_HANDLER_ARGS)
    3685             : {
    3686           0 :         struct stream *s;
    3687           0 :         struct zapi_neigh_ip api = {};
    3688           0 :         int ret;
    3689           0 :         struct interface *ifp;
    3690             : 
    3691           0 :         s = msg;
    3692           0 :         ret = zclient_neigh_ip_decode(s, &api);
    3693           0 :         if (ret < 0)
    3694           0 :                 return;
    3695           0 :         ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
    3696           0 :         if (!ifp)
    3697             :                 return;
    3698           0 :         dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_DELETE, ifp, &api.ip_out,
    3699           0 :                                &api.ip_in, api.ndm_state, client->proto);
    3700             : }
    3701             : 
    3702             : 
    3703           0 : static inline void zread_iptable(ZAPI_HANDLER_ARGS)
    3704             : {
    3705           0 :         struct zebra_pbr_iptable *zpi =
    3706           0 :                 XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_iptable));
    3707           0 :         struct stream *s;
    3708             : 
    3709           0 :         s = msg;
    3710             : 
    3711           0 :         zpi->interface_name_list = list_new();
    3712           0 :         zpi->sock = client->sock;
    3713           0 :         zpi->vrf_id = zvrf->vrf->vrf_id;
    3714           0 :         STREAM_GETL(s, zpi->unique);
    3715           0 :         STREAM_GETL(s, zpi->type);
    3716           0 :         STREAM_GETL(s, zpi->filter_bm);
    3717           0 :         STREAM_GETL(s, zpi->action);
    3718           0 :         STREAM_GETL(s, zpi->fwmark);
    3719           0 :         STREAM_GET(&zpi->ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
    3720           0 :         STREAM_GETC(s, zpi->family);
    3721           0 :         STREAM_GETW(s, zpi->pkt_len_min);
    3722           0 :         STREAM_GETW(s, zpi->pkt_len_max);
    3723           0 :         STREAM_GETW(s, zpi->tcp_flags);
    3724           0 :         STREAM_GETW(s, zpi->tcp_mask_flags);
    3725           0 :         STREAM_GETC(s, zpi->dscp_value);
    3726           0 :         STREAM_GETC(s, zpi->fragment);
    3727           0 :         STREAM_GETC(s, zpi->protocol);
    3728           0 :         STREAM_GETW(s, zpi->flow_label);
    3729           0 :         STREAM_GETL(s, zpi->nb_interface);
    3730           0 :         zebra_pbr_iptable_update_interfacelist(s, zpi);
    3731             : 
    3732           0 :         if (hdr->command == ZEBRA_IPTABLE_ADD)
    3733           0 :                 zebra_pbr_add_iptable(zpi);
    3734             :         else
    3735           0 :                 zebra_pbr_del_iptable(zpi);
    3736             : 
    3737           0 : stream_failure:
    3738           0 :         zebra_pbr_iptable_free(zpi);
    3739           0 :         zpi = NULL;
    3740           0 :         return;
    3741             : }
    3742             : 
    3743           0 : static inline void zread_neigh_discover(ZAPI_HANDLER_ARGS)
    3744             : {
    3745           0 :         struct stream *s;
    3746           0 :         ifindex_t ifindex;
    3747           0 :         struct interface *ifp;
    3748           0 :         struct prefix p;
    3749           0 :         struct ipaddr ip;
    3750             : 
    3751           0 :         s = msg;
    3752             : 
    3753           0 :         STREAM_GETL(s, ifindex);
    3754             : 
    3755           0 :         ifp = if_lookup_by_index_per_ns(zvrf->zns, ifindex);
    3756           0 :         if (!ifp) {
    3757           0 :                 zlog_debug("Failed to lookup ifindex: %u", ifindex);
    3758           0 :                 return;
    3759             :         }
    3760             : 
    3761           0 :         STREAM_GETC(s, p.family);
    3762           0 :         STREAM_GETC(s, p.prefixlen);
    3763           0 :         STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
    3764             : 
    3765           0 :         if (p.family == AF_INET)
    3766           0 :                 SET_IPADDR_V4(&ip);
    3767             :         else
    3768           0 :                 SET_IPADDR_V6(&ip);
    3769             : 
    3770           0 :         memcpy(&ip.ip.addr, &p.u.prefix, prefix_blen(&p));
    3771             : 
    3772           0 :         dplane_neigh_discover(ifp, &ip);
    3773             : 
    3774           0 : stream_failure:
    3775             :         return;
    3776             : }
    3777             : 
    3778           0 : static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS)
    3779             : {
    3780           0 :         struct stream *s;
    3781           0 :         ifindex_t idx, link_idx;
    3782           0 :         vrf_id_t link_vrf_id;
    3783           0 :         struct interface *ifp;
    3784           0 :         struct interface *ifp_link;
    3785           0 :         vrf_id_t vrf_id = zvrf->vrf->vrf_id;
    3786           0 :         struct zebra_if *zif, *gre_zif;
    3787           0 :         struct zebra_l2info_gre *gre_info;
    3788           0 :         unsigned int mtu;
    3789             : 
    3790           0 :         s = msg;
    3791           0 :         STREAM_GETL(s, idx);
    3792           0 :         ifp  = if_lookup_by_index(idx, vrf_id);
    3793           0 :         STREAM_GETL(s, link_idx);
    3794           0 :         STREAM_GETL(s, link_vrf_id);
    3795           0 :         STREAM_GETL(s, mtu);
    3796             : 
    3797           0 :         ifp_link  = if_lookup_by_index(link_idx, link_vrf_id);
    3798           0 :         if (!ifp_link || !ifp) {
    3799           0 :                 zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params",
    3800             :                           idx, vrf_id, link_idx, link_vrf_id);
    3801           0 :                 return;
    3802             :         }
    3803             : 
    3804           0 :         if (!IS_ZEBRA_IF_GRE(ifp))
    3805             :                 return;
    3806             : 
    3807           0 :         gre_zif = (struct zebra_if *)ifp->info;
    3808           0 :         zif = (struct zebra_if *)ifp_link->info;
    3809           0 :         if (!zif || !gre_zif)
    3810             :                 return;
    3811             : 
    3812           0 :         gre_info = &zif->l2info.gre;
    3813           0 :         if (!gre_info)
    3814             :                 return;
    3815             : 
    3816           0 :         if (!mtu)
    3817           0 :                 mtu = ifp->mtu;
    3818             : 
    3819             :         /* if gre link already set or mtu did not change, do not set it */
    3820           0 :         if (gre_zif->link && gre_zif->link == ifp_link && mtu == ifp->mtu)
    3821             :                 return;
    3822             : 
    3823           0 :         dplane_gre_set(ifp, ifp_link, mtu, gre_info);
    3824             : 
    3825           0 :  stream_failure:
    3826             :         return;
    3827             : }
    3828             : 
    3829           0 : static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
    3830             :                             struct zmsghdr *bad_hdr)
    3831             : {
    3832             : 
    3833           0 :         struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    3834             : 
    3835           0 :         zclient_create_header(s, ZEBRA_ERROR, bad_hdr->vrf_id);
    3836             : 
    3837           0 :         zserv_encode_error(s, error);
    3838             : 
    3839           0 :         client->error_cnt++;
    3840           0 :         zserv_send_message(client, s);
    3841           0 : }
    3842             : 
    3843           0 : static void zserv_error_no_vrf(ZAPI_HANDLER_ARGS)
    3844             : {
    3845           0 :         if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    3846           0 :                 zlog_debug("ZAPI message specifies unknown VRF: %d",
    3847             :                            hdr->vrf_id);
    3848             : 
    3849           0 :         zsend_error_msg(client, ZEBRA_NO_VRF, hdr);
    3850           0 : }
    3851             : 
    3852           0 : static void zserv_error_invalid_msg_type(ZAPI_HANDLER_ARGS)
    3853             : {
    3854           0 :         zlog_info("Zebra received unknown command %d", hdr->command);
    3855             : 
    3856           0 :         zsend_error_msg(client, ZEBRA_INVALID_MSG_TYPE, hdr);
    3857           0 : }
    3858             : 
    3859             : void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
    3860             :         [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
    3861             :         [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
    3862             :         [ZEBRA_INTERFACE_ADD] = zread_interface_add,
    3863             :         [ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
    3864             :         [ZEBRA_INTERFACE_SET_PROTODOWN] = zread_interface_set_protodown,
    3865             :         [ZEBRA_ROUTE_ADD] = zread_route_add,
    3866             :         [ZEBRA_ROUTE_DELETE] = zread_route_del,
    3867             :         [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
    3868             :         [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
    3869             :         [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
    3870             :         [ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete,
    3871             :         [ZEBRA_NEXTHOP_LOOKUP_MRIB] = zread_nexthop_lookup_mrib,
    3872             :         [ZEBRA_HELLO] = zread_hello,
    3873             :         [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register,
    3874             :         [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister,
    3875             :         [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register,
    3876             :         [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register,
    3877             :         [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister,
    3878             : #if HAVE_BFDD > 0
    3879             :         [ZEBRA_BFD_DEST_REPLAY] = zebra_ptm_bfd_dst_replay,
    3880             : #endif /* HAVE_BFDD */
    3881             :         [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister,
    3882             :         [ZEBRA_VRF_LABEL] = zread_vrf_label,
    3883             :         [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
    3884             :         [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
    3885             :         [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable,
    3886             :         [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set,
    3887             :         [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete,
    3888             :         [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,
    3889             :         [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete,
    3890             :         [ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,
    3891             :         [ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats,
    3892             :         [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request,
    3893             :         [ZEBRA_LABEL_MANAGER_CONNECT_ASYNC] = zread_label_manager_request,
    3894             :         [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request,
    3895             :         [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request,
    3896             :         [ZEBRA_FEC_REGISTER] = zread_fec_register,
    3897             :         [ZEBRA_FEC_UNREGISTER] = zread_fec_unregister,
    3898             :         [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip,
    3899             :         [ZEBRA_ADVERTISE_SVI_MACIP] = zebra_vxlan_advertise_svi_macip,
    3900             :         [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet,
    3901             :         [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
    3902             :         [ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es,
    3903             :         [ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es,
    3904             :         [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add_zapi,
    3905             :         [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del_zapi,
    3906             :         [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
    3907             :         [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
    3908             :         [ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
    3909             :         [ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master,
    3910             :         [ZEBRA_PW_ADD] = zread_pseudowire,
    3911             :         [ZEBRA_PW_DELETE] = zread_pseudowire,
    3912             :         [ZEBRA_PW_SET] = zread_pseudowire,
    3913             :         [ZEBRA_PW_UNSET] = zread_pseudowire,
    3914             :         [ZEBRA_RULE_ADD] = zread_rule,
    3915             :         [ZEBRA_RULE_DELETE] = zread_rule,
    3916             :         [ZEBRA_TABLE_MANAGER_CONNECT] = zread_table_manager_request,
    3917             :         [ZEBRA_GET_TABLE_CHUNK] = zread_table_manager_request,
    3918             :         [ZEBRA_RELEASE_TABLE_CHUNK] = zread_table_manager_request,
    3919             :         [ZEBRA_IPSET_CREATE] = zread_ipset,
    3920             :         [ZEBRA_IPSET_DESTROY] = zread_ipset,
    3921             :         [ZEBRA_IPSET_ENTRY_ADD] = zread_ipset_entry,
    3922             :         [ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
    3923             :         [ZEBRA_IPTABLE_ADD] = zread_iptable,
    3924             :         [ZEBRA_IPTABLE_DELETE] = zread_iptable,
    3925             :         [ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
    3926             :         [ZEBRA_VXLAN_SG_REPLAY] = zebra_vxlan_sg_replay,
    3927             :         [ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
    3928             :         [ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
    3929             :         [ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
    3930             :         [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = zread_srv6_manager_request,
    3931             :         [ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK] = zread_srv6_manager_request,
    3932             :         [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
    3933             :         [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
    3934             :         [ZEBRA_NHG_ADD] = zread_nhg_add,
    3935             :         [ZEBRA_NHG_DEL] = zread_nhg_del,
    3936             :         [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
    3937             :         [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh,
    3938             :         [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
    3939             :         [ZEBRA_NEIGH_IP_ADD] = zebra_neigh_ip_add,
    3940             :         [ZEBRA_NEIGH_IP_DEL] = zebra_neigh_ip_del,
    3941             :         [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
    3942             :         [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
    3943             :         [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp,
    3944             :         [ZEBRA_GRE_GET] = zebra_gre_get,
    3945             :         [ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set,
    3946             :         [ZEBRA_TC_QDISC_INSTALL] = zread_tc_qdisc,
    3947             :         [ZEBRA_TC_QDISC_UNINSTALL] = zread_tc_qdisc,
    3948             :         [ZEBRA_TC_CLASS_ADD] = zread_tc_class,
    3949             :         [ZEBRA_TC_CLASS_DELETE] = zread_tc_class,
    3950             :         [ZEBRA_TC_FILTER_ADD] = zread_tc_filter,
    3951             :         [ZEBRA_TC_FILTER_DELETE] = zread_tc_filter,
    3952             : };
    3953             : 
    3954             : /*
    3955             :  * Process a batch of zapi messages.
    3956             :  */
    3957          32 : void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo)
    3958             : {
    3959          32 :         struct zmsghdr hdr;
    3960          32 :         struct zebra_vrf *zvrf;
    3961          32 :         struct stream *msg;
    3962          32 :         struct stream_fifo temp_fifo;
    3963             : 
    3964          32 :         stream_fifo_init(&temp_fifo);
    3965             : 
    3966          97 :         while (stream_fifo_head(fifo)) {
    3967          65 :                 msg = stream_fifo_pop(fifo);
    3968             : 
    3969          65 :                 if (STREAM_READABLE(msg) > ZEBRA_MAX_PACKET_SIZ) {
    3970           0 :                         if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
    3971           0 :                                 zlog_debug(
    3972             :                                         "ZAPI message is %zu bytes long but the maximum packet size is %u; dropping",
    3973             :                                         STREAM_READABLE(msg),
    3974             :                                         ZEBRA_MAX_PACKET_SIZ);
    3975           0 :                         goto continue_loop;
    3976             :                 }
    3977             : 
    3978          65 :                 zapi_parse_header(msg, &hdr);
    3979             : 
    3980          65 :                 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV
    3981          65 :                     && IS_ZEBRA_DEBUG_DETAIL)
    3982           0 :                         zserv_log_message(NULL, msg, &hdr);
    3983             : 
    3984          65 :                 hdr.length -= ZEBRA_HEADER_SIZE;
    3985             : 
    3986             :                 /* Before checking for a handler function, check for
    3987             :                  * special messages that are handled in another module;
    3988             :                  * we'll treat these as opaque.
    3989             :                  */
    3990          65 :                 if (zebra_opaque_handles_msgid(hdr.command)) {
    3991             :                         /* Reset message buffer */
    3992           0 :                         stream_set_getp(msg, 0);
    3993             : 
    3994           0 :                         stream_fifo_push(&temp_fifo, msg);
    3995             : 
    3996             :                         /* Continue without freeing the message */
    3997           0 :                         msg = NULL;
    3998           0 :                         goto continue_loop;
    3999             :                 }
    4000             : 
    4001             :                 /* lookup vrf */
    4002          65 :                 zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
    4003          65 :                 if (!zvrf) {
    4004           0 :                         zserv_error_no_vrf(client, &hdr, msg, zvrf);
    4005           0 :                         goto continue_loop;
    4006             :                 }
    4007             : 
    4008          65 :                 if (hdr.command >= array_size(zserv_handlers)
    4009          65 :                     || zserv_handlers[hdr.command] == NULL) {
    4010           0 :                         zserv_error_invalid_msg_type(client, &hdr, msg, zvrf);
    4011           0 :                         goto continue_loop;
    4012             :                 }
    4013             : 
    4014          65 :                 zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
    4015             : 
    4016          65 : continue_loop:
    4017          65 :                 stream_free(msg);
    4018             :         }
    4019             : 
    4020             :         /* Dispatch any special messages from the temp fifo */
    4021          32 :         if (stream_fifo_head(&temp_fifo) != NULL)
    4022           0 :                 zebra_opaque_enqueue_batch(&temp_fifo);
    4023             : 
    4024          32 :         stream_fifo_deinit(&temp_fifo);
    4025          32 : }

Generated by: LCOV version v1.16-topotato