back to topotato report
topotato coverage report
Current view: top level - lib - prefix.c (source / functions) Hit Total Coverage
Test: test_bgp_disable_addpath_rx.py::BGPDisableAddpathRx Lines: 219 812 27.0 %
Date: 2023-02-24 18:37:08 Functions: 35 78 44.9 %

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

Generated by: LCOV version v1.16-topotato