back to topotato report
topotato coverage report
Current view: top level - pimd - pim_zlookup.c (source / functions) Hit Total Coverage
Test: test_mld_basic.py::MLDBasic Lines: 106 258 41.1 %
Date: 2023-02-24 18:38:01 Functions: 6 12 50.0 %

          Line data    Source code
       1             : /*
       2             :  * PIM for Quagga
       3             :  * Copyright (C) 2008  Everton da Silva Marques
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation; either version 2 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but
      11             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "log.h"
      23             : #include "prefix.h"
      24             : #include "zclient.h"
      25             : #include "stream.h"
      26             : #include "network.h"
      27             : #include "thread.h"
      28             : #include "prefix.h"
      29             : #include "vty.h"
      30             : #include "lib_errors.h"
      31             : 
      32             : #include "pimd.h"
      33             : #include "pim_instance.h"
      34             : #include "pim_iface.h"
      35             : #include "pim_neighbor.h"
      36             : #include "pim_pim.h"
      37             : #include "pim_str.h"
      38             : #include "pim_oil.h"
      39             : #include "pim_zlookup.h"
      40             : #include "pim_addr.h"
      41             : 
      42             : static struct zclient *zlookup = NULL;
      43             : struct thread *zlookup_read;
      44             : 
      45             : static void zclient_lookup_sched(struct zclient *zlookup, int delay);
      46             : static void zclient_lookup_read_pipe(struct thread *thread);
      47             : 
      48             : /* Connect to zebra for nexthop lookup. */
      49           1 : static void zclient_lookup_connect(struct thread *t)
      50             : {
      51           1 :         struct zclient *zlookup;
      52             : 
      53           1 :         zlookup = THREAD_ARG(t);
      54             : 
      55           1 :         if (zlookup->sock >= 0) {
      56             :                 return;
      57             :         }
      58             : 
      59           1 :         if (zclient_socket_connect(zlookup) < 0) {
      60           0 :                 ++zlookup->fail;
      61           0 :                 zlog_warn("%s: failure connecting zclient socket: failures=%d",
      62             :                           __func__, zlookup->fail);
      63             :         } else {
      64           1 :                 zlookup->fail = 0; /* reset counter on connection */
      65             :         }
      66             : 
      67           1 :         if (zclient_send_hello(zlookup) == ZCLIENT_SEND_FAILURE) {
      68           0 :                 if (close(zlookup->sock)) {
      69           0 :                         zlog_warn("%s: closing fd=%d: errno=%d %s", __func__,
      70             :                                   zlookup->sock, errno, safe_strerror(errno));
      71             :                 }
      72           0 :                 zlookup->sock = -1;
      73             :         }
      74             : 
      75           1 :         if (zlookup->sock < 0) {
      76             :                 /* Since last connect failed, retry within 10 secs */
      77           0 :                 zclient_lookup_sched(zlookup, 10);
      78           0 :                 return;
      79             :         }
      80             : 
      81           1 :         thread_add_timer(router->master, zclient_lookup_read_pipe, zlookup, 60,
      82             :                          &zlookup_read);
      83             : }
      84             : 
      85             : /* Schedule connection with delay. */
      86           0 : static void zclient_lookup_sched(struct zclient *zlookup, int delay)
      87             : {
      88           0 :         thread_add_timer(router->master, zclient_lookup_connect, zlookup, delay,
      89             :                          &zlookup->t_connect);
      90             : 
      91           0 :         zlog_notice("%s: zclient lookup connection scheduled for %d seconds",
      92             :                     __func__, delay);
      93           0 : }
      94             : 
      95             : /* Schedule connection for now. */
      96           1 : static void zclient_lookup_sched_now(struct zclient *zlookup)
      97             : {
      98           1 :         thread_add_event(router->master, zclient_lookup_connect, zlookup, 0,
      99             :                          &zlookup->t_connect);
     100             : 
     101           1 :         zlog_notice("%s: zclient lookup immediate connection scheduled",
     102             :                     __func__);
     103           1 : }
     104             : 
     105             : /* Schedule reconnection, if needed. */
     106           0 : static void zclient_lookup_reconnect(struct zclient *zlookup)
     107             : {
     108           0 :         if (zlookup->t_connect) {
     109             :                 return;
     110             :         }
     111             : 
     112           0 :         zclient_lookup_sched_now(zlookup);
     113             : }
     114             : 
     115           0 : static void zclient_lookup_failed(struct zclient *zlookup)
     116             : {
     117           0 :         if (zlookup->sock >= 0) {
     118           0 :                 if (close(zlookup->sock)) {
     119           0 :                         zlog_warn("%s: closing fd=%d: errno=%d %s", __func__,
     120             :                                   zlookup->sock, errno, safe_strerror(errno));
     121             :                 }
     122           0 :                 zlookup->sock = -1;
     123             :         }
     124             : 
     125           0 :         zclient_lookup_reconnect(zlookup);
     126           0 : }
     127             : 
     128           0 : void zclient_lookup_free(void)
     129             : {
     130           0 :         THREAD_OFF(zlookup_read);
     131           0 :         zclient_stop(zlookup);
     132           0 :         zclient_free(zlookup);
     133           0 :         zlookup = NULL;
     134           0 : }
     135             : 
     136           1 : void zclient_lookup_new(void)
     137             : {
     138           1 :         struct zclient_options options = zclient_options_default;
     139           1 :         options.synchronous = true;
     140             : 
     141           1 :         zlookup = zclient_new(router->master, &options, NULL, 0);
     142           1 :         if (!zlookup) {
     143           0 :                 flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
     144             :                          __func__);
     145           0 :                 return;
     146             :         }
     147             : 
     148           1 :         zlookup->sock = -1;
     149           1 :         zlookup->t_connect = NULL;
     150           1 :         zlookup->privs = &pimd_privs;
     151             : 
     152           1 :         zclient_lookup_sched_now(zlookup);
     153             : 
     154           1 :         zlog_notice("%s: zclient lookup socket initialized", __func__);
     155             : }
     156             : 
     157           2 : static int zclient_read_nexthop(struct pim_instance *pim,
     158             :                                 struct zclient *zlookup,
     159             :                                 struct pim_zlookup_nexthop nexthop_tab[],
     160             :                                 const int tab_size, pim_addr addr)
     161             : {
     162           2 :         int num_ifindex = 0;
     163           2 :         struct stream *s;
     164           2 :         uint16_t length;
     165           2 :         uint8_t marker;
     166           2 :         uint8_t version;
     167           2 :         vrf_id_t vrf_id;
     168           2 :         uint16_t command = 0;
     169           2 :         struct ipaddr raddr;
     170           2 :         uint8_t distance;
     171           2 :         uint32_t metric;
     172           2 :         int nexthop_num;
     173           2 :         int i, err;
     174             : 
     175           2 :         if (PIM_DEBUG_PIM_NHT_DETAIL)
     176           0 :                 zlog_debug("%s: addr=%pPAs(%s)", __func__, &addr,
     177             :                            pim->vrf->name);
     178             : 
     179           2 :         s = zlookup->ibuf;
     180             : 
     181           4 :         while (command != ZEBRA_NEXTHOP_LOOKUP_MRIB) {
     182           2 :                 stream_reset(s);
     183           2 :                 err = zclient_read_header(s, zlookup->sock, &length, &marker,
     184             :                                           &version, &vrf_id, &command);
     185           2 :                 if (err < 0) {
     186           0 :                         flog_err(EC_LIB_ZAPI_MISSMATCH,
     187             :                                  "%s: zclient_read_header() failed", __func__);
     188           0 :                         zclient_lookup_failed(zlookup);
     189           0 :                         return -1;
     190             :                 }
     191             : 
     192           2 :                 if (command == ZEBRA_ERROR) {
     193           0 :                         enum zebra_error_types error;
     194             : 
     195           0 :                         zapi_error_decode(s, &error);
     196             :                         /* Do nothing with it for now */
     197           0 :                         return -1;
     198             :                 }
     199             :         }
     200             : 
     201           2 :         stream_get_ipaddr(s, &raddr);
     202             : 
     203           2 :         if (raddr.ipa_type != PIM_IPADDR ||
     204           2 :             pim_addr_cmp(raddr.ipaddr_pim, addr)) {
     205           0 :                 zlog_warn("%s: address mismatch: addr=%pPA(%s) raddr=%pIA",
     206             :                           __func__, &addr, pim->vrf->name, &raddr);
     207             :                 /* warning only */
     208             :         }
     209             : 
     210           2 :         distance = stream_getc(s);
     211           2 :         metric = stream_getl(s);
     212           2 :         nexthop_num = stream_getc(s);
     213             : 
     214           2 :         if (nexthop_num < 1 || nexthop_num > router->multipath) {
     215           0 :                 if (PIM_DEBUG_PIM_NHT_DETAIL)
     216           0 :                         zlog_debug("%s: socket %d bad nexthop_num=%d", __func__,
     217             :                                    zlookup->sock, nexthop_num);
     218           0 :                 return -6;
     219             :         }
     220             : 
     221           4 :         for (i = 0; i < nexthop_num; ++i) {
     222           2 :                 vrf_id_t nexthop_vrf_id;
     223           2 :                 enum nexthop_types_t nexthop_type;
     224           2 :                 struct in_addr nh_ip4;
     225           2 :                 struct in6_addr nh_ip6;
     226           2 :                 ifindex_t nh_ifi;
     227             : 
     228           2 :                 nexthop_vrf_id = stream_getl(s);
     229           2 :                 nexthop_type = stream_getc(s);
     230           2 :                 if (num_ifindex >= tab_size) {
     231           0 :                         zlog_warn(
     232             :                                 "%s: found too many nexthop ifindexes (%d > %d) for address %pPAs(%s)",
     233             :                                 __func__, (num_ifindex + 1), tab_size, &addr,
     234             :                                 pim->vrf->name);
     235           0 :                         return num_ifindex;
     236             :                 }
     237           2 :                 nexthop_tab[num_ifindex].protocol_distance = distance;
     238           2 :                 nexthop_tab[num_ifindex].route_metric = metric;
     239           2 :                 nexthop_tab[num_ifindex].vrf_id = nexthop_vrf_id;
     240           2 :                 switch (nexthop_type) {
     241           2 :                 case NEXTHOP_TYPE_IFINDEX:
     242           2 :                         nexthop_tab[num_ifindex].ifindex = stream_getl(s);
     243             :                         /*
     244             :                          * Connected route (i.e. no nexthop), use
     245             :                          * address passed in as PIM nexthop.  This will
     246             :                          * allow us to work in cases where we are
     247             :                          * trying to find a route for this box.
     248             :                          */
     249           2 :                         nexthop_tab[num_ifindex].nexthop_addr = addr;
     250           2 :                         ++num_ifindex;
     251           2 :                         break;
     252           0 :                 case NEXTHOP_TYPE_IPV4_IFINDEX:
     253             :                 case NEXTHOP_TYPE_IPV4:
     254           0 :                         nh_ip4.s_addr = stream_get_ipv4(s);
     255           0 :                         nh_ifi = stream_getl(s);
     256             : #if PIM_IPV == 4
     257             :                         nexthop_tab[num_ifindex].nexthop_addr = nh_ip4;
     258             :                         nexthop_tab[num_ifindex].ifindex = nh_ifi;
     259             :                         ++num_ifindex;
     260             : #else
     261           0 :                         zlog_warn(
     262             :                                 "cannot use IPv4 nexthop %pI4(%d) for IPv6 %pPA",
     263             :                                 &nh_ip4, nh_ifi, &addr);
     264             : #endif
     265           0 :                         break;
     266           0 :                 case NEXTHOP_TYPE_IPV6:
     267             :                 case NEXTHOP_TYPE_IPV6_IFINDEX:
     268           0 :                         stream_get(&nh_ip6, s, sizeof(nh_ip6));
     269           0 :                         nh_ifi = stream_getl(s);
     270             : 
     271             : #if PIM_IPV == 6
     272           0 :                         nexthop_tab[num_ifindex].nexthop_addr = nh_ip6;
     273           0 :                         nexthop_tab[num_ifindex].ifindex = nh_ifi;
     274           0 :                         ++num_ifindex;
     275             : #else
     276             :                         /* RFC 5549 v4-over-v6 nexthop handling */
     277             : 
     278             :                         /*
     279             :                          * If we are sending v6 secondary assume we receive v6
     280             :                          * secondary
     281             :                          */
     282             :                         struct interface *ifp = if_lookup_by_index(
     283             :                                 nh_ifi,
     284             :                                 nexthop_vrf_id);
     285             : 
     286             :                         if (!ifp)
     287             :                                 break;
     288             : 
     289             :                         struct pim_neighbor *nbr;
     290             : 
     291             :                         if (pim->send_v6_secondary) {
     292             :                                 struct prefix p;
     293             : 
     294             :                                 p.family = AF_INET6;
     295             :                                 p.prefixlen = IPV6_MAX_BITLEN;
     296             :                                 p.u.prefix6 = nh_ip6;
     297             : 
     298             :                                 nbr = pim_neighbor_find_by_secondary(ifp, &p);
     299             :                         } else
     300             :                                 nbr = pim_neighbor_find_if(ifp);
     301             : 
     302             :                         if (!nbr)
     303             :                                 break;
     304             : 
     305             :                         nexthop_tab[num_ifindex].nexthop_addr =
     306             :                                 nbr->source_addr;
     307             :                         nexthop_tab[num_ifindex].ifindex = nh_ifi;
     308             :                         ++num_ifindex;
     309             : #endif
     310           0 :                         break;
     311           0 :                 case NEXTHOP_TYPE_BLACKHOLE:
     312             :                         /* do nothing */
     313           0 :                         zlog_warn(
     314             :                                 "%s: found non-ifindex nexthop type=%d for address %pPAs(%s)",
     315             :                                 __func__, nexthop_type, &addr, pim->vrf->name);
     316           0 :                         break;
     317             :                 }
     318             :         }
     319             : 
     320             :         return num_ifindex;
     321             : }
     322             : 
     323           2 : static int zclient_lookup_nexthop_once(struct pim_instance *pim,
     324             :                                        struct pim_zlookup_nexthop nexthop_tab[],
     325             :                                        const int tab_size, pim_addr addr)
     326             : {
     327           2 :         struct stream *s;
     328           2 :         int ret;
     329           2 :         struct ipaddr ipaddr;
     330             : 
     331           2 :         if (PIM_DEBUG_PIM_NHT_DETAIL)
     332           0 :                 zlog_debug("%s: addr=%pPAs(%s)", __func__, &addr,
     333             :                            pim->vrf->name);
     334             : 
     335             :         /* Check socket. */
     336           2 :         if (zlookup->sock < 0) {
     337           0 :                 flog_err(EC_LIB_ZAPI_SOCKET,
     338             :                          "%s: zclient lookup socket is not connected",
     339             :                          __func__);
     340           0 :                 zclient_lookup_failed(zlookup);
     341           0 :                 return -1;
     342             :         }
     343             : 
     344           2 :         if (pim->vrf->vrf_id == VRF_UNKNOWN) {
     345           0 :                 zlog_notice(
     346             :                         "%s: VRF: %s does not fully exist yet, delaying lookup",
     347             :                         __func__, pim->vrf->name);
     348           0 :                 return -1;
     349             :         }
     350             : 
     351           2 :         ipaddr.ipa_type = PIM_IPADDR;
     352           2 :         ipaddr.ipaddr_pim = addr;
     353             : 
     354           2 :         s = zlookup->obuf;
     355           2 :         stream_reset(s);
     356           2 :         zclient_create_header(s, ZEBRA_NEXTHOP_LOOKUP_MRIB, pim->vrf->vrf_id);
     357           2 :         stream_put_ipaddr(s, &ipaddr);
     358           2 :         stream_putw_at(s, 0, stream_get_endp(s));
     359             : 
     360           2 :         ret = writen(zlookup->sock, s->data, stream_get_endp(s));
     361           2 :         if (ret < 0) {
     362           0 :                 flog_err(
     363             :                         EC_LIB_SOCKET,
     364             :                         "%s: writen() failure: %d writing to zclient lookup socket",
     365             :                         __func__, errno);
     366           0 :                 zclient_lookup_failed(zlookup);
     367           0 :                 return -2;
     368             :         }
     369           2 :         if (ret == 0) {
     370           0 :                 flog_err_sys(EC_LIB_SOCKET,
     371             :                              "%s: connection closed on zclient lookup socket",
     372             :                              __func__);
     373           0 :                 zclient_lookup_failed(zlookup);
     374           0 :                 return -3;
     375             :         }
     376             : 
     377           2 :         return zclient_read_nexthop(pim, zlookup, nexthop_tab, tab_size, addr);
     378             : }
     379             : 
     380           0 : void zclient_lookup_read_pipe(struct thread *thread)
     381             : {
     382           0 :         struct zclient *zlookup = THREAD_ARG(thread);
     383           0 :         struct pim_instance *pim = pim_get_pim_instance(VRF_DEFAULT);
     384           0 :         struct pim_zlookup_nexthop nexthop_tab[10];
     385           0 :         pim_addr l = PIMADDR_ANY;
     386             : 
     387           0 :         if (!pim) {
     388           0 :                 if (PIM_DEBUG_PIM_NHT_DETAIL)
     389           0 :                         zlog_debug("%s: Unable to find pim instance", __func__);
     390           0 :                 return;
     391             :         }
     392             : 
     393           0 :         zclient_lookup_nexthop_once(pim, nexthop_tab, 10, l);
     394           0 :         thread_add_timer(router->master, zclient_lookup_read_pipe, zlookup, 60,
     395             :                          &zlookup_read);
     396             : }
     397             : 
     398           2 : int zclient_lookup_nexthop(struct pim_instance *pim,
     399             :                            struct pim_zlookup_nexthop nexthop_tab[],
     400             :                            const int tab_size, pim_addr addr,
     401             :                            int max_lookup)
     402             : {
     403           2 :         int lookup;
     404           2 :         uint32_t route_metric = 0xFFFFFFFF;
     405           2 :         uint8_t protocol_distance = 0xFF;
     406             : 
     407           2 :         pim->nexthop_lookups++;
     408             : 
     409           2 :         for (lookup = 0; lookup < max_lookup; ++lookup) {
     410           2 :                 int num_ifindex;
     411           2 :                 int first_ifindex;
     412           2 :                 pim_addr nexthop_addr;
     413             : 
     414           2 :                 num_ifindex = zclient_lookup_nexthop_once(pim, nexthop_tab,
     415             :                                                           tab_size, addr);
     416           2 :                 if (num_ifindex < 1) {
     417           0 :                         if (PIM_DEBUG_PIM_NHT_DETAIL)
     418           0 :                                 zlog_debug(
     419             :                                         "%s: lookup=%d/%d: could not find nexthop ifindex for address %pPA(%s)",
     420             :                                         __func__, lookup, max_lookup, &addr,
     421             :                                         pim->vrf->name);
     422           2 :                         return -1;
     423             :                 }
     424             : 
     425           2 :                 if (lookup < 1) {
     426             :                         /* this is the non-recursive lookup - save original
     427             :                          * metric/distance */
     428           2 :                         route_metric = nexthop_tab[0].route_metric;
     429           2 :                         protocol_distance = nexthop_tab[0].protocol_distance;
     430             :                 }
     431             : 
     432             :                 /*
     433             :                  * FIXME: Non-recursive nexthop ensured only for first ifindex.
     434             :                  * However, recursive route lookup should really be fixed in
     435             :                  * zebra daemon.
     436             :                  * See also TODO T24.
     437             :                  *
     438             :                  * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since
     439             :                  * it was being stored.  This Doesn't solve all cases of
     440             :                  * recursive lookup but for the most common types it does.
     441             :                  */
     442           2 :                 first_ifindex = nexthop_tab[0].ifindex;
     443           2 :                 nexthop_addr = nexthop_tab[0].nexthop_addr;
     444           2 :                 if (first_ifindex > 0) {
     445             :                         /* found: first ifindex is non-recursive nexthop */
     446             : 
     447           2 :                         if (lookup > 0) {
     448             :                                 /* Report non-recursive success after first
     449             :                                  * lookup */
     450           0 :                                 if (PIM_DEBUG_PIM_NHT)
     451           0 :                                         zlog_debug(
     452             :                                                 "%s: lookup=%d/%d: found non-recursive ifindex=%d for address %pPA(%s) dist=%d met=%d",
     453             :                                                 __func__, lookup, max_lookup,
     454             :                                                 first_ifindex, &addr,
     455             :                                                 pim->vrf->name,
     456             :                                                 nexthop_tab[0]
     457             :                                                         .protocol_distance,
     458             :                                                 nexthop_tab[0].route_metric);
     459             : 
     460             :                                 /* use last address as nexthop address */
     461           0 :                                 nexthop_tab[0].nexthop_addr = addr;
     462             : 
     463             :                                 /* report original route metric/distance */
     464           0 :                                 nexthop_tab[0].route_metric = route_metric;
     465           0 :                                 nexthop_tab[0].protocol_distance =
     466             :                                         protocol_distance;
     467             :                         }
     468             : 
     469           2 :                         return num_ifindex;
     470             :                 }
     471             : 
     472           0 :                 if (PIM_DEBUG_PIM_NHT)
     473           0 :                         zlog_debug(
     474             :                                 "%s: lookup=%d/%d: zebra returned recursive nexthop %pPAs for address %pPA(%s) dist=%d met=%d",
     475             :                                 __func__, lookup, max_lookup, &nexthop_addr,
     476             :                                 &addr, pim->vrf->name,
     477             :                                 nexthop_tab[0].protocol_distance,
     478             :                                 nexthop_tab[0].route_metric);
     479             : 
     480           0 :                 addr = nexthop_addr; /* use nexthop
     481             :                                         addr for recursive lookup */
     482             : 
     483             :         } /* for (max_lookup) */
     484             : 
     485           0 :         if (PIM_DEBUG_PIM_NHT)
     486           0 :                 zlog_warn(
     487             :                         "%s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %pPA(%s)",
     488             :                         __func__, lookup, max_lookup, &addr, pim->vrf->name);
     489             : 
     490             :         return -2;
     491             : }
     492             : 
     493           0 : void pim_zlookup_show_ip_multicast(struct vty *vty)
     494             : {
     495           0 :         vty_out(vty, "Zclient lookup socket: ");
     496           0 :         if (zlookup) {
     497           0 :                 vty_out(vty, "%d failures=%d\n", zlookup->sock, zlookup->fail);
     498             :         } else {
     499           0 :                 vty_out(vty, "<null zclient>\n");
     500             :         }
     501           0 : }
     502             : 
     503           0 : int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
     504             : {
     505           0 :         struct stream *s = zlookup->obuf;
     506           0 :         uint16_t command = 0;
     507           0 :         unsigned long long lastused;
     508           0 :         pim_sgaddr sg;
     509           0 :         int count = 0;
     510           0 :         int ret;
     511           0 :         pim_sgaddr more = {};
     512           0 :         struct interface *ifp =
     513           0 :                 pim_if_find_by_vif_index(c_oil->pim, *oil_parent(c_oil));
     514             : 
     515           0 :         if (PIM_DEBUG_ZEBRA) {
     516           0 :                 more.src = *oil_origin(c_oil);
     517           0 :                 more.grp = *oil_mcastgrp(c_oil);
     518           0 :                 zlog_debug(
     519             :                         "Sending Request for New Channel Oil Information%pSG VIIF %d(%s)",
     520             :                         &more, *oil_parent(c_oil), c_oil->pim->vrf->name);
     521             :         }
     522             : 
     523           0 :         if (!ifp)
     524             :                 return -1;
     525             : 
     526           0 :         stream_reset(s);
     527           0 :         zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS,
     528           0 :                               c_oil->pim->vrf->vrf_id);
     529           0 :         stream_putl(s, PIM_AF);
     530           0 :         stream_write(s, oil_origin(c_oil), sizeof(pim_addr));
     531           0 :         stream_write(s, oil_mcastgrp(c_oil), sizeof(pim_addr));
     532           0 :         stream_putl(s, ifp->ifindex);
     533           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     534             : 
     535           0 :         count = stream_get_endp(s);
     536           0 :         ret = writen(zlookup->sock, s->data, count);
     537           0 :         if (ret <= 0) {
     538           0 :                 flog_err(
     539             :                         EC_LIB_SOCKET,
     540             :                         "%s: writen() failure: %d writing to zclient lookup socket",
     541             :                         __func__, errno);
     542           0 :                 return -1;
     543             :         }
     544             : 
     545           0 :         s = zlookup->ibuf;
     546             : 
     547           0 :         while (command != ZEBRA_IPMR_ROUTE_STATS) {
     548           0 :                 int err;
     549           0 :                 uint16_t length = 0;
     550           0 :                 vrf_id_t vrf_id;
     551           0 :                 uint8_t marker;
     552           0 :                 uint8_t version;
     553             : 
     554           0 :                 stream_reset(s);
     555           0 :                 err = zclient_read_header(s, zlookup->sock, &length, &marker,
     556             :                                           &version, &vrf_id, &command);
     557           0 :                 if (err < 0) {
     558           0 :                         flog_err(EC_LIB_ZAPI_MISSMATCH,
     559             :                                  "%s: zclient_read_header() failed", __func__);
     560           0 :                         zclient_lookup_failed(zlookup);
     561           0 :                         return -1;
     562             :                 }
     563             :         }
     564             : 
     565           0 :         stream_get(&sg.src, s, sizeof(pim_addr));
     566           0 :         stream_get(&sg.grp, s, sizeof(pim_addr));
     567             : 
     568           0 :         more.src = *oil_origin(c_oil);
     569           0 :         more.grp = *oil_mcastgrp(c_oil);
     570           0 :         if (pim_sgaddr_cmp(sg, more)) {
     571           0 :                 if (PIM_DEBUG_ZEBRA)
     572           0 :                         flog_err(
     573             :                                 EC_LIB_ZAPI_MISSMATCH,
     574             :                                 "%s: Received wrong %pSG(%s) information requested",
     575             :                                 __func__, &more, c_oil->pim->vrf->name);
     576           0 :                 zclient_lookup_failed(zlookup);
     577           0 :                 return -3;
     578             :         }
     579             : 
     580           0 :         stream_get(&lastused, s, sizeof(lastused));
     581             :         /* signed success value from netlink_talk; currently unused */
     582           0 :         (void)stream_getl(s);
     583             : 
     584           0 :         c_oil->cc.lastused = lastused;
     585             : 
     586           0 :         return 0;
     587             : }

Generated by: LCOV version v1.16-topotato