2 * Prefix related functions.
3 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
28 #include "sockunion.h"
32 #include "lib_errors.h"
36 DEFINE_MTYPE_STATIC(LIB
, PREFIX
, "Prefix");
37 DEFINE_MTYPE_STATIC(LIB
, PREFIX_FLOWSPEC
, "Prefix Flowspec");
40 static const uint8_t maskbit
[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
41 0xf8, 0xfc, 0xfe, 0xff};
43 /* Number of bits in prefix type. */
48 #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
50 int is_zero_mac(const struct ethaddr
*mac
)
54 for (i
= 0; i
< ETH_ALEN
; i
++) {
62 bool is_bcast_mac(const struct ethaddr
*mac
)
66 for (i
= 0; i
< ETH_ALEN
; i
++)
67 if (mac
->octet
[i
] != 0xFF)
73 bool is_mcast_mac(const struct ethaddr
*mac
)
75 if ((mac
->octet
[0] & 0x01) == 0x01)
81 unsigned int prefix_bit(const uint8_t *prefix
, const uint16_t bit_index
)
83 unsigned int offset
= bit_index
/ 8;
84 unsigned int shift
= 7 - (bit_index
% 8);
86 return (prefix
[offset
] >> shift
) & 1;
89 int str2family(const char *string
)
91 if (!strcmp("ipv4", string
))
93 else if (!strcmp("ipv6", string
))
95 else if (!strcmp("ethernet", string
))
97 else if (!strcmp("evpn", string
))
102 const char *family2str(int family
)
117 /* Address Family Identifier to Address Family converter. */
118 int afi2family(afi_t afi
)
122 else if (afi
== AFI_IP6
)
124 else if (afi
== AFI_L2VPN
)
126 /* NOTE: EVPN code should NOT use this interface. */
130 afi_t
family2afi(int family
)
132 if (family
== AF_INET
)
134 else if (family
== AF_INET6
)
136 else if (family
== AF_ETHERNET
|| family
== AF_EVPN
)
141 const char *afi2str(afi_t afi
)
158 const char *safi2str(safi_t safi
)
171 case SAFI_LABELED_UNICAST
:
172 return "labeled-unicast";
180 /* If n includes p prefix then return 1 else return 0. */
181 int prefix_match(union prefixconstptr unet
, union prefixconstptr upfx
)
183 const struct prefix
*n
= unet
.p
;
184 const struct prefix
*p
= upfx
.p
;
187 const uint8_t *np
, *pp
;
189 /* If n's prefix is longer than p's one return 0. */
190 if (n
->prefixlen
> p
->prefixlen
)
193 if (n
->family
== AF_FLOWSPEC
) {
194 /* prefixlen is unused. look at fs prefix len */
195 if (n
->u
.prefix_flowspec
.family
!=
196 p
->u
.prefix_flowspec
.family
)
199 if (n
->u
.prefix_flowspec
.prefixlen
>
200 p
->u
.prefix_flowspec
.prefixlen
)
203 /* Set both prefix's head pointer. */
204 np
= (const uint8_t *)&n
->u
.prefix_flowspec
.ptr
;
205 pp
= (const uint8_t *)&p
->u
.prefix_flowspec
.ptr
;
207 offset
= n
->u
.prefix_flowspec
.prefixlen
;
210 if (np
[offset
] != pp
[offset
])
215 /* Set both prefix's head pointer. */
219 offset
= n
->prefixlen
/ PNBBY
;
220 shift
= n
->prefixlen
% PNBBY
;
223 if (maskbit
[shift
] & (np
[offset
] ^ pp
[offset
]))
227 if (np
[offset
] != pp
[offset
])
234 * n is a type5 evpn prefix. This function tries to see if there is an
235 * ip-prefix within n which matches prefix p
236 * If n includes p prefix then return 1 else return 0.
238 int evpn_type5_prefix_match(const struct prefix
*n
, const struct prefix
*p
)
243 const uint8_t *np
, *pp
;
244 struct prefix_evpn
*evp
;
246 if (n
->family
!= AF_EVPN
)
249 evp
= (struct prefix_evpn
*)n
;
252 if ((evp
->prefix
.route_type
!= 5) ||
253 (p
->family
== AF_INET6
&& !is_evpn_prefix_ipaddr_v6(evp
)) ||
254 (p
->family
== AF_INET
&& !is_evpn_prefix_ipaddr_v4(evp
)) ||
255 (is_evpn_prefix_ipaddr_none(evp
)))
258 prefixlen
= evp
->prefix
.prefix_addr
.ip_prefix_length
;
259 np
= &evp
->prefix
.prefix_addr
.ip
.ip
.addr
;
261 /* If n's prefix is longer than p's one return 0. */
262 if (prefixlen
> p
->prefixlen
)
265 offset
= prefixlen
/ PNBBY
;
266 shift
= prefixlen
% PNBBY
;
269 if (maskbit
[shift
] & (np
[offset
] ^ pp
[offset
]))
273 if (np
[offset
] != pp
[offset
])
279 /* If n includes p then return 1 else return 0. Prefix mask is not considered */
280 int prefix_match_network_statement(union prefixconstptr unet
,
281 union prefixconstptr upfx
)
283 const struct prefix
*n
= unet
.p
;
284 const struct prefix
*p
= upfx
.p
;
287 const uint8_t *np
, *pp
;
289 /* Set both prefix's head pointer. */
293 offset
= n
->prefixlen
/ PNBBY
;
294 shift
= n
->prefixlen
% PNBBY
;
297 if (maskbit
[shift
] & (np
[offset
] ^ pp
[offset
]))
301 if (np
[offset
] != pp
[offset
])
306 #ifdef __clang_analyzer__
307 #undef prefix_copy /* cf. prefix.h */
310 void prefix_copy(union prefixptr udest
, union prefixconstptr usrc
)
312 struct prefix
*dest
= udest
.p
;
313 const struct prefix
*src
= usrc
.p
;
315 dest
->family
= src
->family
;
316 dest
->prefixlen
= src
->prefixlen
;
318 if (src
->family
== AF_INET
)
319 dest
->u
.prefix4
= src
->u
.prefix4
;
320 else if (src
->family
== AF_INET6
)
321 dest
->u
.prefix6
= src
->u
.prefix6
;
322 else if (src
->family
== AF_ETHERNET
) {
323 memcpy(&dest
->u
.prefix_eth
, &src
->u
.prefix_eth
,
324 sizeof(struct ethaddr
));
325 } else if (src
->family
== AF_EVPN
) {
326 memcpy(&dest
->u
.prefix_evpn
, &src
->u
.prefix_evpn
,
327 sizeof(struct evpn_addr
));
328 } else if (src
->family
== AF_UNSPEC
) {
329 dest
->u
.lp
.id
= src
->u
.lp
.id
;
330 dest
->u
.lp
.adv_router
= src
->u
.lp
.adv_router
;
331 } else if (src
->family
== AF_FLOWSPEC
) {
335 len
= src
->u
.prefix_flowspec
.prefixlen
;
336 dest
->u
.prefix_flowspec
.prefixlen
=
337 src
->u
.prefix_flowspec
.prefixlen
;
338 dest
->u
.prefix_flowspec
.family
=
339 src
->u
.prefix_flowspec
.family
;
340 dest
->family
= src
->family
;
341 temp
= XCALLOC(MTYPE_PREFIX_FLOWSPEC
, len
);
342 dest
->u
.prefix_flowspec
.ptr
= (uintptr_t)temp
;
343 memcpy((void *)dest
->u
.prefix_flowspec
.ptr
,
344 (void *)src
->u
.prefix_flowspec
.ptr
, len
);
346 flog_err(EC_LIB_DEVELOPMENT
,
347 "prefix_copy(): Unknown address family %d",
354 * Return 1 if the address/netmask contained in the prefix structure
355 * is the same, and else return 0. For this routine, 'same' requires
356 * that not only the prefix length and the network part be the same,
357 * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
358 * the same. Note that this routine has the same return value sense
359 * as '==' (which is different from prefix_cmp).
361 int prefix_same(union prefixconstptr up1
, union prefixconstptr up2
)
363 const struct prefix
*p1
= up1
.p
;
364 const struct prefix
*p2
= up2
.p
;
366 if ((p1
&& !p2
) || (!p1
&& p2
))
372 if (p1
->family
== p2
->family
&& p1
->prefixlen
== p2
->prefixlen
) {
373 if (p1
->family
== AF_INET
)
374 if (IPV4_ADDR_SAME(&p1
->u
.prefix4
, &p2
->u
.prefix4
))
376 if (p1
->family
== AF_INET6
)
377 if (IPV6_ADDR_SAME(&p1
->u
.prefix6
.s6_addr
,
378 &p2
->u
.prefix6
.s6_addr
))
380 if (p1
->family
== AF_ETHERNET
)
381 if (!memcmp(&p1
->u
.prefix_eth
, &p2
->u
.prefix_eth
,
382 sizeof(struct ethaddr
)))
384 if (p1
->family
== AF_EVPN
)
385 if (!memcmp(&p1
->u
.prefix_evpn
, &p2
->u
.prefix_evpn
,
386 sizeof(struct evpn_addr
)))
388 if (p1
->family
== AF_FLOWSPEC
) {
389 if (p1
->u
.prefix_flowspec
.family
!=
390 p2
->u
.prefix_flowspec
.family
)
392 if (p1
->u
.prefix_flowspec
.prefixlen
!=
393 p2
->u
.prefix_flowspec
.prefixlen
)
395 if (!memcmp(&p1
->u
.prefix_flowspec
.ptr
,
396 &p2
->u
.prefix_flowspec
.ptr
,
397 p2
->u
.prefix_flowspec
.prefixlen
))
405 * Return -1/0/1 comparing the prefixes in a way that gives a full/linear
408 * Network prefixes are considered the same if the prefix lengths are equal
409 * and the network parts are the same. Host bits (which are considered masked
410 * by the prefix length) are not significant. Thus, 10.0.0.1/8 and
411 * 10.0.0.2/8 are considered equivalent by this routine. Note that
412 * this routine has the same return sense as strcmp (which is different
415 int prefix_cmp(union prefixconstptr up1
, union prefixconstptr up2
)
417 const struct prefix
*p1
= up1
.p
;
418 const struct prefix
*p2
= up2
.p
;
423 /* Set both prefix's head pointer. */
427 if (p1
->family
!= p2
->family
)
428 return numcmp(p1
->family
, p2
->family
);
429 if (p1
->family
== AF_FLOWSPEC
) {
430 pp1
= (const uint8_t *)p1
->u
.prefix_flowspec
.ptr
;
431 pp2
= (const uint8_t *)p2
->u
.prefix_flowspec
.ptr
;
433 if (p1
->u
.prefix_flowspec
.family
!=
434 p2
->u
.prefix_flowspec
.family
)
437 if (p1
->u
.prefix_flowspec
.prefixlen
!=
438 p2
->u
.prefix_flowspec
.prefixlen
)
439 return numcmp(p1
->u
.prefix_flowspec
.prefixlen
,
440 p2
->u
.prefix_flowspec
.prefixlen
);
442 offset
= p1
->u
.prefix_flowspec
.prefixlen
;
444 if (pp1
[offset
] != pp2
[offset
])
445 return numcmp(pp1
[offset
], pp2
[offset
]);
451 if (p1
->prefixlen
!= p2
->prefixlen
)
452 return numcmp(p1
->prefixlen
, p2
->prefixlen
);
453 offset
= p1
->prefixlen
/ PNBBY
;
454 shift
= p1
->prefixlen
% PNBBY
;
456 i
= memcmp(pp1
, pp2
, offset
);
461 * At this point offset was the same, if we have shift
462 * that means we still have data to compare, if shift is
463 * 0 then we are at the end of the data structure
464 * and should just return, as that we will be accessing
465 * memory beyond the end of the party zone
468 return numcmp(pp1
[offset
] & maskbit
[shift
],
469 pp2
[offset
] & maskbit
[shift
]);
475 * Count the number of common bits in 2 prefixes. The prefix length is
476 * ignored for this function; the whole prefix is compared. If the prefix
477 * address families don't match, return -1; otherwise the return value is
478 * in range 0 ... maximum prefix length for the address family.
480 int prefix_common_bits(union prefixconstptr ua
, union prefixconstptr ub
)
482 const struct prefix
*p1
= ua
.p
;
483 const struct prefix
*p2
= ub
.p
;
488 /* Set both prefix's head pointer. */
489 const uint8_t *pp1
= p1
->u
.val
;
490 const uint8_t *pp2
= p2
->u
.val
;
492 if (p1
->family
== AF_INET
)
493 length
= IPV4_MAX_BYTELEN
;
494 if (p1
->family
== AF_INET6
)
495 length
= IPV6_MAX_BYTELEN
;
496 if (p1
->family
== AF_ETHERNET
)
498 if (p1
->family
== AF_EVPN
)
499 length
= 8 * sizeof(struct evpn_addr
);
501 if (p1
->family
!= p2
->family
|| !length
)
504 for (pos
= 0; pos
< length
; pos
++)
505 if (pp1
[pos
] != pp2
[pos
])
510 xor = pp1
[pos
] ^ pp2
[pos
];
511 for (bit
= 0; bit
< 8; bit
++)
512 if (xor&(1 << (7 - bit
)))
515 return pos
* 8 + bit
;
518 /* Return prefix family type string. */
519 const char *prefix_family_str(union prefixconstptr pu
)
521 const struct prefix
*p
= pu
.p
;
523 if (p
->family
== AF_INET
)
525 if (p
->family
== AF_INET6
)
527 if (p
->family
== AF_ETHERNET
)
529 if (p
->family
== AF_EVPN
)
534 /* Allocate new prefix_ipv4 structure. */
535 struct prefix_ipv4
*prefix_ipv4_new(void)
537 struct prefix_ipv4
*p
;
539 /* Call prefix_new to allocate a full-size struct prefix to avoid
541 where the struct prefix_ipv4 is cast to struct prefix and unallocated
542 bytes were being referenced (e.g. in structure assignments). */
543 p
= (struct prefix_ipv4
*)prefix_new();
548 /* Free prefix_ipv4 structure. */
549 void prefix_ipv4_free(struct prefix_ipv4
**p
)
551 prefix_free((struct prefix
**)p
);
554 /* If given string is valid return 1 else return 0 */
555 int str2prefix_ipv4(const char *str
, struct prefix_ipv4
*p
)
562 /* Find slash inside string. */
563 pnt
= strchr(str
, '/');
565 /* String doesn't contail slash. */
567 /* Convert string to prefix. */
568 ret
= inet_pton(AF_INET
, str
, &p
->prefix
);
572 /* If address doesn't contain slash we assume it host address.
575 p
->prefixlen
= IPV4_MAX_BITLEN
;
579 cp
= XMALLOC(MTYPE_TMP
, (pnt
- str
) + 1);
580 memcpy(cp
, str
, pnt
- str
);
581 *(cp
+ (pnt
- str
)) = '\0';
582 ret
= inet_pton(AF_INET
, cp
, &p
->prefix
);
583 XFREE(MTYPE_TMP
, cp
);
587 /* Get prefix length. */
588 plen
= (uint8_t)atoi(++pnt
);
589 if (plen
> IPV4_MAX_BITLEN
)
599 /* When string format is invalid return 0. */
600 int str2prefix_eth(const char *str
, struct prefix_eth
*p
)
606 const char *str_addr
= str
;
611 if (!strcmp(str
, "any")) {
612 memset(p
, 0, sizeof(*p
));
613 p
->family
= AF_ETHERNET
;
617 /* Find slash inside string. */
618 pnt
= strchr(str
, '/');
621 /* Get prefix length. */
622 plen
= (uint8_t)atoi(++pnt
);
628 cp
= XMALLOC(MTYPE_TMP
, (pnt
- str
) + 1);
629 memcpy(cp
, str
, pnt
- str
);
630 *(cp
+ (pnt
- str
)) = '\0';
636 /* Convert string to prefix. */
637 if (sscanf(str_addr
, "%2x:%2x:%2x:%2x:%2x:%2x", a
+ 0, a
+ 1, a
+ 2,
643 for (i
= 0; i
< 6; ++i
) {
644 p
->eth_addr
.octet
[i
] = a
[i
] & 0xff;
647 p
->family
= AF_ETHERNET
;
650 * special case to allow old configurations to work
651 * Since all zero's is implicitly meant to allow
652 * a comparison to zero, let's assume
654 if (!slash
&& is_zero_mac(&(p
->eth_addr
)))
660 XFREE(MTYPE_TMP
, cp
);
665 /* Convert masklen into IP address's netmask (network byte order). */
666 void masklen2ip(const int masklen
, struct in_addr
*netmask
)
668 assert(masklen
>= 0 && masklen
<= IPV4_MAX_BITLEN
);
670 /* left shift is only defined for less than the size of the type.
671 * we unconditionally use long long in case the target platform
672 * has defined behaviour for << 32 (or has a 64-bit left shift) */
674 if (sizeof(unsigned long long) > 4)
675 netmask
->s_addr
= htonl(0xffffffffULL
<< (32 - masklen
));
678 htonl(masklen
? 0xffffffffU
<< (32 - masklen
) : 0);
681 /* Convert IP address's netmask into integer. We assume netmask is
682 * sequential one. Argument netmask should be network byte order. */
683 uint8_t ip_masklen(struct in_addr netmask
)
685 uint32_t tmp
= ~ntohl(netmask
.s_addr
);
688 * clz: count leading zeroes. sadly, the behaviour of this builtin is
689 * undefined for a 0 argument, even though most CPUs give 32
691 return tmp
? __builtin_clz(tmp
) : 32;
694 /* Apply mask to IPv4 prefix (network byte order). */
695 void apply_mask_ipv4(struct prefix_ipv4
*p
)
698 masklen2ip(p
->prefixlen
, &mask
);
699 p
->prefix
.s_addr
&= mask
.s_addr
;
702 /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
703 int prefix_ipv4_any(const struct prefix_ipv4
*p
)
705 return (p
->prefix
.s_addr
== INADDR_ANY
&& p
->prefixlen
== 0);
708 /* Allocate a new ip version 6 route */
709 struct prefix_ipv6
*prefix_ipv6_new(void)
711 struct prefix_ipv6
*p
;
713 /* Allocate a full-size struct prefix to avoid problems with structure
715 p
= (struct prefix_ipv6
*)prefix_new();
716 p
->family
= AF_INET6
;
720 /* Free prefix for IPv6. */
721 void prefix_ipv6_free(struct prefix_ipv6
**p
)
723 prefix_free((struct prefix
**)p
);
726 /* If given string is valid return 1 else return 0 */
727 int str2prefix_ipv6(const char *str
, struct prefix_ipv6
*p
)
733 pnt
= strchr(str
, '/');
735 /* If string doesn't contain `/' treat it as host route. */
737 ret
= inet_pton(AF_INET6
, str
, &p
->prefix
);
740 p
->prefixlen
= IPV6_MAX_BITLEN
;
744 cp
= XMALLOC(MTYPE_TMP
, (pnt
- str
) + 1);
745 memcpy(cp
, str
, pnt
- str
);
746 *(cp
+ (pnt
- str
)) = '\0';
747 ret
= inet_pton(AF_INET6
, cp
, &p
->prefix
);
748 XFREE(MTYPE_TMP
, cp
);
751 plen
= (uint8_t)atoi(++pnt
);
752 if (plen
> IPV6_MAX_BITLEN
)
756 p
->family
= AF_INET6
;
761 /* Convert struct in6_addr netmask into integer.
762 * FIXME return uint8_t as ip_maskleni() does. */
763 int ip6_masklen(struct in6_addr netmask
)
765 if (netmask
.s6_addr32
[0] != 0xffffffffU
)
766 return __builtin_clz(~ntohl(netmask
.s6_addr32
[0]));
767 if (netmask
.s6_addr32
[1] != 0xffffffffU
)
768 return __builtin_clz(~ntohl(netmask
.s6_addr32
[1])) + 32;
769 if (netmask
.s6_addr32
[2] != 0xffffffffU
)
770 return __builtin_clz(~ntohl(netmask
.s6_addr32
[2])) + 64;
771 if (netmask
.s6_addr32
[3] != 0xffffffffU
)
772 return __builtin_clz(~ntohl(netmask
.s6_addr32
[3])) + 96;
773 /* note __builtin_clz(0) is undefined */
777 void masklen2ip6(const int masklen
, struct in6_addr
*netmask
)
779 assert(masklen
>= 0 && masklen
<= IPV6_MAX_BITLEN
);
782 /* note << 32 is undefined */
783 memset(netmask
, 0, sizeof(*netmask
));
784 } else if (masklen
<= 32) {
785 netmask
->s6_addr32
[0] = htonl(0xffffffffU
<< (32 - masklen
));
786 netmask
->s6_addr32
[1] = 0;
787 netmask
->s6_addr32
[2] = 0;
788 netmask
->s6_addr32
[3] = 0;
789 } else if (masklen
<= 64) {
790 netmask
->s6_addr32
[0] = 0xffffffffU
;
791 netmask
->s6_addr32
[1] = htonl(0xffffffffU
<< (64 - masklen
));
792 netmask
->s6_addr32
[2] = 0;
793 netmask
->s6_addr32
[3] = 0;
794 } else if (masklen
<= 96) {
795 netmask
->s6_addr32
[0] = 0xffffffffU
;
796 netmask
->s6_addr32
[1] = 0xffffffffU
;
797 netmask
->s6_addr32
[2] = htonl(0xffffffffU
<< (96 - masklen
));
798 netmask
->s6_addr32
[3] = 0;
800 netmask
->s6_addr32
[0] = 0xffffffffU
;
801 netmask
->s6_addr32
[1] = 0xffffffffU
;
802 netmask
->s6_addr32
[2] = 0xffffffffU
;
803 netmask
->s6_addr32
[3] = htonl(0xffffffffU
<< (128 - masklen
));
807 void apply_mask_ipv6(struct prefix_ipv6
*p
)
813 index
= p
->prefixlen
/ 8;
816 pnt
= (uint8_t *)&p
->prefix
;
817 offset
= p
->prefixlen
% 8;
819 pnt
[index
] &= maskbit
[offset
];
827 void apply_mask(union prefixptr pu
)
829 struct prefix
*p
= pu
.p
;
833 apply_mask_ipv4(pu
.p4
);
836 apply_mask_ipv6(pu
.p6
);
844 /* Utility function of convert between struct prefix <=> union sockunion. */
845 struct prefix
*sockunion2hostprefix(const union sockunion
*su
,
846 struct prefix
*prefix
)
848 if (su
->sa
.sa_family
== AF_INET
) {
849 struct prefix_ipv4
*p
;
851 p
= prefix
? (struct prefix_ipv4
*)prefix
: prefix_ipv4_new();
853 p
->prefix
= su
->sin
.sin_addr
;
854 p
->prefixlen
= IPV4_MAX_BITLEN
;
855 return (struct prefix
*)p
;
857 if (su
->sa
.sa_family
== AF_INET6
) {
858 struct prefix_ipv6
*p
;
860 p
= prefix
? (struct prefix_ipv6
*)prefix
: prefix_ipv6_new();
861 p
->family
= AF_INET6
;
862 p
->prefixlen
= IPV6_MAX_BITLEN
;
863 memcpy(&p
->prefix
, &su
->sin6
.sin6_addr
,
864 sizeof(struct in6_addr
));
865 return (struct prefix
*)p
;
870 void prefix2sockunion(const struct prefix
*p
, union sockunion
*su
)
872 memset(su
, 0, sizeof(*su
));
874 su
->sa
.sa_family
= p
->family
;
875 if (p
->family
== AF_INET
)
876 su
->sin
.sin_addr
= p
->u
.prefix4
;
877 if (p
->family
== AF_INET6
)
878 memcpy(&su
->sin6
.sin6_addr
, &p
->u
.prefix6
,
879 sizeof(struct in6_addr
));
882 int prefix_blen(union prefixconstptr pu
)
884 const struct prefix
*p
= pu
.p
;
888 return IPV4_MAX_BYTELEN
;
890 return IPV6_MAX_BYTELEN
;
897 /* Generic function for conversion string to struct prefix. */
898 int str2prefix(const char *str
, struct prefix
*p
)
905 /* First we try to convert string to struct prefix_ipv4. */
906 ret
= str2prefix_ipv4(str
, (struct prefix_ipv4
*)p
);
910 /* Next we try to convert string to struct prefix_ipv6. */
911 ret
= str2prefix_ipv6(str
, (struct prefix_ipv6
*)p
);
915 /* Next we try to convert string to struct prefix_eth. */
916 ret
= str2prefix_eth(str
, (struct prefix_eth
*)p
);
923 static const char *prefixevpn_ead2str(const struct prefix_evpn
*p
, char *str
,
927 char buf
[ESI_STR_LEN
];
928 char buf1
[INET6_ADDRSTRLEN
];
930 family
= IS_IPADDR_V4(&p
->prefix
.ead_addr
.ip
) ? AF_INET
: AF_INET6
;
931 snprintf(str
, size
, "[%d]:[%u]:[%s]:[%d]:[%s]:[%u]",
932 p
->prefix
.route_type
, p
->prefix
.ead_addr
.eth_tag
,
933 esi_to_str(&p
->prefix
.ead_addr
.esi
, buf
, sizeof(buf
)),
934 (family
== AF_INET
) ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN
,
935 inet_ntop(family
, &p
->prefix
.ead_addr
.ip
.ipaddr_v4
, buf1
,
937 p
->prefix
.ead_addr
.frag_id
);
941 static const char *prefixevpn_macip2str(const struct prefix_evpn
*p
, char *str
,
945 char buf1
[ETHER_ADDR_STRLEN
];
946 char buf2
[PREFIX2STR_BUFFER
];
948 if (is_evpn_prefix_ipaddr_none(p
))
949 snprintf(str
, size
, "[%d]:[%d]:[%d]:[%s]", p
->prefix
.route_type
,
950 p
->prefix
.macip_addr
.eth_tag
, 8 * ETH_ALEN
,
951 prefix_mac2str(&p
->prefix
.macip_addr
.mac
, buf1
,
954 family
= is_evpn_prefix_ipaddr_v4(p
) ? AF_INET
: AF_INET6
;
955 snprintf(str
, size
, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
956 p
->prefix
.route_type
, p
->prefix
.macip_addr
.eth_tag
,
958 prefix_mac2str(&p
->prefix
.macip_addr
.mac
, buf1
,
960 family
== AF_INET
? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN
,
961 inet_ntop(family
, &p
->prefix
.macip_addr
.ip
.ip
.addr
,
962 buf2
, PREFIX2STR_BUFFER
));
967 static const char *prefixevpn_imet2str(const struct prefix_evpn
*p
, char *str
,
971 char buf
[INET6_ADDRSTRLEN
];
973 family
= IS_IPADDR_V4(&p
->prefix
.imet_addr
.ip
) ? AF_INET
: AF_INET6
;
974 snprintf(str
, size
, "[%d]:[%d]:[%d]:[%s]", p
->prefix
.route_type
,
975 p
->prefix
.imet_addr
.eth_tag
,
976 (family
== AF_INET
) ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN
,
977 inet_ntop(family
, &p
->prefix
.imet_addr
.ip
.ipaddr_v4
, buf
,
983 static const char *prefixevpn_es2str(const struct prefix_evpn
*p
, char *str
,
987 char buf
[ESI_STR_LEN
];
988 char buf1
[INET6_ADDRSTRLEN
];
990 family
= IS_IPADDR_V4(&p
->prefix
.es_addr
.ip
) ? AF_INET
: AF_INET6
;
991 snprintf(str
, size
, "[%d]:[%s]:[%d]:[%s]", p
->prefix
.route_type
,
992 esi_to_str(&p
->prefix
.es_addr
.esi
, buf
, sizeof(buf
)),
993 (family
== AF_INET
) ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN
,
994 inet_ntop(family
, &p
->prefix
.es_addr
.ip
.ipaddr_v4
, buf1
,
1000 static const char *prefixevpn_prefix2str(const struct prefix_evpn
*p
, char *str
,
1004 char buf
[INET6_ADDRSTRLEN
];
1006 family
= IS_IPADDR_V4(&p
->prefix
.prefix_addr
.ip
) ? AF_INET
: AF_INET6
;
1007 snprintf(str
, size
, "[%d]:[%d]:[%d]:[%s]", p
->prefix
.route_type
,
1008 p
->prefix
.prefix_addr
.eth_tag
,
1009 p
->prefix
.prefix_addr
.ip_prefix_length
,
1010 inet_ntop(family
, &p
->prefix
.prefix_addr
.ip
.ipaddr_v4
, buf
,
1015 static const char *prefixevpn2str(const struct prefix_evpn
*p
, char *str
,
1018 switch (p
->prefix
.route_type
) {
1019 case BGP_EVPN_AD_ROUTE
:
1020 return prefixevpn_ead2str(p
, str
, size
);
1021 case BGP_EVPN_MAC_IP_ROUTE
:
1022 return prefixevpn_macip2str(p
, str
, size
);
1023 case BGP_EVPN_IMET_ROUTE
:
1024 return prefixevpn_imet2str(p
, str
, size
);
1025 case BGP_EVPN_ES_ROUTE
:
1026 return prefixevpn_es2str(p
, str
, size
);
1027 case BGP_EVPN_IP_PREFIX_ROUTE
:
1028 return prefixevpn_prefix2str(p
, str
, size
);
1030 snprintf(str
, size
, "Unsupported EVPN prefix");
1036 const char *prefix2str(union prefixconstptr pu
, char *str
, int size
)
1038 const struct prefix
*p
= pu
.p
;
1039 char buf
[PREFIX2STR_BUFFER
];
1040 int byte
, tmp
, a
, b
;
1044 switch (p
->family
) {
1047 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, sizeof(buf
));
1050 byte
= p
->prefixlen
;
1051 tmp
= p
->prefixlen
- 100;
1063 strlcpy(str
, buf
, size
);
1067 snprintf(str
, size
, "%s/%d",
1068 prefix_mac2str(&p
->u
.prefix_eth
, buf
, sizeof(buf
)),
1073 prefixevpn2str((const struct prefix_evpn
*)p
, str
, size
);
1077 strlcpy(str
, "FS prefix", size
);
1081 strlcpy(str
, "UNK prefix", size
);
1088 static ssize_t
prefixhost2str(struct fbuf
*fbuf
, union prefixconstptr pu
)
1090 const struct prefix
*p
= pu
.p
;
1091 char buf
[PREFIX2STR_BUFFER
];
1093 switch (p
->family
) {
1096 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, sizeof(buf
));
1097 return bputs(fbuf
, buf
);
1100 prefix_mac2str(&p
->u
.prefix_eth
, buf
, sizeof(buf
));
1101 return bputs(fbuf
, buf
);
1104 return bprintfrr(fbuf
, "{prefix.af=%dPF}", p
->family
);
1108 void prefix_mcast_inet4_dump(const char *onfail
, struct in_addr addr
,
1109 char *buf
, int buf_size
)
1111 int save_errno
= errno
;
1113 if (addr
.s_addr
== INADDR_ANY
)
1114 strlcpy(buf
, "*", buf_size
);
1116 if (!inet_ntop(AF_INET
, &addr
, buf
, buf_size
)) {
1118 snprintf(buf
, buf_size
, "%s", onfail
);
1125 const char *prefix_sg2str(const struct prefix_sg
*sg
, char *sg_str
)
1127 char src_str
[INET_ADDRSTRLEN
];
1128 char grp_str
[INET_ADDRSTRLEN
];
1130 prefix_mcast_inet4_dump("<src?>", sg
->src
, src_str
, sizeof(src_str
));
1131 prefix_mcast_inet4_dump("<grp?>", sg
->grp
, grp_str
, sizeof(grp_str
));
1132 snprintf(sg_str
, PREFIX_SG_STR_LEN
, "(%s,%s)", src_str
, grp_str
);
1137 struct prefix
*prefix_new(void)
1141 p
= XCALLOC(MTYPE_PREFIX
, sizeof(*p
));
1145 void prefix_free_lists(void *arg
)
1147 struct prefix
*p
= arg
;
1152 /* Free prefix structure. */
1153 void prefix_free(struct prefix
**p
)
1155 XFREE(MTYPE_PREFIX
, *p
);
1158 /* Utility function to convert ipv4 prefixes to Classful prefixes */
1159 void apply_classful_mask_ipv4(struct prefix_ipv4
*p
)
1162 uint32_t destination
;
1164 destination
= ntohl(p
->prefix
.s_addr
);
1166 if (p
->prefixlen
== IPV4_MAX_BITLEN
)
1168 /* do nothing for host routes */
1169 else if (IN_CLASSC(destination
)) {
1172 } else if (IN_CLASSB(destination
)) {
1181 in_addr_t
ipv4_broadcast_addr(in_addr_t hostaddr
, int masklen
)
1183 struct in_addr mask
;
1185 masklen2ip(masklen
, &mask
);
1186 return (masklen
!= IPV4_MAX_BITLEN
- 1)
1189 (hostaddr
| ~mask
.s_addr
)
1191 /* For prefix 31 return 255.255.255.255 (RFC3021) */
1195 /* Utility function to convert ipv4 netmask to prefixes
1196 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
1197 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
1198 int netmask_str2prefix_str(const char *net_str
, const char *mask_str
,
1199 char *prefix_str
, size_t prefix_str_len
)
1201 struct in_addr network
;
1202 struct in_addr mask
;
1204 uint32_t destination
;
1207 ret
= inet_aton(net_str
, &network
);
1212 ret
= inet_aton(mask_str
, &mask
);
1216 prefixlen
= ip_masklen(mask
);
1218 destination
= ntohl(network
.s_addr
);
1220 if (network
.s_addr
== INADDR_ANY
)
1222 else if (IN_CLASSC(destination
))
1224 else if (IN_CLASSB(destination
))
1226 else if (IN_CLASSA(destination
))
1232 snprintf(prefix_str
, prefix_str_len
, "%s/%d", net_str
, prefixlen
);
1237 /* converts to internal representation of mac address
1238 * returns 1 on success, 0 otherwise
1239 * format accepted: AA:BB:CC:DD:EE:FF
1240 * if mac parameter is null, then check only
1242 int prefix_str2mac(const char *str
, struct ethaddr
*mac
)
1250 if (sscanf(str
, "%2x:%2x:%2x:%2x:%2x:%2x", a
+ 0, a
+ 1, a
+ 2, a
+ 3,
1253 /* error in incoming str length */
1256 /* valid mac address */
1259 for (i
= 0; i
< 6; ++i
)
1260 mac
->octet
[i
] = a
[i
] & 0xff;
1264 char *prefix_mac2str(const struct ethaddr
*mac
, char *buf
, int size
)
1271 ptr
= XMALLOC(MTYPE_TMP
, ETHER_ADDR_STRLEN
* sizeof(char));
1273 assert(size
>= ETHER_ADDR_STRLEN
);
1276 snprintf(ptr
, (ETHER_ADDR_STRLEN
), "%02x:%02x:%02x:%02x:%02x:%02x",
1277 (uint8_t)mac
->octet
[0], (uint8_t)mac
->octet
[1],
1278 (uint8_t)mac
->octet
[2], (uint8_t)mac
->octet
[3],
1279 (uint8_t)mac
->octet
[4], (uint8_t)mac
->octet
[5]);
1283 unsigned prefix_hash_key(const void *pp
)
1287 if (((struct prefix
*)pp
)->family
== AF_FLOWSPEC
) {
1291 /* make sure *all* unused bits are zero,
1292 * particularly including alignment /
1293 * padding and unused prefix bytes.
1295 memset(©
, 0, sizeof(copy
));
1296 prefix_copy(©
, (struct prefix
*)pp
);
1297 len
= jhash((void *)copy
.u
.prefix_flowspec
.ptr
,
1298 copy
.u
.prefix_flowspec
.prefixlen
,
1300 temp
= (void *)copy
.u
.prefix_flowspec
.ptr
;
1301 XFREE(MTYPE_PREFIX_FLOWSPEC
, temp
);
1302 copy
.u
.prefix_flowspec
.ptr
= (uintptr_t)NULL
;
1305 /* make sure *all* unused bits are zero, particularly including
1307 * padding and unused prefix bytes. */
1308 memset(©
, 0, sizeof(copy
));
1309 prefix_copy(©
, (struct prefix
*)pp
);
1311 offsetof(struct prefix
, u
.prefix
) + PSIZE(copy
.prefixlen
),
1315 /* converts to internal representation of esi
1316 * returns 1 on success, 0 otherwise
1317 * format accepted: aa:aa:aa:aa:aa:aa:aa:aa:aa:aa
1318 * if esi parameter is null, then check only
1320 int str_to_esi(const char *str
, esi_t
*esi
)
1323 unsigned int a
[ESI_BYTES
];
1328 if (sscanf(str
, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x",
1329 a
+ 0, a
+ 1, a
+ 2, a
+ 3,
1330 a
+ 4, a
+ 5, a
+ 6, a
+ 7,
1333 /* error in incoming str length */
1340 for (i
= 0; i
< ESI_BYTES
; ++i
)
1341 esi
->val
[i
] = a
[i
] & 0xff;
1345 char *esi_to_str(const esi_t
*esi
, char *buf
, int size
)
1352 ptr
= XMALLOC(MTYPE_TMP
, ESI_STR_LEN
* sizeof(char));
1354 assert(size
>= ESI_STR_LEN
);
1358 snprintf(ptr
, ESI_STR_LEN
,
1359 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1360 esi
->val
[0], esi
->val
[1], esi
->val
[2],
1361 esi
->val
[3], esi
->val
[4], esi
->val
[5],
1362 esi
->val
[6], esi
->val
[7], esi
->val
[8],
1367 char *evpn_es_df_alg2str(uint8_t df_alg
, char *buf
, int buf_len
)
1370 case EVPN_MH_DF_ALG_SERVICE_CARVING
:
1371 snprintf(buf
, buf_len
, "service-carving");
1374 case EVPN_MH_DF_ALG_HRW
:
1375 snprintf(buf
, buf_len
, "HRW");
1378 case EVPN_MH_DF_ALG_PREF
:
1379 snprintf(buf
, buf_len
, "preference");
1383 snprintf(buf
, buf_len
, "unknown %u", df_alg
);
1390 bool ipv4_unicast_valid(const struct in_addr
*addr
)
1392 in_addr_t ip
= ntohl(addr
->s_addr
);
1394 if (IPV4_CLASS_D(ip
))
1397 if (IPV4_CLASS_E(ip
)) {
1398 if (cmd_allow_reserved_ranges_get())
1407 printfrr_ext_autoreg_p("EA", printfrr_ea
);
1408 static ssize_t
printfrr_ea(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1411 const struct ethaddr
*mac
= ptr
;
1412 char cbuf
[ETHER_ADDR_STRLEN
];
1415 return bputs(buf
, "(null)");
1417 /* need real length even if buffer is too short */
1418 prefix_mac2str(mac
, cbuf
, sizeof(cbuf
));
1419 return bputs(buf
, cbuf
);
1422 printfrr_ext_autoreg_p("IA", printfrr_ia
);
1423 static ssize_t
printfrr_ia(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1426 const struct ipaddr
*ipa
= ptr
;
1427 char cbuf
[INET6_ADDRSTRLEN
];
1428 bool use_star
= false;
1430 if (ea
->fmt
[0] == 's') {
1436 return bputs(buf
, "(null)");
1439 struct in_addr zero4
= {};
1440 struct in6_addr zero6
= {};
1442 switch (ipa
->ipa_type
) {
1444 if (!memcmp(&ipa
->ip
.addr
, &zero4
, sizeof(zero4
)))
1445 return bputch(buf
, '*');
1449 if (!memcmp(&ipa
->ip
.addr
, &zero6
, sizeof(zero6
)))
1450 return bputch(buf
, '*');
1458 ipaddr2str(ipa
, cbuf
, sizeof(cbuf
));
1459 return bputs(buf
, cbuf
);
1462 printfrr_ext_autoreg_p("I4", printfrr_i4
);
1463 static ssize_t
printfrr_i4(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1466 char cbuf
[INET_ADDRSTRLEN
];
1467 bool use_star
= false;
1468 struct in_addr zero
= {};
1470 if (ea
->fmt
[0] == 's') {
1476 return bputs(buf
, "(null)");
1478 if (use_star
&& !memcmp(ptr
, &zero
, sizeof(zero
)))
1479 return bputch(buf
, '*');
1481 inet_ntop(AF_INET
, ptr
, cbuf
, sizeof(cbuf
));
1482 return bputs(buf
, cbuf
);
1485 printfrr_ext_autoreg_p("I6", printfrr_i6
);
1486 static ssize_t
printfrr_i6(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1489 char cbuf
[INET6_ADDRSTRLEN
];
1490 bool use_star
= false;
1491 struct in6_addr zero
= {};
1493 if (ea
->fmt
[0] == 's') {
1499 return bputs(buf
, "(null)");
1501 if (use_star
&& !memcmp(ptr
, &zero
, sizeof(zero
)))
1502 return bputch(buf
, '*');
1504 inet_ntop(AF_INET6
, ptr
, cbuf
, sizeof(cbuf
));
1505 return bputs(buf
, cbuf
);
1508 printfrr_ext_autoreg_p("FX", printfrr_pfx
);
1509 static ssize_t
printfrr_pfx(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1512 bool host_only
= false;
1514 if (ea
->fmt
[0] == 'h') {
1520 return bputs(buf
, "(null)");
1523 return prefixhost2str(buf
, (struct prefix
*)ptr
);
1525 char cbuf
[PREFIX_STRLEN
];
1527 prefix2str(ptr
, cbuf
, sizeof(cbuf
));
1528 return bputs(buf
, cbuf
);
1532 printfrr_ext_autoreg_p("PSG4", printfrr_psg
);
1533 static ssize_t
printfrr_psg(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
1536 const struct prefix_sg
*sg
= ptr
;
1540 return bputs(buf
, "(null)");
1542 if (sg
->src
.s_addr
== INADDR_ANY
)
1543 ret
+= bputs(buf
, "(*,");
1545 ret
+= bprintfrr(buf
, "(%pI4,", &sg
->src
);
1547 if (sg
->grp
.s_addr
== INADDR_ANY
)
1548 ret
+= bputs(buf
, "*)");
1550 ret
+= bprintfrr(buf
, "%pI4)", &sg
->grp
);