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