back to topotato report
topotato coverage report
Current view: top level - lib - prefix.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 206 845 24.4 %
Date: 2023-11-16 17:19:14 Functions: 36 158 22.8 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Prefix related functions.
       4             :  * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : 
       9             : #include "command.h"
      10             : #include "prefix.h"
      11             : #include "ipaddr.h"
      12             : #include "vty.h"
      13             : #include "sockunion.h"
      14             : #include "memory.h"
      15             : #include "log.h"
      16             : #include "jhash.h"
      17             : #include "lib_errors.h"
      18             : #include "printfrr.h"
      19             : #include "vxlan.h"
      20             : 
      21          12 : DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix");
      22          12 : DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec");
      23             : 
      24             : /* Maskbit. */
      25             : static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
      26             :                                   0xf8, 0xfc, 0xfe, 0xff};
      27             : 
      28             : /* Number of bits in prefix type. */
      29             : #ifndef PNBBY
      30             : #define PNBBY 8
      31             : #endif /* PNBBY */
      32             : 
      33             : #define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff)
      34             : 
      35           0 : int is_zero_mac(const struct ethaddr *mac)
      36             : {
      37           0 :         int i = 0;
      38             : 
      39           0 :         for (i = 0; i < ETH_ALEN; i++) {
      40           0 :                 if (mac->octet[i])
      41             :                         return 0;
      42             :         }
      43             : 
      44             :         return 1;
      45             : }
      46             : 
      47           0 : bool is_bcast_mac(const struct ethaddr *mac)
      48             : {
      49           0 :         int i = 0;
      50             : 
      51           0 :         for (i = 0; i < ETH_ALEN; i++)
      52           0 :                 if (mac->octet[i] != 0xFF)
      53             :                         return false;
      54             : 
      55             :         return true;
      56             : }
      57             : 
      58           0 : bool is_mcast_mac(const struct ethaddr *mac)
      59             : {
      60           0 :         if ((mac->octet[0] & 0x01) == 0x01)
      61           0 :                 return true;
      62             : 
      63             :         return false;
      64             : }
      65             : 
      66         337 : unsigned int prefix_bit(const uint8_t *prefix, const uint16_t bit_index)
      67             : {
      68         337 :         unsigned int offset = bit_index / 8;
      69         337 :         unsigned int shift = 7 - (bit_index % 8);
      70             : 
      71         337 :         return (prefix[offset] >> shift) & 1;
      72             : }
      73             : 
      74           0 : int str2family(const char *string)
      75             : {
      76           0 :         if (!strcmp("ipv4", string))
      77             :                 return AF_INET;
      78           0 :         else if (!strcmp("ipv6", string))
      79             :                 return AF_INET6;
      80           0 :         else if (!strcmp("ethernet", string))
      81             :                 return AF_ETHERNET;
      82           0 :         else if (!strcmp("evpn", string))
      83           0 :                 return AF_EVPN;
      84             :         return -1;
      85             : }
      86             : 
      87           0 : const char *family2str(int family)
      88             : {
      89           0 :         switch (family) {
      90             :         case AF_INET:
      91             :                 return "IPv4";
      92           0 :         case AF_INET6:
      93           0 :                 return "IPv6";
      94           0 :         case AF_ETHERNET:
      95           0 :                 return "Ethernet";
      96           0 :         case AF_EVPN:
      97           0 :                 return "Evpn";
      98             :         }
      99           0 :         return "?";
     100             : }
     101             : 
     102             : /* Address Family Identifier to Address Family converter. */
     103          20 : int afi2family(afi_t afi)
     104             : {
     105          20 :         if (afi == AFI_IP)
     106             :                 return AF_INET;
     107           4 :         else if (afi == AFI_IP6)
     108             :                 return AF_INET6;
     109           0 :         else if (afi == AFI_L2VPN)
     110           0 :                 return AF_ETHERNET;
     111             :         /* NOTE: EVPN code should NOT use this interface. */
     112             :         return 0;
     113             : }
     114             : 
     115         394 : afi_t family2afi(int family)
     116             : {
     117         394 :         if (family == AF_INET)
     118             :                 return AFI_IP;
     119         138 :         else if (family == AF_INET6)
     120             :                 return AFI_IP6;
     121           0 :         else if (family == AF_ETHERNET || family == AF_EVPN)
     122           0 :                 return AFI_L2VPN;
     123             :         return 0;
     124             : }
     125             : 
     126           0 : const char *afi2str_lower(afi_t afi)
     127             : {
     128           0 :         switch (afi) {
     129             :         case AFI_IP:
     130             :                 return "ipv4";
     131           0 :         case AFI_IP6:
     132           0 :                 return "ipv6";
     133           0 :         case AFI_L2VPN:
     134           0 :                 return "l2vpn";
     135           0 :         case AFI_MAX:
     136             :         case AFI_UNSPEC:
     137           0 :                 return "bad-value";
     138             :         }
     139             : 
     140           0 :         assert(!"Reached end of function we should never reach");
     141             : }
     142             : 
     143          27 : const char *afi2str(afi_t afi)
     144             : {
     145          27 :         switch (afi) {
     146             :         case AFI_IP:
     147             :                 return "IPv4";
     148           0 :         case AFI_IP6:
     149           0 :                 return "IPv6";
     150           0 :         case AFI_L2VPN:
     151           0 :                 return "l2vpn";
     152           0 :         case AFI_MAX:
     153             :         case AFI_UNSPEC:
     154           0 :                 return "bad-value";
     155             :         }
     156             : 
     157           0 :         assert(!"Reached end of function we should never reach");
     158             : }
     159             : 
     160          27 : const char *safi2str(safi_t safi)
     161             : {
     162          27 :         switch (safi) {
     163             :         case SAFI_UNICAST:
     164             :                 return "unicast";
     165           0 :         case SAFI_MULTICAST:
     166           0 :                 return "multicast";
     167           0 :         case SAFI_MPLS_VPN:
     168           0 :                 return "vpn";
     169           0 :         case SAFI_ENCAP:
     170           0 :                 return "encap";
     171           0 :         case SAFI_EVPN:
     172           0 :                 return "evpn";
     173           0 :         case SAFI_LABELED_UNICAST:
     174           0 :                 return "labeled-unicast";
     175           0 :         case SAFI_FLOWSPEC:
     176           0 :                 return "flowspec";
     177           0 :         case SAFI_UNSPEC:
     178             :         case SAFI_MAX:
     179           0 :                 return "unknown";
     180             :         }
     181             : 
     182           0 :         assert(!"Reached end of function we should never reach");
     183             : }
     184             : 
     185             : /* If n includes p prefix then return 1 else return 0. */
     186         280 : int prefix_match(union prefixconstptr unet, union prefixconstptr upfx)
     187             : {
     188         280 :         const struct prefix *n = unet.p;
     189         280 :         const struct prefix *p = upfx.p;
     190         280 :         int offset;
     191         280 :         int shift;
     192         280 :         const uint8_t *np, *pp;
     193             : 
     194             :         /* If n's prefix is longer than p's one return 0. */
     195         280 :         if (n->prefixlen > p->prefixlen)
     196             :                 return 0;
     197             : 
     198         280 :         if (n->family == AF_FLOWSPEC) {
     199             :                 /* prefixlen is unused. look at fs prefix len */
     200           0 :                 if (n->u.prefix_flowspec.family !=
     201           0 :                     p->u.prefix_flowspec.family)
     202             :                         return 0;
     203             : 
     204           0 :                 if (n->u.prefix_flowspec.prefixlen >
     205           0 :                     p->u.prefix_flowspec.prefixlen)
     206             :                         return 0;
     207             : 
     208             :                 /* Set both prefix's head pointer. */
     209           0 :                 np = (const uint8_t *)&n->u.prefix_flowspec.ptr;
     210           0 :                 pp = (const uint8_t *)&p->u.prefix_flowspec.ptr;
     211             : 
     212           0 :                 offset = n->u.prefix_flowspec.prefixlen;
     213             : 
     214           0 :                 while (offset--)
     215           0 :                         if (np[offset] != pp[offset])
     216             :                                 return 0;
     217             :                 return 1;
     218             :         }
     219             : 
     220             :         /* Set both prefix's head pointer. */
     221         280 :         np = n->u.val;
     222         280 :         pp = p->u.val;
     223             : 
     224         280 :         offset = n->prefixlen / PNBBY;
     225         280 :         shift = n->prefixlen % PNBBY;
     226             : 
     227         280 :         if (shift)
     228          64 :                 if (maskbit[shift] & (np[offset] ^ pp[offset]))
     229             :                         return 0;
     230             : 
     231         758 :         while (offset--)
     232         522 :                 if (np[offset] != pp[offset])
     233             :                         return 0;
     234             :         return 1;
     235             : 
     236             : }
     237             : 
     238             : /*
     239             :  * n is a type5 evpn prefix. This function tries to see if there is an
     240             :  * ip-prefix within n which matches prefix p
     241             :  * If n includes p prefix then return 1 else return 0.
     242             :  */
     243           0 : int evpn_type5_prefix_match(const struct prefix *n, const struct prefix *p)
     244             : {
     245           0 :         int offset;
     246           0 :         int shift;
     247           0 :         int prefixlen;
     248           0 :         const uint8_t *np, *pp;
     249           0 :         struct prefix_evpn *evp;
     250             : 
     251           0 :         if (n->family != AF_EVPN)
     252             :                 return 0;
     253             : 
     254           0 :         evp = (struct prefix_evpn *)n;
     255           0 :         pp = p->u.val;
     256             : 
     257           0 :         if ((evp->prefix.route_type != 5) ||
     258           0 :             (p->family == AF_INET6 && !is_evpn_prefix_ipaddr_v6(evp)) ||
     259           0 :             (p->family == AF_INET && !is_evpn_prefix_ipaddr_v4(evp)) ||
     260           0 :             (is_evpn_prefix_ipaddr_none(evp)))
     261             :                 return 0;
     262             : 
     263           0 :         prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
     264           0 :         np = evp->prefix.prefix_addr.ip.ip.addrbytes;
     265             : 
     266             :         /* If n's prefix is longer than p's one return 0. */
     267           0 :         if (prefixlen > p->prefixlen)
     268             :                 return 0;
     269             : 
     270           0 :         offset = prefixlen / PNBBY;
     271           0 :         shift = prefixlen % PNBBY;
     272             : 
     273           0 :         if (shift)
     274           0 :                 if (maskbit[shift] & (np[offset] ^ pp[offset]))
     275             :                         return 0;
     276             : 
     277           0 :         while (offset--)
     278           0 :                 if (np[offset] != pp[offset])
     279             :                         return 0;
     280             :         return 1;
     281             : 
     282             : }
     283             : 
     284             : /* If n includes p then return 1 else return 0. Prefix mask is not considered */
     285           0 : int prefix_match_network_statement(union prefixconstptr unet,
     286             :                                    union prefixconstptr upfx)
     287             : {
     288           0 :         const struct prefix *n = unet.p;
     289           0 :         const struct prefix *p = upfx.p;
     290           0 :         int offset;
     291           0 :         int shift;
     292           0 :         const uint8_t *np, *pp;
     293             : 
     294             :         /* Set both prefix's head pointer. */
     295           0 :         np = n->u.val;
     296           0 :         pp = p->u.val;
     297             : 
     298           0 :         offset = n->prefixlen / PNBBY;
     299           0 :         shift = n->prefixlen % PNBBY;
     300             : 
     301           0 :         if (shift)
     302           0 :                 if (maskbit[shift] & (np[offset] ^ pp[offset]))
     303             :                         return 0;
     304             : 
     305           0 :         while (offset--)
     306           0 :                 if (np[offset] != pp[offset])
     307             :                         return 0;
     308             :         return 1;
     309             : }
     310             : 
     311             : #ifdef __clang_analyzer__
     312             : #undef prefix_copy      /* cf. prefix.h */
     313             : #endif
     314             : 
     315        1056 : void prefix_copy(union prefixptr udest, union prefixconstptr usrc)
     316             : {
     317        1056 :         struct prefix *dest = udest.p;
     318        1056 :         const struct prefix *src = usrc.p;
     319             : 
     320        1056 :         dest->family = src->family;
     321        1056 :         dest->prefixlen = src->prefixlen;
     322             : 
     323        1056 :         if (src->family == AF_INET)
     324         532 :                 dest->u.prefix4 = src->u.prefix4;
     325             :         else if (src->family == AF_INET6)
     326         524 :                 dest->u.prefix6 = src->u.prefix6;
     327             :         else if (src->family == AF_ETHERNET) {
     328           0 :                 memcpy(&dest->u.prefix_eth, &src->u.prefix_eth,
     329             :                        sizeof(struct ethaddr));
     330             :         } else if (src->family == AF_EVPN) {
     331           0 :                 memcpy(&dest->u.prefix_evpn, &src->u.prefix_evpn,
     332             :                        sizeof(struct evpn_addr));
     333             :         } else if (src->family == AF_UNSPEC) {
     334           0 :                 dest->u.lp.id = src->u.lp.id;
     335           0 :                 dest->u.lp.adv_router = src->u.lp.adv_router;
     336             :         } else if (src->family == AF_FLOWSPEC) {
     337           0 :                 void *temp;
     338           0 :                 int len;
     339             : 
     340           0 :                 len = src->u.prefix_flowspec.prefixlen;
     341           0 :                 dest->u.prefix_flowspec.prefixlen =
     342             :                         src->u.prefix_flowspec.prefixlen;
     343           0 :                 dest->u.prefix_flowspec.family =
     344           0 :                         src->u.prefix_flowspec.family;
     345           0 :                 dest->family = src->family;
     346           0 :                 temp = XCALLOC(MTYPE_PREFIX_FLOWSPEC, len);
     347           0 :                 dest->u.prefix_flowspec.ptr = (uintptr_t)temp;
     348           0 :                 memcpy((void *)dest->u.prefix_flowspec.ptr,
     349           0 :                        (void *)src->u.prefix_flowspec.ptr, len);
     350             :         } else {
     351           0 :                 flog_err(EC_LIB_DEVELOPMENT,
     352             :                          "prefix_copy(): Unknown address family %d",
     353             :                          src->family);
     354           0 :                 assert(0);
     355             :         }
     356        1056 : }
     357             : 
     358           0 : bool evpn_addr_same(const struct evpn_addr *e1, const struct evpn_addr *e2)
     359             : {
     360           0 :         if (e1->route_type != e2->route_type)
     361             :                 return false;
     362           0 :         if (e1->route_type == BGP_EVPN_AD_ROUTE)
     363           0 :                 return (!memcmp(&e1->ead_addr.esi.val,
     364           0 :                                 &e2->ead_addr.esi.val, ESI_BYTES) &&
     365           0 :                         e1->ead_addr.eth_tag == e2->ead_addr.eth_tag &&
     366           0 :                         !ipaddr_cmp(&e1->ead_addr.ip, &e2->ead_addr.ip));
     367             :         if (e1->route_type == BGP_EVPN_MAC_IP_ROUTE)
     368           0 :                 return (e1->macip_addr.eth_tag == e2->macip_addr.eth_tag &&
     369           0 :                         e1->macip_addr.ip_prefix_length
     370           0 :                                 == e2->macip_addr.ip_prefix_length &&
     371           0 :                         !memcmp(&e1->macip_addr.mac,
     372           0 :                                 &e2->macip_addr.mac, ETH_ALEN) &&
     373           0 :                         !ipaddr_cmp(&e1->macip_addr.ip, &e2->macip_addr.ip));
     374             :         if (e1->route_type == BGP_EVPN_IMET_ROUTE)
     375           0 :                 return (e1->imet_addr.eth_tag == e2->imet_addr.eth_tag &&
     376           0 :                         e1->imet_addr.ip_prefix_length
     377           0 :                                 == e2->imet_addr.ip_prefix_length &&
     378           0 :                         !ipaddr_cmp(&e1->imet_addr.ip, &e2->imet_addr.ip));
     379             :         if (e1->route_type == BGP_EVPN_ES_ROUTE)
     380           0 :                 return (!memcmp(&e1->es_addr.esi.val,
     381           0 :                                 &e2->es_addr.esi.val, ESI_BYTES) &&
     382           0 :                         e1->es_addr.ip_prefix_length
     383           0 :                                 == e2->es_addr.ip_prefix_length &&
     384           0 :                         !ipaddr_cmp(&e1->es_addr.ip, &e2->es_addr.ip));
     385             :         if (e1->route_type == BGP_EVPN_IP_PREFIX_ROUTE)
     386           0 :                 return (e1->prefix_addr.eth_tag == e2->prefix_addr.eth_tag &&
     387           0 :                         e1->prefix_addr.ip_prefix_length
     388           0 :                                 == e2->prefix_addr.ip_prefix_length &&
     389           0 :                         !ipaddr_cmp(&e1->prefix_addr.ip, &e2->prefix_addr.ip));
     390             :         return true;
     391             : }
     392             : 
     393             : /*
     394             :  * Return 1 if the address/netmask contained in the prefix structure
     395             :  * is the same, and else return 0.  For this routine, 'same' requires
     396             :  * that not only the prefix length and the network part be the same,
     397             :  * but also the host part.  Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
     398             :  * the same.  Note that this routine has the same return value sense
     399             :  * as '==' (which is different from prefix_cmp).
     400             :  */
     401         160 : int prefix_same(union prefixconstptr up1, union prefixconstptr up2)
     402             : {
     403         160 :         const struct prefix *p1 = up1.p;
     404         160 :         const struct prefix *p2 = up2.p;
     405             : 
     406         160 :         if ((p1 && !p2) || (!p1 && p2))
     407             :                 return 0;
     408             : 
     409         160 :         if (!p1 && !p2)
     410             :                 return 1;
     411             : 
     412         160 :         if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) {
     413         132 :                 if (p1->family == AF_INET)
     414          29 :                         if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
     415             :                                 return 1;
     416         105 :                 if (p1->family == AF_INET6)
     417         103 :                         if (IPV6_ADDR_SAME(&p1->u.prefix6.s6_addr,
     418             :                                            &p2->u.prefix6.s6_addr))
     419             :                                 return 1;
     420          29 :                 if (p1->family == AF_ETHERNET)
     421           0 :                         if (!memcmp(&p1->u.prefix_eth, &p2->u.prefix_eth,
     422             :                                     sizeof(struct ethaddr)))
     423             :                                 return 1;
     424          29 :                 if (p1->family == AF_EVPN)
     425           0 :                         if (evpn_addr_same(&p1->u.prefix_evpn, &p2->u.prefix_evpn))
     426             :                                 return 1;
     427          29 :                 if (p1->family == AF_FLOWSPEC) {
     428           0 :                         if (p1->u.prefix_flowspec.family !=
     429           0 :                             p2->u.prefix_flowspec.family)
     430             :                                 return 0;
     431           0 :                         if (p1->u.prefix_flowspec.prefixlen !=
     432           0 :                             p2->u.prefix_flowspec.prefixlen)
     433             :                                 return 0;
     434           0 :                         if (!memcmp(&p1->u.prefix_flowspec.ptr,
     435           0 :                                     &p2->u.prefix_flowspec.ptr,
     436             :                                     p2->u.prefix_flowspec.prefixlen))
     437             :                                 return 1;
     438             :                 }
     439             :         }
     440             :         return 0;
     441             : }
     442             : 
     443             : /*
     444             :  * Return -1/0/1 comparing the prefixes in a way that gives a full/linear
     445             :  * order.
     446             :  *
     447             :  * Network prefixes are considered the same if the prefix lengths are equal
     448             :  * and the network parts are the same.  Host bits (which are considered masked
     449             :  * by the prefix length) are not significant.  Thus, 10.0.0.1/8 and
     450             :  * 10.0.0.2/8 are considered equivalent by this routine.  Note that
     451             :  * this routine has the same return sense as strcmp (which is different
     452             :  * from prefix_same).
     453             :  */
     454         259 : int prefix_cmp(union prefixconstptr up1, union prefixconstptr up2)
     455             : {
     456         259 :         const struct prefix *p1 = up1.p;
     457         259 :         const struct prefix *p2 = up2.p;
     458         259 :         int offset;
     459         259 :         int shift;
     460         259 :         int i;
     461             : 
     462             :         /* Set both prefix's head pointer. */
     463         259 :         const uint8_t *pp1;
     464         259 :         const uint8_t *pp2;
     465             : 
     466         259 :         if (p1->family != p2->family)
     467           0 :                 return numcmp(p1->family, p2->family);
     468         259 :         if (p1->family == AF_FLOWSPEC) {
     469           0 :                 pp1 = (const uint8_t *)p1->u.prefix_flowspec.ptr;
     470           0 :                 pp2 = (const uint8_t *)p2->u.prefix_flowspec.ptr;
     471             : 
     472           0 :                 if (p1->u.prefix_flowspec.family !=
     473           0 :                     p2->u.prefix_flowspec.family)
     474             :                         return 1;
     475             : 
     476           0 :                 if (p1->u.prefix_flowspec.prefixlen !=
     477           0 :                     p2->u.prefix_flowspec.prefixlen)
     478           0 :                         return numcmp(p1->u.prefix_flowspec.prefixlen,
     479             :                                       p2->u.prefix_flowspec.prefixlen);
     480             : 
     481           0 :                 offset = p1->u.prefix_flowspec.prefixlen;
     482           0 :                 while (offset--)
     483           0 :                         if (pp1[offset] != pp2[offset])
     484           0 :                                 return numcmp(pp1[offset], pp2[offset]);
     485             :                 return 0;
     486             :         }
     487         259 :         pp1 = p1->u.val;
     488         259 :         pp2 = p2->u.val;
     489             : 
     490         259 :         if (p1->prefixlen != p2->prefixlen)
     491           0 :                 return numcmp(p1->prefixlen, p2->prefixlen);
     492         259 :         offset = p1->prefixlen / PNBBY;
     493         259 :         shift = p1->prefixlen % PNBBY;
     494             : 
     495         259 :         i = memcmp(pp1, pp2, offset);
     496         259 :         if (i)
     497             :                 return i;
     498             : 
     499             :         /*
     500             :          * At this point offset was the same, if we have shift
     501             :          * that means we still have data to compare, if shift is
     502             :          * 0 then we are at the end of the data structure
     503             :          * and should just return, as that we will be accessing
     504             :          * memory beyond the end of the party zone
     505             :          */
     506         240 :         if (shift)
     507           0 :                 return numcmp(pp1[offset] & maskbit[shift],
     508             :                               pp2[offset] & maskbit[shift]);
     509             : 
     510             :         return 0;
     511             : }
     512             : 
     513             : /*
     514             :  * Count the number of common bits in 2 prefixes. The prefix length is
     515             :  * ignored for this function; the whole prefix is compared. If the prefix
     516             :  * address families don't match, return -1; otherwise the return value is
     517             :  * in range 0 ... maximum prefix length for the address family.
     518             :  */
     519           0 : int prefix_common_bits(union prefixconstptr ua, union prefixconstptr ub)
     520             : {
     521           0 :         const struct prefix *p1 = ua.p;
     522           0 :         const struct prefix *p2 = ub.p;
     523           0 :         int pos, bit;
     524           0 :         int length = 0;
     525           0 :         uint8_t xor ;
     526             : 
     527             :         /* Set both prefix's head pointer. */
     528           0 :         const uint8_t *pp1 = p1->u.val;
     529           0 :         const uint8_t *pp2 = p2->u.val;
     530             : 
     531           0 :         if (p1->family == AF_INET)
     532           0 :                 length = IPV4_MAX_BYTELEN;
     533           0 :         if (p1->family == AF_INET6)
     534           0 :                 length = IPV6_MAX_BYTELEN;
     535           0 :         if (p1->family == AF_ETHERNET)
     536           0 :                 length = ETH_ALEN;
     537           0 :         if (p1->family == AF_EVPN)
     538           0 :                 length = 8 * sizeof(struct evpn_addr);
     539             : 
     540           0 :         if (p1->family != p2->family || !length)
     541             :                 return -1;
     542             : 
     543           0 :         for (pos = 0; pos < length; pos++)
     544           0 :                 if (pp1[pos] != pp2[pos])
     545             :                         break;
     546           0 :         if (pos == length)
     547           0 :                 return pos * 8;
     548             : 
     549           0 :         xor = pp1[pos] ^ pp2[pos];
     550           0 :         for (bit = 0; bit < 8; bit++)
     551           0 :                 if (xor&(1 << (7 - bit)))
     552             :                         break;
     553             : 
     554           0 :         return pos * 8 + bit;
     555             : }
     556             : 
     557             : /* Return prefix family type string. */
     558           0 : const char *prefix_family_str(union prefixconstptr pu)
     559             : {
     560           0 :         const struct prefix *p = pu.p;
     561             : 
     562           0 :         if (p->family == AF_INET)
     563             :                 return "inet";
     564           0 :         if (p->family == AF_INET6)
     565             :                 return "inet6";
     566           0 :         if (p->family == AF_ETHERNET)
     567             :                 return "ether";
     568           0 :         if (p->family == AF_EVPN)
     569           0 :                 return "evpn";
     570             :         return "unspec";
     571             : }
     572             : 
     573             : /* Allocate new prefix_ipv4 structure. */
     574           4 : struct prefix_ipv4 *prefix_ipv4_new(void)
     575             : {
     576           4 :         struct prefix_ipv4 *p;
     577             : 
     578             :         /* Call prefix_new to allocate a full-size struct prefix to avoid
     579             :            problems
     580             :            where the struct prefix_ipv4 is cast to struct prefix and unallocated
     581             :            bytes were being referenced (e.g. in structure assignments). */
     582           4 :         p = (struct prefix_ipv4 *)prefix_new();
     583           4 :         p->family = AF_INET;
     584           4 :         return p;
     585             : }
     586             : 
     587             : /* Free prefix_ipv4 structure. */
     588           0 : void prefix_ipv4_free(struct prefix_ipv4 **p)
     589             : {
     590           0 :         prefix_free((struct prefix **)p);
     591           0 : }
     592             : 
     593             : /* If given string is valid return 1 else return 0 */
     594           0 : int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
     595             : {
     596           0 :         int ret;
     597           0 :         int plen;
     598           0 :         char *pnt;
     599           0 :         char *cp;
     600             : 
     601             :         /* Find slash inside string. */
     602           0 :         pnt = strchr(str, '/');
     603             : 
     604             :         /* String doesn't contail slash. */
     605           0 :         if (pnt == NULL) {
     606             :                 /* Convert string to prefix. */
     607           0 :                 ret = inet_pton(AF_INET, str, &p->prefix);
     608           0 :                 if (ret == 0)
     609             :                         return 0;
     610             : 
     611             :                 /* If address doesn't contain slash we assume it host address.
     612             :                  */
     613           0 :                 p->family = AF_INET;
     614           0 :                 p->prefixlen = IPV4_MAX_BITLEN;
     615             : 
     616           0 :                 return ret;
     617             :         } else {
     618           0 :                 cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
     619           0 :                 memcpy(cp, str, pnt - str);
     620           0 :                 *(cp + (pnt - str)) = '\0';
     621           0 :                 ret = inet_pton(AF_INET, cp, &p->prefix);
     622           0 :                 XFREE(MTYPE_TMP, cp);
     623           0 :                 if (ret == 0)
     624             :                         return 0;
     625             : 
     626             :                 /* Get prefix length. */
     627           0 :                 plen = (uint8_t)atoi(++pnt);
     628           0 :                 if (plen > IPV4_MAX_BITLEN)
     629             :                         return 0;
     630             : 
     631           0 :                 p->family = AF_INET;
     632           0 :                 p->prefixlen = plen;
     633             :         }
     634             : 
     635           0 :         return ret;
     636             : }
     637             : 
     638             : /* When string format is invalid return 0. */
     639           0 : int str2prefix_eth(const char *str, struct prefix_eth *p)
     640             : {
     641           0 :         int ret = 0;
     642           0 :         int plen = 48;
     643           0 :         char *pnt;
     644           0 :         char *cp = NULL;
     645           0 :         const char *str_addr = str;
     646           0 :         unsigned int a[6];
     647           0 :         int i;
     648           0 :         bool slash = false;
     649             : 
     650           0 :         if (!strcmp(str, "any")) {
     651           0 :                 memset(p, 0, sizeof(*p));
     652           0 :                 p->family = AF_ETHERNET;
     653           0 :                 return 1;
     654             :         }
     655             : 
     656             :         /* Find slash inside string. */
     657           0 :         pnt = strchr(str, '/');
     658             : 
     659           0 :         if (pnt) {
     660             :                 /* Get prefix length. */
     661           0 :                 plen = (uint8_t)atoi(++pnt);
     662           0 :                 if (plen > 48) {
     663           0 :                         ret = 0;
     664           0 :                         goto done;
     665             :                 }
     666             : 
     667           0 :                 cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
     668           0 :                 memcpy(cp, str, pnt - str);
     669           0 :                 *(cp + (pnt - str)) = '\0';
     670             : 
     671           0 :                 str_addr = cp;
     672           0 :                 slash = true;
     673             :         }
     674             : 
     675             :         /* Convert string to prefix. */
     676           0 :         if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2,
     677             :                    a + 3, a + 4, a + 5)
     678             :             != 6) {
     679           0 :                 ret = 0;
     680           0 :                 goto done;
     681             :         }
     682           0 :         for (i = 0; i < 6; ++i) {
     683           0 :                 p->eth_addr.octet[i] = a[i] & 0xff;
     684             :         }
     685           0 :         p->prefixlen = plen;
     686           0 :         p->family = AF_ETHERNET;
     687             : 
     688             :         /*
     689             :          * special case to allow old configurations to work
     690             :          * Since all zero's is implicitly meant to allow
     691             :          * a comparison to zero, let's assume
     692             :          */
     693           0 :         if (!slash && is_zero_mac(&(p->eth_addr)))
     694           0 :                 p->prefixlen = 0;
     695             : 
     696             :         ret = 1;
     697             : 
     698           0 : done:
     699           0 :         XFREE(MTYPE_TMP, cp);
     700             : 
     701           0 :         return ret;
     702             : }
     703             : 
     704             : /* Convert masklen into IP address's netmask (network byte order). */
     705         247 : void masklen2ip(const int masklen, struct in_addr *netmask)
     706             : {
     707         247 :         assert(masklen >= 0 && masklen <= IPV4_MAX_BITLEN);
     708             : 
     709             :         /* left shift is only defined for less than the size of the type.
     710             :          * we unconditionally use long long in case the target platform
     711             :          * has defined behaviour for << 32 (or has a 64-bit left shift) */
     712             : 
     713         247 :         if (sizeof(unsigned long long) > 4)
     714         247 :                 netmask->s_addr = htonl(0xffffffffULL << (32 - masklen));
     715             :         else
     716             :                 netmask->s_addr =
     717             :                         htonl(masklen ? 0xffffffffU << (32 - masklen) : 0);
     718         247 : }
     719             : 
     720             : /* Convert IP address's netmask into integer. We assume netmask is
     721             :  * sequential one. Argument netmask should be network byte order. */
     722           0 : uint8_t ip_masklen(struct in_addr netmask)
     723             : {
     724           0 :         uint32_t tmp = ~ntohl(netmask.s_addr);
     725             : 
     726             :         /*
     727             :          * clz: count leading zeroes. sadly, the behaviour of this builtin is
     728             :          * undefined for a 0 argument, even though most CPUs give 32
     729             :          */
     730           0 :         return tmp ? __builtin_clz(tmp) : 32;
     731             : }
     732             : 
     733             : /* Apply mask to IPv4 prefix (network byte order). */
     734         247 : void apply_mask_ipv4(struct prefix_ipv4 *p)
     735             : {
     736         247 :         struct in_addr mask;
     737         247 :         masklen2ip(p->prefixlen, &mask);
     738         247 :         p->prefix.s_addr &= mask.s_addr;
     739         247 : }
     740             : 
     741             : /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
     742          22 : int prefix_ipv4_any(const struct prefix_ipv4 *p)
     743             : {
     744          22 :         return (p->prefix.s_addr == INADDR_ANY && p->prefixlen == 0);
     745             : }
     746             : 
     747             : /* Allocate a new ip version 6 route */
     748          14 : struct prefix_ipv6 *prefix_ipv6_new(void)
     749             : {
     750          14 :         struct prefix_ipv6 *p;
     751             : 
     752             :         /* Allocate a full-size struct prefix to avoid problems with structure
     753             :            size mismatches. */
     754          14 :         p = (struct prefix_ipv6 *)prefix_new();
     755          14 :         p->family = AF_INET6;
     756          14 :         return p;
     757             : }
     758             : 
     759             : /* Free prefix for IPv6. */
     760           0 : void prefix_ipv6_free(struct prefix_ipv6 **p)
     761             : {
     762           0 :         prefix_free((struct prefix **)p);
     763           0 : }
     764             : 
     765             : /* If given string is valid return 1 else return 0 */
     766           0 : int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
     767             : {
     768           0 :         char *pnt;
     769           0 :         char *cp;
     770           0 :         int ret;
     771             : 
     772           0 :         pnt = strchr(str, '/');
     773             : 
     774             :         /* If string doesn't contain `/' treat it as host route. */
     775           0 :         if (pnt == NULL) {
     776           0 :                 ret = inet_pton(AF_INET6, str, &p->prefix);
     777           0 :                 if (ret == 0)
     778             :                         return 0;
     779           0 :                 p->prefixlen = IPV6_MAX_BITLEN;
     780             :         } else {
     781           0 :                 int plen;
     782             : 
     783           0 :                 cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
     784           0 :                 memcpy(cp, str, pnt - str);
     785           0 :                 *(cp + (pnt - str)) = '\0';
     786           0 :                 ret = inet_pton(AF_INET6, cp, &p->prefix);
     787           0 :                 XFREE(MTYPE_TMP, cp);
     788           0 :                 if (ret == 0)
     789             :                         return 0;
     790           0 :                 plen = (uint8_t)atoi(++pnt);
     791           0 :                 if (plen > IPV6_MAX_BITLEN)
     792             :                         return 0;
     793           0 :                 p->prefixlen = plen;
     794             :         }
     795           0 :         p->family = AF_INET6;
     796             : 
     797           0 :         return ret;
     798             : }
     799             : 
     800             : /* Convert struct in6_addr netmask into integer.
     801             :  * FIXME return uint8_t as ip_maskleni() does. */
     802           0 : int ip6_masklen(struct in6_addr netmask)
     803             : {
     804           0 :         if (netmask.s6_addr32[0] != 0xffffffffU)
     805           0 :                 return __builtin_clz(~ntohl(netmask.s6_addr32[0]));
     806           0 :         if (netmask.s6_addr32[1] != 0xffffffffU)
     807           0 :                 return __builtin_clz(~ntohl(netmask.s6_addr32[1])) + 32;
     808           0 :         if (netmask.s6_addr32[2] != 0xffffffffU)
     809           0 :                 return __builtin_clz(~ntohl(netmask.s6_addr32[2])) + 64;
     810           0 :         if (netmask.s6_addr32[3] != 0xffffffffU)
     811           0 :                 return __builtin_clz(~ntohl(netmask.s6_addr32[3])) + 96;
     812             :         /* note __builtin_clz(0) is undefined */
     813             :         return 128;
     814             : }
     815             : 
     816           0 : void masklen2ip6(const int masklen, struct in6_addr *netmask)
     817             : {
     818           0 :         assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN);
     819             : 
     820           0 :         if (masklen == 0) {
     821             :                 /* note << 32 is undefined */
     822           0 :                 memset(netmask, 0, sizeof(*netmask));
     823           0 :         } else if (masklen <= 32) {
     824           0 :                 netmask->s6_addr32[0] = htonl(0xffffffffU << (32 - masklen));
     825           0 :                 netmask->s6_addr32[1] = 0;
     826           0 :                 netmask->s6_addr32[2] = 0;
     827           0 :                 netmask->s6_addr32[3] = 0;
     828           0 :         } else if (masklen <= 64) {
     829           0 :                 netmask->s6_addr32[0] = 0xffffffffU;
     830           0 :                 netmask->s6_addr32[1] = htonl(0xffffffffU << (64 - masklen));
     831           0 :                 netmask->s6_addr32[2] = 0;
     832           0 :                 netmask->s6_addr32[3] = 0;
     833           0 :         } else if (masklen <= 96) {
     834           0 :                 netmask->s6_addr32[0] = 0xffffffffU;
     835           0 :                 netmask->s6_addr32[1] = 0xffffffffU;
     836           0 :                 netmask->s6_addr32[2] = htonl(0xffffffffU << (96 - masklen));
     837           0 :                 netmask->s6_addr32[3] = 0;
     838             :         } else {
     839           0 :                 netmask->s6_addr32[0] = 0xffffffffU;
     840           0 :                 netmask->s6_addr32[1] = 0xffffffffU;
     841           0 :                 netmask->s6_addr32[2] = 0xffffffffU;
     842           0 :                 netmask->s6_addr32[3] = htonl(0xffffffffU << (128 - masklen));
     843             :         }
     844           0 : }
     845             : 
     846         280 : void apply_mask_ipv6(struct prefix_ipv6 *p)
     847             : {
     848         280 :         uint8_t *pnt;
     849         280 :         int index;
     850         280 :         int offset;
     851             : 
     852         280 :         index = p->prefixlen / 8;
     853             : 
     854         280 :         if (index < 16) {
     855         234 :                 pnt = (uint8_t *)&p->prefix;
     856         234 :                 offset = p->prefixlen % 8;
     857             : 
     858         234 :                 pnt[index] &= maskbit[offset];
     859         234 :                 index++;
     860             : 
     861        1904 :                 while (index < 16)
     862        1670 :                         pnt[index++] = 0;
     863             :         }
     864         280 : }
     865             : 
     866         478 : void apply_mask(union prefixptr pu)
     867             : {
     868         478 :         struct prefix *p = pu.p;
     869             : 
     870         478 :         switch (p->family) {
     871         236 :         case AF_INET:
     872         236 :                 apply_mask_ipv4(pu.p4);
     873         236 :                 break;
     874         242 :         case AF_INET6:
     875         242 :                 apply_mask_ipv6(pu.p6);
     876         242 :                 break;
     877             :         default:
     878             :                 break;
     879             :         }
     880         478 :         return;
     881             : }
     882             : 
     883             : /* Utility function of convert between struct prefix <=> union sockunion. */
     884          30 : struct prefix *sockunion2hostprefix(const union sockunion *su,
     885             :                                     struct prefix *prefix)
     886             : {
     887          30 :         if (su->sa.sa_family == AF_INET) {
     888           0 :                 struct prefix_ipv4 *p;
     889             : 
     890           0 :                 p = prefix ? (struct prefix_ipv4 *)prefix : prefix_ipv4_new();
     891           0 :                 p->family = AF_INET;
     892           0 :                 p->prefix = su->sin.sin_addr;
     893           0 :                 p->prefixlen = IPV4_MAX_BITLEN;
     894           0 :                 return (struct prefix *)p;
     895             :         }
     896          30 :         if (su->sa.sa_family == AF_INET6) {
     897          30 :                 struct prefix_ipv6 *p;
     898             : 
     899          30 :                 p = prefix ? (struct prefix_ipv6 *)prefix : prefix_ipv6_new();
     900          30 :                 p->family = AF_INET6;
     901          30 :                 p->prefixlen = IPV6_MAX_BITLEN;
     902          30 :                 memcpy(&p->prefix, &su->sin6.sin6_addr,
     903             :                        sizeof(struct in6_addr));
     904          30 :                 return (struct prefix *)p;
     905             :         }
     906             :         return NULL;
     907             : }
     908             : 
     909           0 : void prefix2sockunion(const struct prefix *p, union sockunion *su)
     910             : {
     911           0 :         memset(su, 0, sizeof(*su));
     912             : 
     913           0 :         su->sa.sa_family = p->family;
     914           0 :         if (p->family == AF_INET)
     915           0 :                 su->sin.sin_addr = p->u.prefix4;
     916           0 :         if (p->family == AF_INET6)
     917           0 :                 memcpy(&su->sin6.sin6_addr, &p->u.prefix6,
     918             :                        sizeof(struct in6_addr));
     919           0 : }
     920             : 
     921         160 : int prefix_blen(union prefixconstptr pu)
     922             : {
     923         160 :         const struct prefix *p = pu.p;
     924             : 
     925         160 :         switch (p->family) {
     926             :         case AF_INET:
     927             :                 return IPV4_MAX_BYTELEN;
     928             :         case AF_INET6:
     929             :                 return IPV6_MAX_BYTELEN;
     930             :         case AF_ETHERNET:
     931             :                 return ETH_ALEN;
     932             :         }
     933             :         return 0;
     934             : }
     935             : 
     936             : /* Generic function for conversion string to struct prefix. */
     937           0 : int str2prefix(const char *str, struct prefix *p)
     938             : {
     939           0 :         int ret;
     940             : 
     941           0 :         if (!str || !p)
     942             :                 return 0;
     943             : 
     944             :         /* First we try to convert string to struct prefix_ipv4. */
     945           0 :         ret = str2prefix_ipv4(str, (struct prefix_ipv4 *)p);
     946           0 :         if (ret)
     947             :                 return ret;
     948             : 
     949             :         /* Next we try to convert string to struct prefix_ipv6. */
     950           0 :         ret = str2prefix_ipv6(str, (struct prefix_ipv6 *)p);
     951           0 :         if (ret)
     952             :                 return ret;
     953             : 
     954             :         /* Next we try to convert string to struct prefix_eth. */
     955           0 :         ret = str2prefix_eth(str, (struct prefix_eth *)p);
     956           0 :         if (ret)
     957             :                 return ret;
     958             : 
     959             :         return 0;
     960             : }
     961             : 
     962           0 : static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
     963             :                                       int size)
     964             : {
     965           0 :         uint8_t family;
     966           0 :         char buf[ESI_STR_LEN];
     967           0 :         char buf1[INET6_ADDRSTRLEN];
     968             : 
     969           0 :         family = IS_IPADDR_V4(&p->prefix.ead_addr.ip) ? AF_INET : AF_INET6;
     970           0 :         snprintf(str, size, "[%d]:[%u]:[%s]:[%d]:[%s]:[%u]",
     971           0 :                  p->prefix.route_type, p->prefix.ead_addr.eth_tag,
     972             :                  esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)),
     973             :                  (family == AF_INET) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
     974           0 :                  inet_ntop(family, &p->prefix.ead_addr.ip.ipaddr_v4, buf1,
     975             :                            sizeof(buf1)),
     976           0 :                  p->prefix.ead_addr.frag_id);
     977           0 :         return str;
     978             : }
     979             : 
     980           0 : static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
     981             :                                         int size)
     982             : {
     983           0 :         uint8_t family;
     984           0 :         char buf1[ETHER_ADDR_STRLEN];
     985           0 :         char buf2[PREFIX2STR_BUFFER];
     986             : 
     987           0 :         if (is_evpn_prefix_ipaddr_none(p))
     988           0 :                 snprintf(str, size, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
     989           0 :                          p->prefix.macip_addr.eth_tag, 8 * ETH_ALEN,
     990             :                          prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
     991             :                                         sizeof(buf1)));
     992             :         else {
     993           0 :                 family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
     994           0 :                 snprintf(str, size, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
     995           0 :                          p->prefix.route_type, p->prefix.macip_addr.eth_tag,
     996             :                          8 * ETH_ALEN,
     997             :                          prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
     998             :                                         sizeof(buf1)),
     999             :                          family == AF_INET ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
    1000           0 :                          inet_ntop(family, &p->prefix.macip_addr.ip.ip.addr,
    1001             :                                    buf2, PREFIX2STR_BUFFER));
    1002             :         }
    1003           0 :         return str;
    1004             : }
    1005             : 
    1006           0 : static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
    1007             :                                        int size)
    1008             : {
    1009           0 :         uint8_t family;
    1010           0 :         char buf[INET6_ADDRSTRLEN];
    1011             : 
    1012           0 :         family = IS_IPADDR_V4(&p->prefix.imet_addr.ip) ? AF_INET : AF_INET6;
    1013           0 :         snprintf(str, size, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
    1014           0 :                  p->prefix.imet_addr.eth_tag,
    1015             :                  (family == AF_INET) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
    1016           0 :                  inet_ntop(family, &p->prefix.imet_addr.ip.ipaddr_v4, buf,
    1017             :                            sizeof(buf)));
    1018             : 
    1019           0 :         return str;
    1020             : }
    1021             : 
    1022           0 : static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
    1023             :                                      int size)
    1024             : {
    1025           0 :         uint8_t family;
    1026           0 :         char buf[ESI_STR_LEN];
    1027           0 :         char buf1[INET6_ADDRSTRLEN];
    1028             : 
    1029           0 :         family = IS_IPADDR_V4(&p->prefix.es_addr.ip) ? AF_INET : AF_INET6;
    1030           0 :         snprintf(str, size, "[%d]:[%s]:[%d]:[%s]", p->prefix.route_type,
    1031             :                  esi_to_str(&p->prefix.es_addr.esi, buf, sizeof(buf)),
    1032             :                  (family == AF_INET) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
    1033           0 :                  inet_ntop(family, &p->prefix.es_addr.ip.ipaddr_v4, buf1,
    1034             :                            sizeof(buf1)));
    1035             : 
    1036           0 :         return str;
    1037             : }
    1038             : 
    1039           0 : static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
    1040             :                                          int size)
    1041             : {
    1042           0 :         uint8_t family;
    1043           0 :         char buf[INET6_ADDRSTRLEN];
    1044             : 
    1045           0 :         family = IS_IPADDR_V4(&p->prefix.prefix_addr.ip) ? AF_INET : AF_INET6;
    1046           0 :         snprintf(str, size, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
    1047           0 :                  p->prefix.prefix_addr.eth_tag,
    1048           0 :                  p->prefix.prefix_addr.ip_prefix_length,
    1049           0 :                  inet_ntop(family, &p->prefix.prefix_addr.ip.ipaddr_v4, buf,
    1050             :                            sizeof(buf)));
    1051           0 :         return str;
    1052             : }
    1053             : 
    1054           0 : static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
    1055             :                                   int size)
    1056             : {
    1057           0 :         switch (p->prefix.route_type) {
    1058           0 :         case BGP_EVPN_AD_ROUTE:
    1059           0 :                 return prefixevpn_ead2str(p, str, size);
    1060           0 :         case BGP_EVPN_MAC_IP_ROUTE:
    1061           0 :                 return prefixevpn_macip2str(p, str, size);
    1062           0 :         case BGP_EVPN_IMET_ROUTE:
    1063           0 :                 return prefixevpn_imet2str(p, str, size);
    1064           0 :         case BGP_EVPN_ES_ROUTE:
    1065           0 :                 return prefixevpn_es2str(p, str, size);
    1066           0 :         case BGP_EVPN_IP_PREFIX_ROUTE:
    1067           0 :                 return prefixevpn_prefix2str(p, str, size);
    1068           0 :         default:
    1069           0 :                 snprintf(str, size, "Unsupported EVPN prefix");
    1070           0 :                 break;
    1071             :         }
    1072           0 :         return str;
    1073             : }
    1074             : 
    1075         385 : const char *prefix2str(union prefixconstptr pu, char *str, int size)
    1076             : {
    1077         385 :         const struct prefix *p = pu.p;
    1078         385 :         char buf[PREFIX2STR_BUFFER];
    1079         385 :         int byte, tmp, a, b;
    1080         385 :         bool z = false;
    1081         385 :         size_t l;
    1082             : 
    1083         385 :         switch (p->family) {
    1084         385 :         case AF_INET:
    1085             :         case AF_INET6:
    1086         385 :                 inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
    1087         385 :                 l = strlen(buf);
    1088         385 :                 buf[l++] = '/';
    1089         385 :                 byte = p->prefixlen;
    1090         385 :                 tmp = p->prefixlen - 100;
    1091         385 :                 if (tmp >= 0) {
    1092          52 :                         buf[l++] = '1';
    1093          52 :                         z = true;
    1094          52 :                         byte = tmp;
    1095             :                 }
    1096         385 :                 b = byte % 10;
    1097         385 :                 a = byte / 10;
    1098         385 :                 if (a || z)
    1099         385 :                         buf[l++] = '0' + a;
    1100         385 :                 buf[l++] = '0' + b;
    1101         385 :                 buf[l] = '\0';
    1102         385 :                 strlcpy(str, buf, size);
    1103         385 :                 break;
    1104             : 
    1105           0 :         case AF_ETHERNET:
    1106           0 :                 snprintf(str, size, "%s/%d",
    1107             :                          prefix_mac2str(&p->u.prefix_eth, buf, sizeof(buf)),
    1108           0 :                          p->prefixlen);
    1109           0 :                 break;
    1110             : 
    1111           0 :         case AF_EVPN:
    1112           0 :                 prefixevpn2str((const struct prefix_evpn *)p, str, size);
    1113           0 :                 break;
    1114             : 
    1115           0 :         case AF_FLOWSPEC:
    1116           0 :                 strlcpy(str, "FS prefix", size);
    1117           0 :                 break;
    1118             : 
    1119           0 :         default:
    1120           0 :                 strlcpy(str, "UNK prefix", size);
    1121           0 :                 break;
    1122             :         }
    1123             : 
    1124         385 :         return str;
    1125             : }
    1126             : 
    1127           0 : static ssize_t prefixhost2str(struct fbuf *fbuf, union prefixconstptr pu)
    1128             : {
    1129           0 :         const struct prefix *p = pu.p;
    1130           0 :         char buf[PREFIX2STR_BUFFER];
    1131             : 
    1132           0 :         switch (p->family) {
    1133           0 :         case AF_INET:
    1134             :         case AF_INET6:
    1135           0 :                 inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
    1136           0 :                 return bputs(fbuf, buf);
    1137             : 
    1138           0 :         case AF_ETHERNET:
    1139           0 :                 prefix_mac2str(&p->u.prefix_eth, buf, sizeof(buf));
    1140           0 :                 return bputs(fbuf, buf);
    1141             : 
    1142           0 :         default:
    1143           0 :                 return bprintfrr(fbuf, "{prefix.af=%dPF}", p->family);
    1144             :         }
    1145             : }
    1146             : 
    1147           0 : void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
    1148             :                 char *buf, int buf_size)
    1149             : {
    1150           0 :         int save_errno = errno;
    1151             : 
    1152           0 :         if (addr.s_addr == INADDR_ANY)
    1153           0 :                 strlcpy(buf, "*", buf_size);
    1154             :         else {
    1155           0 :                 if (!inet_ntop(AF_INET, &addr, buf, buf_size)) {
    1156           0 :                         if (onfail)
    1157           0 :                                 snprintf(buf, buf_size, "%s", onfail);
    1158             :                 }
    1159             :         }
    1160             : 
    1161           0 :         errno = save_errno;
    1162           0 : }
    1163             : 
    1164           0 : const char *prefix_sg2str(const struct prefix_sg *sg, char *sg_str)
    1165             : {
    1166           0 :         char src_str[INET_ADDRSTRLEN];
    1167           0 :         char grp_str[INET_ADDRSTRLEN];
    1168             : 
    1169           0 :         prefix_mcast_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str));
    1170           0 :         prefix_mcast_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str));
    1171           0 :         snprintf(sg_str, PREFIX_SG_STR_LEN, "(%s,%s)", src_str, grp_str);
    1172             : 
    1173           0 :         return sg_str;
    1174             : }
    1175             : 
    1176          40 : struct prefix *prefix_new(void)
    1177             : {
    1178          40 :         struct prefix *p;
    1179             : 
    1180          40 :         p = XCALLOC(MTYPE_PREFIX, sizeof(*p));
    1181          40 :         return p;
    1182             : }
    1183             : 
    1184           0 : void prefix_free_lists(void *arg)
    1185             : {
    1186           0 :         struct prefix *p = arg;
    1187             : 
    1188           0 :         prefix_free(&p);
    1189           0 : }
    1190             : 
    1191             : /* Free prefix structure. */
    1192          80 : void prefix_free(struct prefix **p)
    1193             : {
    1194          80 :         XFREE(MTYPE_PREFIX, *p);
    1195          80 : }
    1196             : 
    1197             : /* Utility function to convert ipv4 prefixes to Classful prefixes */
    1198           0 : void apply_classful_mask_ipv4(struct prefix_ipv4 *p)
    1199             : {
    1200             : 
    1201           0 :         uint32_t destination;
    1202             : 
    1203           0 :         destination = ntohl(p->prefix.s_addr);
    1204             : 
    1205           0 :         if (p->prefixlen == IPV4_MAX_BITLEN)
    1206             :                 ;
    1207             :         /* do nothing for host routes */
    1208           0 :         else if (IN_CLASSC(destination)) {
    1209           0 :                 p->prefixlen = 24;
    1210           0 :                 apply_mask_ipv4(p);
    1211           0 :         } else if (IN_CLASSB(destination)) {
    1212           0 :                 p->prefixlen = 16;
    1213           0 :                 apply_mask_ipv4(p);
    1214             :         } else {
    1215           0 :                 p->prefixlen = 8;
    1216           0 :                 apply_mask_ipv4(p);
    1217             :         }
    1218           0 : }
    1219             : 
    1220           0 : in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
    1221             : {
    1222           0 :         struct in_addr mask;
    1223             : 
    1224           0 :         masklen2ip(masklen, &mask);
    1225           0 :         return (masklen != IPV4_MAX_BITLEN - 1)
    1226             :                        ?
    1227             :                        /* normal case */
    1228           0 :                        (hostaddr | ~mask.s_addr)
    1229           0 :                        :
    1230             :                        /* For prefix 31 return 255.255.255.255 (RFC3021) */
    1231             :                        htonl(0xFFFFFFFF);
    1232             : }
    1233             : 
    1234             : /* Utility function to convert ipv4 netmask to prefixes
    1235             :    ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
    1236             :    ex.) "1.0.0.0" NULL => "1.0.0.0/8"                   */
    1237           0 : int netmask_str2prefix_str(const char *net_str, const char *mask_str,
    1238             :                            char *prefix_str, size_t prefix_str_len)
    1239             : {
    1240           0 :         struct in_addr network;
    1241           0 :         struct in_addr mask;
    1242           0 :         uint8_t prefixlen;
    1243           0 :         uint32_t destination;
    1244           0 :         int ret;
    1245             : 
    1246           0 :         ret = inet_aton(net_str, &network);
    1247           0 :         if (!ret)
    1248             :                 return 0;
    1249             : 
    1250           0 :         if (mask_str) {
    1251           0 :                 ret = inet_aton(mask_str, &mask);
    1252           0 :                 if (!ret)
    1253             :                         return 0;
    1254             : 
    1255           0 :                 prefixlen = ip_masklen(mask);
    1256             :         } else {
    1257           0 :                 destination = ntohl(network.s_addr);
    1258             : 
    1259           0 :                 if (network.s_addr == INADDR_ANY)
    1260             :                         prefixlen = 0;
    1261           0 :                 else if (IN_CLASSC(destination))
    1262             :                         prefixlen = 24;
    1263           0 :                 else if (IN_CLASSB(destination))
    1264             :                         prefixlen = 16;
    1265           0 :                 else if (IN_CLASSA(destination))
    1266             :                         prefixlen = 8;
    1267             :                 else
    1268             :                         return 0;
    1269             :         }
    1270             : 
    1271           0 :         snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
    1272             : 
    1273           0 :         return 1;
    1274             : }
    1275             : 
    1276             : /* converts to internal representation of mac address
    1277             :  * returns 1 on success, 0 otherwise
    1278             :  * format accepted: AA:BB:CC:DD:EE:FF
    1279             :  * if mac parameter is null, then check only
    1280             :  */
    1281           0 : int prefix_str2mac(const char *str, struct ethaddr *mac)
    1282             : {
    1283           0 :         unsigned int a[6];
    1284           0 :         int i;
    1285             : 
    1286           0 :         if (!str)
    1287             :                 return 0;
    1288             : 
    1289           0 :         if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3,
    1290             :                    a + 4, a + 5)
    1291             :             != 6) {
    1292             :                 /* error in incoming str length */
    1293             :                 return 0;
    1294             :         }
    1295             :         /* valid mac address */
    1296           0 :         if (!mac)
    1297             :                 return 1;
    1298           0 :         for (i = 0; i < 6; ++i)
    1299           0 :                 mac->octet[i] = a[i] & 0xff;
    1300             :         return 1;
    1301             : }
    1302             : 
    1303           0 : char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
    1304             : {
    1305           0 :         char *ptr;
    1306             : 
    1307           0 :         if (!mac)
    1308             :                 return NULL;
    1309           0 :         if (!buf)
    1310           0 :                 ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
    1311             :         else {
    1312           0 :                 assert(size >= ETHER_ADDR_STRLEN);
    1313             :                 ptr = buf;
    1314             :         }
    1315           0 :         snprintf(ptr, (ETHER_ADDR_STRLEN), "%02x:%02x:%02x:%02x:%02x:%02x",
    1316           0 :                  (uint8_t)mac->octet[0], (uint8_t)mac->octet[1],
    1317           0 :                  (uint8_t)mac->octet[2], (uint8_t)mac->octet[3],
    1318           0 :                  (uint8_t)mac->octet[4], (uint8_t)mac->octet[5]);
    1319           0 :         return ptr;
    1320             : }
    1321             : 
    1322         499 : unsigned prefix_hash_key(const void *pp)
    1323             : {
    1324         499 :         struct prefix copy;
    1325             : 
    1326         499 :         if (((struct prefix *)pp)->family == AF_FLOWSPEC) {
    1327           0 :                 uint32_t len;
    1328           0 :                 void *temp;
    1329             : 
    1330             :                 /* make sure *all* unused bits are zero,
    1331             :                  * particularly including alignment /
    1332             :                  * padding and unused prefix bytes.
    1333             :                  */
    1334           0 :                 memset(&copy, 0, sizeof(copy));
    1335           0 :                 prefix_copy(&copy, (struct prefix *)pp);
    1336           0 :                 len = jhash((void *)copy.u.prefix_flowspec.ptr,
    1337           0 :                             copy.u.prefix_flowspec.prefixlen,
    1338             :                             0x55aa5a5a);
    1339           0 :                 temp = (void *)copy.u.prefix_flowspec.ptr;
    1340           0 :                 XFREE(MTYPE_PREFIX_FLOWSPEC, temp);
    1341           0 :                 copy.u.prefix_flowspec.ptr = (uintptr_t)NULL;
    1342           0 :                 return len;
    1343             :         }
    1344             :         /* make sure *all* unused bits are zero, particularly including
    1345             :          * alignment /
    1346             :          * padding and unused prefix bytes. */
    1347         499 :         memset(&copy, 0, sizeof(copy));
    1348         499 :         prefix_copy(&copy, (struct prefix *)pp);
    1349         499 :         return jhash(&copy,
    1350         499 :                      offsetof(struct prefix, u.prefix) + PSIZE(copy.prefixlen),
    1351             :                      0x55aa5a5a);
    1352             : }
    1353             : 
    1354             : /* converts to internal representation of esi
    1355             :  * returns 1 on success, 0 otherwise
    1356             :  * format accepted: aa:aa:aa:aa:aa:aa:aa:aa:aa:aa
    1357             :  * if esi parameter is null, then check only
    1358             :  */
    1359           0 : int str_to_esi(const char *str, esi_t *esi)
    1360             : {
    1361           0 :         int i;
    1362           0 :         unsigned int a[ESI_BYTES];
    1363             : 
    1364           0 :         if (!str)
    1365             :                 return 0;
    1366             : 
    1367           0 :         if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x",
    1368             :                    a + 0, a + 1, a + 2, a + 3,
    1369             :                    a + 4, a + 5, a + 6, a + 7,
    1370             :                    a + 8, a + 9)
    1371             :             != ESI_BYTES) {
    1372             :                 /* error in incoming str length */
    1373             :                 return 0;
    1374             :         }
    1375             : 
    1376             :         /* valid ESI */
    1377           0 :         if (!esi)
    1378             :                 return 1;
    1379           0 :         for (i = 0; i < ESI_BYTES; ++i)
    1380           0 :                 esi->val[i] = a[i] & 0xff;
    1381             :         return 1;
    1382             : }
    1383             : 
    1384           0 : char *esi_to_str(const esi_t *esi, char *buf, int size)
    1385             : {
    1386           0 :         char *ptr;
    1387             : 
    1388           0 :         if (!esi)
    1389             :                 return NULL;
    1390           0 :         if (!buf)
    1391           0 :                 ptr = XMALLOC(MTYPE_TMP, ESI_STR_LEN * sizeof(char));
    1392             :         else {
    1393           0 :                 assert(size >= ESI_STR_LEN);
    1394             :                 ptr = buf;
    1395             :         }
    1396             : 
    1397           0 :         snprintf(ptr, ESI_STR_LEN,
    1398             :                  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
    1399           0 :                  esi->val[0], esi->val[1], esi->val[2],
    1400           0 :                  esi->val[3], esi->val[4], esi->val[5],
    1401           0 :                  esi->val[6], esi->val[7], esi->val[8],
    1402           0 :                  esi->val[9]);
    1403           0 :         return ptr;
    1404             : }
    1405             : 
    1406           0 : char *evpn_es_df_alg2str(uint8_t df_alg, char *buf, int buf_len)
    1407             : {
    1408           0 :         switch (df_alg) {
    1409           0 :         case EVPN_MH_DF_ALG_SERVICE_CARVING:
    1410           0 :                 snprintf(buf, buf_len, "service-carving");
    1411           0 :                 break;
    1412             : 
    1413           0 :         case EVPN_MH_DF_ALG_HRW:
    1414           0 :                 snprintf(buf, buf_len, "HRW");
    1415           0 :                 break;
    1416             : 
    1417           0 :         case EVPN_MH_DF_ALG_PREF:
    1418           0 :                 snprintf(buf, buf_len, "preference");
    1419           0 :                 break;
    1420             : 
    1421           0 :         default:
    1422           0 :                 snprintf(buf, buf_len, "unknown %u", df_alg);
    1423           0 :                 break;
    1424             :         }
    1425             : 
    1426           0 :         return buf;
    1427             : }
    1428             : 
    1429           6 : bool ipv4_unicast_valid(const struct in_addr *addr)
    1430             : {
    1431           6 :         in_addr_t ip = ntohl(addr->s_addr);
    1432             : 
    1433           6 :         if (IPV4_CLASS_D(ip))
    1434             :                 return false;
    1435             : 
    1436           6 :         if (IPV4_NET0(ip) || IPV4_NET127(ip) || IPV4_CLASS_E(ip)) {
    1437           2 :                 if (cmd_allow_reserved_ranges_get())
    1438             :                         return true;
    1439             :                 else
    1440             :                         return false;
    1441             :         }
    1442             : 
    1443             :         return true;
    1444             : }
    1445             : 
    1446           0 : static int ipaddr2prefix(const struct ipaddr *ip, uint16_t prefixlen,
    1447             :                          struct prefix *p)
    1448             : {
    1449           0 :         switch (ip->ipa_type) {
    1450           0 :         case (IPADDR_V4):
    1451           0 :                 p->family = AF_INET;
    1452           0 :                 p->u.prefix4 = ip->ipaddr_v4;
    1453           0 :                 p->prefixlen = prefixlen;
    1454           0 :                 break;
    1455           0 :         case (IPADDR_V6):
    1456           0 :                 p->family = AF_INET6;
    1457           0 :                 p->u.prefix6 = ip->ipaddr_v6;
    1458           0 :                 p->prefixlen = prefixlen;
    1459           0 :                 break;
    1460           0 :         case (IPADDR_NONE):
    1461           0 :                 p->family = AF_UNSPEC;
    1462           0 :                 break;
    1463             :         }
    1464             : 
    1465           0 :         return 0;
    1466             : }
    1467             : 
    1468             : /*
    1469             :  * Convert type-2 and type-5 evpn route prefixes into the more
    1470             :  * general ipv4/ipv6 prefix types so we can match prefix lists
    1471             :  * and such.
    1472             :  */
    1473           0 : int evpn_prefix2prefix(const struct prefix *evpn, struct prefix *to)
    1474             : {
    1475           0 :         const struct evpn_addr *addr;
    1476             : 
    1477           0 :         if (evpn->family != AF_EVPN)
    1478             :                 return -1;
    1479             : 
    1480           0 :         addr = &evpn->u.prefix_evpn;
    1481             : 
    1482           0 :         switch (addr->route_type) {
    1483           0 :         case BGP_EVPN_MAC_IP_ROUTE:
    1484           0 :                 if (IS_IPADDR_V4(&addr->macip_addr.ip))
    1485           0 :                         ipaddr2prefix(&addr->macip_addr.ip, IPV4_MAX_BITLEN,
    1486             :                                       to);
    1487           0 :                 else if (IS_IPADDR_V6(&addr->macip_addr.ip))
    1488           0 :                         ipaddr2prefix(&addr->macip_addr.ip, IPV6_MAX_BITLEN,
    1489             :                                       to);
    1490             :                 else
    1491             :                         return -1; /* mac only? */
    1492             : 
    1493             :                 break;
    1494           0 :         case BGP_EVPN_IP_PREFIX_ROUTE:
    1495           0 :                 ipaddr2prefix(&addr->prefix_addr.ip,
    1496           0 :                               addr->prefix_addr.ip_prefix_length, to);
    1497           0 :                 break;
    1498             :         default:
    1499             :                 return -1;
    1500             :         }
    1501             : 
    1502             :         return 0;
    1503             : }
    1504             : 
    1505           4 : printfrr_ext_autoreg_p("EA", printfrr_ea);
    1506           0 : static ssize_t printfrr_ea(struct fbuf *buf, struct printfrr_eargs *ea,
    1507             :                            const void *ptr)
    1508             : {
    1509           0 :         const struct ethaddr *mac = ptr;
    1510           0 :         char cbuf[ETHER_ADDR_STRLEN];
    1511             : 
    1512           0 :         if (!mac)
    1513           0 :                 return bputs(buf, "(null)");
    1514             : 
    1515             :         /* need real length even if buffer is too short */
    1516           0 :         prefix_mac2str(mac, cbuf, sizeof(cbuf));
    1517           0 :         return bputs(buf, cbuf);
    1518             : }
    1519             : 
    1520           4 : printfrr_ext_autoreg_p("IA", printfrr_ia);
    1521           0 : static ssize_t printfrr_ia(struct fbuf *buf, struct printfrr_eargs *ea,
    1522             :                            const void *ptr)
    1523             : {
    1524           0 :         const struct ipaddr *ipa = ptr;
    1525           0 :         char cbuf[INET6_ADDRSTRLEN];
    1526           0 :         bool use_star = false;
    1527             : 
    1528           0 :         if (ea->fmt[0] == 's') {
    1529           0 :                 use_star = true;
    1530           0 :                 ea->fmt++;
    1531             :         }
    1532             : 
    1533           0 :         if (!ipa || !ipa->ipa_type)
    1534           0 :                 return bputs(buf, "(null)");
    1535             : 
    1536           0 :         if (use_star) {
    1537           0 :                 struct in_addr zero4 = {};
    1538           0 :                 struct in6_addr zero6 = {};
    1539             : 
    1540           0 :                 switch (ipa->ipa_type) {
    1541           0 :                 case IPADDR_V4:
    1542           0 :                         if (!memcmp(&ipa->ip.addr, &zero4, sizeof(zero4)))
    1543           0 :                                 return bputch(buf, '*');
    1544             :                         break;
    1545             : 
    1546           0 :                 case IPADDR_V6:
    1547           0 :                         if (!memcmp(&ipa->ip.addr, &zero6, sizeof(zero6)))
    1548           0 :                                 return bputch(buf, '*');
    1549             :                         break;
    1550             : 
    1551             :                 case IPADDR_NONE:
    1552             :                         break;
    1553             :                 }
    1554             :         }
    1555             : 
    1556           0 :         ipaddr2str(ipa, cbuf, sizeof(cbuf));
    1557           0 :         return bputs(buf, cbuf);
    1558             : }
    1559             : 
    1560           4 : printfrr_ext_autoreg_p("I4", printfrr_i4);
    1561          36 : static ssize_t printfrr_i4(struct fbuf *buf, struct printfrr_eargs *ea,
    1562             :                            const void *ptr)
    1563             : {
    1564          36 :         char cbuf[INET_ADDRSTRLEN];
    1565          36 :         bool use_star = false;
    1566          36 :         struct in_addr zero = {};
    1567             : 
    1568          36 :         if (ea->fmt[0] == 's') {
    1569           0 :                 use_star = true;
    1570           0 :                 ea->fmt++;
    1571             :         }
    1572             : 
    1573          36 :         if (!ptr)
    1574           0 :                 return bputs(buf, "(null)");
    1575             : 
    1576          36 :         if (use_star && !memcmp(ptr, &zero, sizeof(zero)))
    1577           0 :                 return bputch(buf, '*');
    1578             : 
    1579          36 :         inet_ntop(AF_INET, ptr, cbuf, sizeof(cbuf));
    1580          36 :         return bputs(buf, cbuf);
    1581             : }
    1582             : 
    1583           4 : printfrr_ext_autoreg_p("I6", printfrr_i6);
    1584          58 : static ssize_t printfrr_i6(struct fbuf *buf, struct printfrr_eargs *ea,
    1585             :                            const void *ptr)
    1586             : {
    1587          58 :         char cbuf[INET6_ADDRSTRLEN];
    1588          58 :         bool use_star = false;
    1589          58 :         struct in6_addr zero = {};
    1590             : 
    1591          58 :         if (ea->fmt[0] == 's') {
    1592           0 :                 use_star = true;
    1593           0 :                 ea->fmt++;
    1594             :         }
    1595             : 
    1596          58 :         if (!ptr)
    1597           0 :                 return bputs(buf, "(null)");
    1598             : 
    1599          58 :         if (use_star && !memcmp(ptr, &zero, sizeof(zero)))
    1600           0 :                 return bputch(buf, '*');
    1601             : 
    1602          58 :         inet_ntop(AF_INET6, ptr, cbuf, sizeof(cbuf));
    1603          58 :         return bputs(buf, cbuf);
    1604             : }
    1605             : 
    1606           4 : printfrr_ext_autoreg_p("FX", printfrr_pfx);
    1607         120 : static ssize_t printfrr_pfx(struct fbuf *buf, struct printfrr_eargs *ea,
    1608             :                             const void *ptr)
    1609             : {
    1610         120 :         bool host_only = false;
    1611             : 
    1612         120 :         if (ea->fmt[0] == 'h') {
    1613           0 :                 ea->fmt++;
    1614           0 :                 host_only = true;
    1615             :         }
    1616             : 
    1617         120 :         if (!ptr)
    1618           0 :                 return bputs(buf, "(null)");
    1619             : 
    1620         120 :         if (host_only)
    1621           0 :                 return prefixhost2str(buf, (struct prefix *)ptr);
    1622             :         else {
    1623         120 :                 char cbuf[PREFIX_STRLEN];
    1624             : 
    1625         120 :                 prefix2str(ptr, cbuf, sizeof(cbuf));
    1626         120 :                 return bputs(buf, cbuf);
    1627             :         }
    1628             : }
    1629             : 
    1630           4 : printfrr_ext_autoreg_p("PSG4", printfrr_psg);
    1631           0 : static ssize_t printfrr_psg(struct fbuf *buf, struct printfrr_eargs *ea,
    1632             :                             const void *ptr)
    1633             : {
    1634           0 :         const struct prefix_sg *sg = ptr;
    1635           0 :         ssize_t ret = 0;
    1636             : 
    1637           0 :         if (!sg)
    1638           0 :                 return bputs(buf, "(null)");
    1639             : 
    1640           0 :         if (sg->src.s_addr == INADDR_ANY)
    1641           0 :                 ret += bputs(buf, "(*,");
    1642             :         else
    1643           0 :                 ret += bprintfrr(buf, "(%pI4,", &sg->src);
    1644             : 
    1645           0 :         if (sg->grp.s_addr == INADDR_ANY)
    1646           0 :                 ret += bputs(buf, "*)");
    1647             :         else
    1648           0 :                 ret += bprintfrr(buf, "%pI4)", &sg->grp);
    1649             : 
    1650             :         return ret;
    1651             : }

Generated by: LCOV version v1.16-topotato