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