]> git.proxmox.com Git - mirror_frr.git/blame - lib/prefix.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / prefix.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
3 * Prefix related functions.
4 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
718e3744 5 */
6
7#include <zebra.h>
8
d80132b1 9#include "command.h"
718e3744 10#include "prefix.h"
dc5d0186 11#include "ipaddr.h"
718e3744 12#include "vty.h"
13#include "sockunion.h"
14#include "memory.h"
15#include "log.h"
7a7761d2 16#include "jhash.h"
472878dc 17#include "lib_errors.h"
d52ec572 18#include "printfrr.h"
74e2bd89 19#include "vxlan.h"
6b0655a2 20
bf8d3d6a
DL
21DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix");
22DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec");
4a1ab8e4 23
718e3744 24/* Maskbit. */
d7c0a89a
QY
25static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
26 0xf8, 0xfc, 0xfe, 0xff};
d62a17ae 27
718e3744 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
a9e08ebc 35int is_zero_mac(const struct ethaddr *mac)
69b61704
MK
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
c6ec0c74
KA
47bool 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
58bool is_mcast_mac(const struct ethaddr *mac)
59{
60 if ((mac->octet[0] & 0x01) == 0x01)
61 return true;
62
63 return false;
64}
65
adeb0672 66unsigned int prefix_bit(const uint8_t *prefix, const uint16_t bit_index)
f63f06da 67{
adeb0672
QY
68 unsigned int offset = bit_index / 8;
69 unsigned int shift = 7 - (bit_index % 8);
d62a17ae 70
71 return (prefix[offset] >> shift) & 1;
f63f06da
PJ
72}
73
d62a17ae 74int str2family(const char *string)
f3ccedaa 75{
d62a17ae 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;
b03b8898
DS
82 else if (!strcmp("evpn", string))
83 return AF_EVPN;
d62a17ae 84 return -1;
f3ccedaa
CF
85}
86
db2fde34
PZ
87const 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
214d8a60 102/* Address Family Identifier to Address Family converter. */
d62a17ae 103int afi2family(afi_t afi)
718e3744 104{
d62a17ae 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;
b03b8898 111 /* NOTE: EVPN code should NOT use this interface. */
d62a17ae 112 return 0;
718e3744 113}
114
d62a17ae 115afi_t family2afi(int family)
718e3744 116{
d62a17ae 117 if (family == AF_INET)
118 return AFI_IP;
119 else if (family == AF_INET6)
120 return AFI_IP6;
b03b8898 121 else if (family == AF_ETHERNET || family == AF_EVPN)
d62a17ae 122 return AFI_L2VPN;
123 return 0;
718e3744 124}
125
0884f164
DS
126const 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
d62a17ae 143const char *afi2str(afi_t afi)
32ac65d9 144{
d62a17ae 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:
bde30e78 153 case AFI_UNSPEC:
d62a17ae 154 return "bad-value";
d62a17ae 155 }
bde30e78
DS
156
157 assert(!"Reached end of function we should never reach");
32ac65d9
LB
158}
159
d62a17ae 160const char *safi2str(safi_t safi)
1ec23d90 161{
d62a17ae 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";
7c40bf39 175 case SAFI_FLOWSPEC:
176 return "flowspec";
bde30e78
DS
177 case SAFI_UNSPEC:
178 case SAFI_MAX:
5c525538 179 return "unknown";
d62a17ae 180 }
bde30e78
DS
181
182 assert(!"Reached end of function we should never reach");
1ec23d90
LB
183}
184
718e3744 185/* If n includes p prefix then return 1 else return 0. */
3125fa6d 186int prefix_match(union prefixconstptr unet, union prefixconstptr upfx)
718e3744 187{
3125fa6d
DL
188 const struct prefix *n = unet.p;
189 const struct prefix *p = upfx.p;
d62a17ae 190 int offset;
191 int shift;
d7c0a89a 192 const uint8_t *np, *pp;
d62a17ae 193
194 /* If n's prefix is longer than p's one return 0. */
195 if (n->prefixlen > p->prefixlen)
196 return 0;
197
9a14899b
PG
198 if (n->family == AF_FLOWSPEC) {
199 /* prefixlen is unused. look at fs prefix len */
e4552d66
PG
200 if (n->u.prefix_flowspec.family !=
201 p->u.prefix_flowspec.family)
202 return 0;
203
9a14899b
PG
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
d62a17ae 220 /* Set both prefix's head pointer. */
f0ed6bea 221 np = n->u.val;
222 pp = p->u.val;
d62a17ae 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;
44c69747
LK
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 */
243int 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
3bec29ac
DS
282}
283
284/* If n includes p then return 1 else return 0. Prefix mask is not considered */
3125fa6d
DL
285int prefix_match_network_statement(union prefixconstptr unet,
286 union prefixconstptr upfx)
3bec29ac 287{
3125fa6d
DL
288 const struct prefix *n = unet.p;
289 const struct prefix *p = upfx.p;
d62a17ae 290 int offset;
291 int shift;
d7c0a89a 292 const uint8_t *np, *pp;
3bec29ac 293
d62a17ae 294 /* Set both prefix's head pointer. */
f0ed6bea 295 np = n->u.val;
296 pp = p->u.val;
3bec29ac 297
d62a17ae 298 offset = n->prefixlen / PNBBY;
299 shift = n->prefixlen % PNBBY;
3bec29ac 300
d62a17ae 301 if (shift)
302 if (maskbit[shift] & (np[offset] ^ pp[offset]))
303 return 0;
3bec29ac 304
d62a17ae 305 while (offset--)
306 if (np[offset] != pp[offset])
307 return 0;
308 return 1;
718e3744 309}
310
4937287f
DL
311#ifdef __clang_analyzer__
312#undef prefix_copy /* cf. prefix.h */
313#endif
314
9c3a2171 315void prefix_copy(union prefixptr udest, union prefixconstptr usrc)
718e3744 316{
9c3a2171
DL
317 struct prefix *dest = udest.p;
318 const struct prefix *src = usrc.p;
319
d62a17ae 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) {
b03b8898
DS
328 memcpy(&dest->u.prefix_eth, &src->u.prefix_eth,
329 sizeof(struct ethaddr));
330 } else if (src->family == AF_EVPN) {
d62a17ae 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;
9a14899b
PG
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;
e4552d66
PG
343 dest->u.prefix_flowspec.family =
344 src->u.prefix_flowspec.family;
9a14899b
PG
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);
d62a17ae 350 } else {
450971aa 351 flog_err(EC_LIB_DEVELOPMENT,
1c50c1c0
QY
352 "prefix_copy(): Unknown address family %d",
353 src->family);
d62a17ae 354 assert(0);
355 }
718e3744 356}
357
d62a17ae 358/*
9d24baaa 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 */
9c3a2171 366int prefix_same(union prefixconstptr up1, union prefixconstptr up2)
718e3744 367{
9c3a2171
DL
368 const struct prefix *p1 = up1.p;
369 const struct prefix *p2 = up2.p;
370
d62a17ae 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)
19aad877 379 if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
d62a17ae 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)
b03b8898
DS
386 if (!memcmp(&p1->u.prefix_eth, &p2->u.prefix_eth,
387 sizeof(struct ethaddr)))
388 return 1;
389 if (p1->family == AF_EVPN)
d62a17ae 390 if (!memcmp(&p1->u.prefix_evpn, &p2->u.prefix_evpn,
391 sizeof(struct evpn_addr)))
392 return 1;
9a14899b 393 if (p1->family == AF_FLOWSPEC) {
e4552d66
PG
394 if (p1->u.prefix_flowspec.family !=
395 p2->u.prefix_flowspec.family)
396 return 0;
9a14899b
PG
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 }
d62a17ae 405 }
406 return 0;
718e3744 407}
408
9d24baaa 409/*
1315d74d
DL
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
9d24baaa 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 */
9c3a2171 420int prefix_cmp(union prefixconstptr up1, union prefixconstptr up2)
718e3744 421{
9c3a2171
DL
422 const struct prefix *p1 = up1.p;
423 const struct prefix *p2 = up2.p;
d62a17ae 424 int offset;
425 int shift;
1315d74d 426 int i;
718e3744 427
d62a17ae 428 /* Set both prefix's head pointer. */
9a14899b
PG
429 const uint8_t *pp1;
430 const uint8_t *pp2;
718e3744 431
9a14899b 432 if (p1->family != p2->family)
1315d74d 433 return numcmp(p1->family, p2->family);
9a14899b
PG
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;
718e3744 437
e4552d66
PG
438 if (p1->u.prefix_flowspec.family !=
439 p2->u.prefix_flowspec.family)
440 return 1;
441
9a14899b
PG
442 if (p1->u.prefix_flowspec.prefixlen !=
443 p2->u.prefix_flowspec.prefixlen)
1315d74d
DL
444 return numcmp(p1->u.prefix_flowspec.prefixlen,
445 p2->u.prefix_flowspec.prefixlen);
9a14899b
PG
446
447 offset = p1->u.prefix_flowspec.prefixlen;
448 while (offset--)
449 if (pp1[offset] != pp2[offset])
1315d74d 450 return numcmp(pp1[offset], pp2[offset]);
9a14899b
PG
451 return 0;
452 }
f0ed6bea 453 pp1 = p1->u.val;
454 pp2 = p2->u.val;
9a14899b
PG
455
456 if (p1->prefixlen != p2->prefixlen)
1315d74d 457 return numcmp(p1->prefixlen, p2->prefixlen);
d62a17ae 458 offset = p1->prefixlen / PNBBY;
459 shift = p1->prefixlen % PNBBY;
718e3744 460
1315d74d
DL
461 i = memcmp(pp1, pp2, offset);
462 if (i)
463 return i;
718e3744 464
dd5bab0c
DS
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;
718e3744 477}
478
17e52061
DL
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 */
3125fa6d 485int prefix_common_bits(union prefixconstptr ua, union prefixconstptr ub)
17e52061 486{
3125fa6d
DL
487 const struct prefix *p1 = ua.p;
488 const struct prefix *p2 = ub.p;
d62a17ae 489 int pos, bit;
490 int length = 0;
d7c0a89a 491 uint8_t xor ;
d62a17ae 492
493 /* Set both prefix's head pointer. */
f0ed6bea 494 const uint8_t *pp1 = p1->u.val;
495 const uint8_t *pp2 = p2->u.val;
d62a17ae 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)
b03b8898
DS
502 length = ETH_ALEN;
503 if (p1->family == AF_EVPN)
d62a17ae 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;
17e52061
DL
521}
522
718e3744 523/* Return prefix family type string. */
3125fa6d 524const char *prefix_family_str(union prefixconstptr pu)
718e3744 525{
3125fa6d
DL
526 const struct prefix *p = pu.p;
527
d62a17ae 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";
b03b8898
DS
534 if (p->family == AF_EVPN)
535 return "evpn";
d62a17ae 536 return "unspec";
718e3744 537}
538
539/* Allocate new prefix_ipv4 structure. */
4d762f26 540struct prefix_ipv4 *prefix_ipv4_new(void)
718e3744 541{
d62a17ae 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;
718e3744 551}
552
553/* Free prefix_ipv4 structure. */
63265b5c 554void prefix_ipv4_free(struct prefix_ipv4 **p)
718e3744 555{
63265b5c 556 prefix_free((struct prefix **)p);
718e3744 557}
558
3923b6e3 559/* If given string is valid return 1 else return 0 */
d62a17ae 560int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
718e3744 561{
d62a17ae 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. */
8d920049 573 ret = inet_pton(AF_INET, str, &p->prefix);
d62a17ae 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);
aab9a0a0 585 memcpy(cp, str, pnt - str);
d62a17ae 586 *(cp + (pnt - str)) = '\0';
ef231ac7 587 ret = inet_pton(AF_INET, cp, &p->prefix);
d62a17ae 588 XFREE(MTYPE_TMP, cp);
ef231ac7
RW
589 if (ret == 0)
590 return 0;
d62a17ae 591
592 /* Get prefix length. */
d7c0a89a 593 plen = (uint8_t)atoi(++pnt);
936fbaef 594 if (plen > IPV4_MAX_BITLEN)
d62a17ae 595 return 0;
596
597 p->family = AF_INET;
598 p->prefixlen = plen;
599 }
718e3744 600
d62a17ae 601 return ret;
718e3744 602}
603
32ac65d9 604/* When string format is invalid return 0. */
d62a17ae 605int str2prefix_eth(const char *str, struct prefix_eth *p)
32ac65d9 606{
d62a17ae 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;
0f6476cc 614 bool slash = false;
d62a17ae 615
3b0f6068
DL
616 if (!strcmp(str, "any")) {
617 memset(p, 0, sizeof(*p));
618 p->family = AF_ETHERNET;
619 return 1;
620 }
621
d62a17ae 622 /* Find slash inside string. */
623 pnt = strchr(str, '/');
624
625 if (pnt) {
626 /* Get prefix length. */
d7c0a89a 627 plen = (uint8_t)atoi(++pnt);
d62a17ae 628 if (plen > 48) {
629 ret = 0;
630 goto done;
631 }
632
633 cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
aab9a0a0 634 memcpy(cp, str, pnt - str);
d62a17ae 635 *(cp + (pnt - str)) = '\0';
636
637 str_addr = cp;
0f6476cc 638 slash = true;
32ac65d9
LB
639 }
640
d62a17ae 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;
0f6476cc
DS
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)))
996c9314 660 p->prefixlen = 0;
0f6476cc 661
d62a17ae 662 ret = 1;
32ac65d9
LB
663
664done:
0a22ddfb 665 XFREE(MTYPE_TMP, cp);
32ac65d9 666
d62a17ae 667 return ret;
32ac65d9
LB
668}
669
051954f5 670/* Convert masklen into IP address's netmask (network byte order). */
d62a17ae 671void masklen2ip(const int masklen, struct in_addr *netmask)
718e3744 672{
d62a17ae 673 assert(masklen >= 0 && masklen <= IPV4_MAX_BITLEN);
e96b3121 674
d62a17ae 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) */
e96b3121 678
d62a17ae 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);
718e3744 684}
685
686/* Convert IP address's netmask into integer. We assume netmask is
f93eee44 687 * sequential one. Argument netmask should be network byte order. */
d7c0a89a 688uint8_t ip_masklen(struct in_addr netmask)
718e3744 689{
d62a17ae 690 uint32_t tmp = ~ntohl(netmask.s_addr);
f93eee44 691
61be6e94
QY
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 */
f93eee44 696 return tmp ? __builtin_clz(tmp) : 32;
718e3744 697}
698
caff7905 699/* Apply mask to IPv4 prefix (network byte order). */
d62a17ae 700void apply_mask_ipv4(struct prefix_ipv4 *p)
718e3744 701{
d62a17ae 702 struct in_addr mask;
703 masklen2ip(p->prefixlen, &mask);
704 p->prefix.s_addr &= mask.s_addr;
718e3744 705}
706
707/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
d62a17ae 708int prefix_ipv4_any(const struct prefix_ipv4 *p)
718e3744 709{
975a328e 710 return (p->prefix.s_addr == INADDR_ANY && p->prefixlen == 0);
718e3744 711}
6b0655a2 712
718e3744 713/* Allocate a new ip version 6 route */
d62a17ae 714struct prefix_ipv6 *prefix_ipv6_new(void)
718e3744 715{
d62a17ae 716 struct prefix_ipv6 *p;
718e3744 717
d62a17ae 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;
718e3744 723}
724
725/* Free prefix for IPv6. */
63265b5c 726void prefix_ipv6_free(struct prefix_ipv6 **p)
718e3744 727{
63265b5c 728 prefix_free((struct prefix **)p);
718e3744 729}
730
3923b6e3 731/* If given string is valid return 1 else return 0 */
d62a17ae 732int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
718e3744 733{
d62a17ae 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);
aab9a0a0 750 memcpy(cp, str, pnt - str);
d62a17ae 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;
d7c0a89a 756 plen = (uint8_t)atoi(++pnt);
d62a17ae 757 if (plen > IPV6_MAX_BITLEN)
758 return 0;
759 p->prefixlen = plen;
760 }
761 p->family = AF_INET6;
718e3744 762
d62a17ae 763 return ret;
718e3744 764}
765
b04c699e 766/* Convert struct in6_addr netmask into integer.
d7c0a89a 767 * FIXME return uint8_t as ip_maskleni() does. */
d62a17ae 768int ip6_masklen(struct in6_addr netmask)
718e3744 769{
25d86233
DL
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;
718e3744 780}
781
d62a17ae 782void masklen2ip6(const int masklen, struct in6_addr *netmask)
718e3744 783{
d62a17ae 784 assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN);
25d86233
DL
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 }
718e3744 810}
811
d62a17ae 812void apply_mask_ipv6(struct prefix_ipv6 *p)
718e3744 813{
d7c0a89a 814 uint8_t *pnt;
d62a17ae 815 int index;
816 int offset;
8c7f49d2 817
d62a17ae 818 index = p->prefixlen / 8;
8c7f49d2 819
d62a17ae 820 if (index < 16) {
d7c0a89a 821 pnt = (uint8_t *)&p->prefix;
d62a17ae 822 offset = p->prefixlen % 8;
8c7f49d2 823
d62a17ae 824 pnt[index] &= maskbit[offset];
825 index++;
8c7f49d2 826
d62a17ae 827 while (index < 16)
828 pnt[index++] = 0;
829 }
718e3744 830}
831
3125fa6d 832void apply_mask(union prefixptr pu)
718e3744 833{
3125fa6d
DL
834 struct prefix *p = pu.p;
835
d62a17ae 836 switch (p->family) {
837 case AF_INET:
3125fa6d 838 apply_mask_ipv4(pu.p4);
d62a17ae 839 break;
840 case AF_INET6:
3125fa6d 841 apply_mask_ipv6(pu.p6);
d62a17ae 842 break;
843 default:
844 break;
845 }
846 return;
718e3744 847}
848
b04c699e 849/* Utility function of convert between struct prefix <=> union sockunion. */
d62a17ae 850struct prefix *sockunion2hostprefix(const union sockunion *su,
851 struct prefix *prefix)
718e3744 852{
d62a17ae 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;
718e3744 873}
874
d62a17ae 875void prefix2sockunion(const struct prefix *p, union sockunion *su)
17e52061 876{
d62a17ae 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));
17e52061
DL
885}
886
3125fa6d 887int prefix_blen(union prefixconstptr pu)
718e3744 888{
3125fa6d
DL
889 const struct prefix *p = pu.p;
890
d62a17ae 891 switch (p->family) {
892 case AF_INET:
893 return IPV4_MAX_BYTELEN;
d62a17ae 894 case AF_INET6:
895 return IPV6_MAX_BYTELEN;
d62a17ae 896 case AF_ETHERNET:
7628d862 897 return ETH_ALEN;
d62a17ae 898 }
899 return 0;
718e3744 900}
901
902/* Generic function for conversion string to struct prefix. */
d62a17ae 903int str2prefix(const char *str, struct prefix *p)
718e3744 904{
d62a17ae 905 int ret;
718e3744 906
c37a11ad 907 if (!str || !p)
908 return 0;
909
d62a17ae 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;
718e3744 914
d62a17ae 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;
718e3744 919
d62a17ae 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;
32ac65d9 924
d62a17ae 925 return 0;
718e3744 926}
927
3714a385 928static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
929 int size)
930{
f137734b 931 uint8_t family;
8d78eeb5 932 char buf[ESI_STR_LEN];
f137734b 933 char buf1[INET6_ADDRSTRLEN];
8d78eeb5 934
f137734b 935 family = IS_IPADDR_V4(&p->prefix.ead_addr.ip) ? AF_INET : AF_INET6;
7b0db0e4
AK
936 snprintf(str, size, "[%d]:[%u]:[%s]:[%d]:[%s]:[%u]",
937 p->prefix.route_type, p->prefix.ead_addr.eth_tag,
8d78eeb5 938 esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)),
f137734b
PR
939 (family == AF_INET) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
940 inet_ntop(family, &p->prefix.ead_addr.ip.ipaddr_v4, buf1,
7b0db0e4
AK
941 sizeof(buf1)),
942 p->prefix.ead_addr.frag_id);
3714a385 943 return str;
944}
945
946static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
947 int size)
86f1ef44 948{
d7c0a89a 949 uint8_t family;
8d78eeb5
PR
950 char buf1[ETHER_ADDR_STRLEN];
951 char buf2[PREFIX2STR_BUFFER];
d62a17ae 952
3714a385 953 if (is_evpn_prefix_ipaddr_none(p))
8d78eeb5
PR
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)));
3714a385 958 else {
8d78eeb5
PR
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));
d62a17ae 968 }
3714a385 969 return str;
970}
971
972static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
973 int size)
974{
f137734b
PR
975 uint8_t family;
976 char buf[INET6_ADDRSTRLEN];
977
978 family = IS_IPADDR_V4(&p->prefix.imet_addr.ip) ? AF_INET : AF_INET6;
8d78eeb5
PR
979 snprintf(str, size, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
980 p->prefix.imet_addr.eth_tag,
f137734b
PR
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)));
d62a17ae 984
3714a385 985 return str;
986}
987
988static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
989 int size)
990{
f137734b 991 uint8_t family;
50f74cf1 992 char buf[ESI_STR_LEN];
f137734b 993 char buf1[INET6_ADDRSTRLEN];
50f74cf1 994
f137734b 995 family = IS_IPADDR_V4(&p->prefix.es_addr.ip) ? AF_INET : AF_INET6;
8d78eeb5 996 snprintf(str, size, "[%d]:[%s]:[%d]:[%s]", p->prefix.route_type,
50f74cf1 997 esi_to_str(&p->prefix.es_addr.esi, buf, sizeof(buf)),
f137734b
PR
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)));
8d78eeb5 1001
3714a385 1002 return str;
1003}
1004
1005static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
1006 int size)
1007{
f137734b
PR
1008 uint8_t family;
1009 char buf[INET6_ADDRSTRLEN];
1010
1011 family = IS_IPADDR_V4(&p->prefix.prefix_addr.ip) ? AF_INET : AF_INET6;
8d78eeb5 1012 snprintf(str, size, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
3714a385 1013 p->prefix.prefix_addr.eth_tag,
3714a385 1014 p->prefix.prefix_addr.ip_prefix_length,
f137734b
PR
1015 inet_ntop(family, &p->prefix.prefix_addr.ip.ipaddr_v4, buf,
1016 sizeof(buf)));
3714a385 1017 return str;
1018}
1019
1020static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
1021 int size)
1022{
1023 switch (p->prefix.route_type) {
8d78eeb5 1024 case BGP_EVPN_AD_ROUTE:
3714a385 1025 return prefixevpn_ead2str(p, str, size);
8d78eeb5 1026 case BGP_EVPN_MAC_IP_ROUTE:
3714a385 1027 return prefixevpn_macip2str(p, str, size);
8d78eeb5 1028 case BGP_EVPN_IMET_ROUTE:
3714a385 1029 return prefixevpn_imet2str(p, str, size);
8d78eeb5 1030 case BGP_EVPN_ES_ROUTE:
3714a385 1031 return prefixevpn_es2str(p, str, size);
8d78eeb5 1032 case BGP_EVPN_IP_PREFIX_ROUTE:
3714a385 1033 return prefixevpn_prefix2str(p, str, size);
1034 default:
1035 snprintf(str, size, "Unsupported EVPN prefix");
1036 break;
1037 }
d62a17ae 1038 return str;
86f1ef44 1039}
1040
d62a17ae 1041const char *prefix2str(union prefixconstptr pu, char *str, int size)
718e3744 1042{
d62a17ae 1043 const struct prefix *p = pu.p;
1044 char buf[PREFIX2STR_BUFFER];
ec466f65
QY
1045 int byte, tmp, a, b;
1046 bool z = false;
1047 size_t l;
d62a17ae 1048
1049 switch (p->family) {
1050 case AF_INET:
1051 case AF_INET6:
ec466f65
QY
1052 inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
1053 l = strlen(buf);
1054 buf[l++] = '/';
1055 byte = p->prefixlen;
0e2d7076
DA
1056 tmp = p->prefixlen - 100;
1057 if (tmp >= 0) {
ec466f65
QY
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);
d62a17ae 1069 break;
1070
1071 case AF_ETHERNET:
b03b8898
DS
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:
3714a385 1078 prefixevpn2str((const struct prefix_evpn *)p, str, size);
d62a17ae 1079 break;
1080
9a14899b 1081 case AF_FLOWSPEC:
ec466f65 1082 strlcpy(str, "FS prefix", size);
9a14899b
PG
1083 break;
1084
d62a17ae 1085 default:
ec466f65 1086 strlcpy(str, "UNK prefix", size);
d62a17ae 1087 break;
1088 }
1089
1090 return str;
718e3744 1091}
1092
543a2684
DL
1093static 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
c6b6b53b
AK
1113void 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)
9f73d2c9 1119 strlcpy(buf, "*", buf_size);
c6b6b53b
AK
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
1130const 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
4d762f26 1142struct prefix *prefix_new(void)
718e3744 1143{
d62a17ae 1144 struct prefix *p;
718e3744 1145
0d6f7fd6 1146 p = XCALLOC(MTYPE_PREFIX, sizeof(*p));
d62a17ae 1147 return p;
718e3744 1148}
1149
63265b5c
DS
1150void prefix_free_lists(void *arg)
1151{
1152 struct prefix *p = arg;
1153
1154 prefix_free(&p);
1155}
1156
718e3744 1157/* Free prefix structure. */
63265b5c 1158void prefix_free(struct prefix **p)
718e3744 1159{
63265b5c 1160 XFREE(MTYPE_PREFIX, *p);
718e3744 1161}
1162
718e3744 1163/* Utility function to convert ipv4 prefixes to Classful prefixes */
d62a17ae 1164void apply_classful_mask_ipv4(struct prefix_ipv4 *p)
718e3744 1165{
1166
d7c0a89a 1167 uint32_t destination;
d62a17ae 1168
1169 destination = ntohl(p->prefix.s_addr);
1170
936fbaef 1171 if (p->prefixlen == IPV4_MAX_BITLEN)
d62a17ae 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 }
718e3744 1184}
1185
d62a17ae 1186in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
3fb9cd6e 1187{
d62a17ae 1188 struct in_addr mask;
1189
1190 masklen2ip(masklen, &mask);
936fbaef
DA
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);
3fb9cd6e 1198}
1199
d62a17ae 1200/* Utility function to convert ipv4 netmask to prefixes
718e3744 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" */
d62a17ae 1203int netmask_str2prefix_str(const char *net_str, const char *mask_str,
7533cad7 1204 char *prefix_str, size_t prefix_str_len)
718e3744 1205{
d62a17ae 1206 struct in_addr network;
1207 struct in_addr mask;
d7c0a89a
QY
1208 uint8_t prefixlen;
1209 uint32_t destination;
d62a17ae 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
975a328e 1225 if (network.s_addr == INADDR_ANY)
d62a17ae 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 }
718e3744 1236
7533cad7 1237 snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
718e3744 1238
d62a17ae 1239 return 1;
718e3744 1240}
1241
c215ecaf 1242/* converts to internal representation of mac address
d62a17ae 1243 * returns 1 on success, 0 otherwise
c215ecaf
PG
1244 * format accepted: AA:BB:CC:DD:EE:FF
1245 * if mac parameter is null, then check only
1246 */
db42a173 1247int prefix_str2mac(const char *str, struct ethaddr *mac)
c215ecaf 1248{
d62a17ae 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;
c215ecaf
PG
1267}
1268
db42a173 1269char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
c215ecaf 1270{
d62a17ae 1271 char *ptr;
1272
1273 if (!mac)
1274 return NULL;
1275 if (!buf)
9f5dc319 1276 ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
d62a17ae 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;
c215ecaf 1286}
7a7761d2 1287
62b4b3b6 1288unsigned prefix_hash_key(const void *pp)
7a7761d2
CF
1289{
1290 struct prefix copy;
1291
9a14899b
PG
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 }
7a7761d2
CF
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);
996c9314
LB
1315 return jhash(&copy,
1316 offsetof(struct prefix, u.prefix) + PSIZE(copy.prefixlen),
1317 0x55aa5a5a);
7a7761d2 1318}
50f74cf1 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 */
1325int 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
1350char *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)
9f5dc319 1357 ptr = XMALLOC(MTYPE_TMP, ESI_STR_LEN * sizeof(char));
50f74cf1 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}
d52ec572 1371
74e2bd89
AK
1372char *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
d80132b1
DA
1395bool 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
8eb09e64 1402 if (IPV4_NET0(ip) || IPV4_NET127(ip) || IPV4_CLASS_E(ip)) {
d80132b1
DA
1403 if (cmd_allow_reserved_ranges_get())
1404 return true;
1405 else
1406 return false;
1407 }
1408
1409 return true;
1410}
1411
6eb83505
SW
1412static 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 */
1439int 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) {
5ad4fc6c 1449 case BGP_EVPN_MAC_IP_ROUTE:
6eb83505 1450 if (IS_IPADDR_V4(&addr->macip_addr.ip))
0c5675b7
TA
1451 ipaddr2prefix(&addr->macip_addr.ip, IPV4_MAX_BITLEN,
1452 to);
6eb83505 1453 else if (IS_IPADDR_V6(&addr->macip_addr.ip))
0c5675b7
TA
1454 ipaddr2prefix(&addr->macip_addr.ip, IPV6_MAX_BITLEN,
1455 to);
6eb83505
SW
1456 else
1457 return -1; /* mac only? */
1458
1459 break;
5ad4fc6c 1460 case BGP_EVPN_IP_PREFIX_ROUTE:
6eb83505
SW
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
54929fd3 1471printfrr_ext_autoreg_p("EA", printfrr_ea);
3ea79430
DL
1472static ssize_t printfrr_ea(struct fbuf *buf, struct printfrr_eargs *ea,
1473 const void *ptr)
bd0ab4d8
DL
1474{
1475 const struct ethaddr *mac = ptr;
212e04e5 1476 char cbuf[ETHER_ADDR_STRLEN];
bd0ab4d8 1477
212e04e5 1478 if (!mac)
eba599a3 1479 return bputs(buf, "(null)");
8e2c653e 1480
212e04e5
DL
1481 /* need real length even if buffer is too short */
1482 prefix_mac2str(mac, cbuf, sizeof(cbuf));
1483 return bputs(buf, cbuf);
bd0ab4d8
DL
1484}
1485
54929fd3 1486printfrr_ext_autoreg_p("IA", printfrr_ia);
3ea79430
DL
1487static ssize_t printfrr_ia(struct fbuf *buf, struct printfrr_eargs *ea,
1488 const void *ptr)
dc5d0186
DL
1489{
1490 const struct ipaddr *ipa = ptr;
212e04e5 1491 char cbuf[INET6_ADDRSTRLEN];
2c5b4d80
DL
1492 bool use_star = false;
1493
1494 if (ea->fmt[0] == 's') {
1495 use_star = true;
1496 ea->fmt++;
1497 }
dc5d0186 1498
927c633d 1499 if (!ipa || !ipa->ipa_type)
eba599a3 1500 return bputs(buf, "(null)");
8e2c653e 1501
2c5b4d80
DL
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
bde30e78 1517 case IPADDR_NONE:
2c5b4d80
DL
1518 break;
1519 }
1520 }
1521
212e04e5
DL
1522 ipaddr2str(ipa, cbuf, sizeof(cbuf));
1523 return bputs(buf, cbuf);
dc5d0186
DL
1524}
1525
54929fd3 1526printfrr_ext_autoreg_p("I4", printfrr_i4);
3ea79430
DL
1527static ssize_t printfrr_i4(struct fbuf *buf, struct printfrr_eargs *ea,
1528 const void *ptr)
d52ec572 1529{
212e04e5 1530 char cbuf[INET_ADDRSTRLEN];
2c5b4d80
DL
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 }
212e04e5
DL
1538
1539 if (!ptr)
eba599a3 1540 return bputs(buf, "(null)");
8e2c653e 1541
2c5b4d80
DL
1542 if (use_star && !memcmp(ptr, &zero, sizeof(zero)))
1543 return bputch(buf, '*');
1544
212e04e5
DL
1545 inet_ntop(AF_INET, ptr, cbuf, sizeof(cbuf));
1546 return bputs(buf, cbuf);
d52ec572
DL
1547}
1548
54929fd3 1549printfrr_ext_autoreg_p("I6", printfrr_i6);
3ea79430
DL
1550static ssize_t printfrr_i6(struct fbuf *buf, struct printfrr_eargs *ea,
1551 const void *ptr)
d52ec572 1552{
212e04e5 1553 char cbuf[INET6_ADDRSTRLEN];
2c5b4d80
DL
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 }
212e04e5
DL
1561
1562 if (!ptr)
eba599a3 1563 return bputs(buf, "(null)");
8e2c653e 1564
2c5b4d80
DL
1565 if (use_star && !memcmp(ptr, &zero, sizeof(zero)))
1566 return bputch(buf, '*');
1567
212e04e5
DL
1568 inet_ntop(AF_INET6, ptr, cbuf, sizeof(cbuf));
1569 return bputs(buf, cbuf);
d52ec572
DL
1570}
1571
54929fd3 1572printfrr_ext_autoreg_p("FX", printfrr_pfx);
3ea79430
DL
1573static ssize_t printfrr_pfx(struct fbuf *buf, struct printfrr_eargs *ea,
1574 const void *ptr)
d52ec572 1575{
543a2684
DL
1576 bool host_only = false;
1577
1578 if (ea->fmt[0] == 'h') {
1579 ea->fmt++;
1580 host_only = true;
1581 }
212e04e5
DL
1582
1583 if (!ptr)
eba599a3 1584 return bputs(buf, "(null)");
8e2c653e 1585
543a2684
DL
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 }
d52ec572
DL
1594}
1595
54929fd3 1596printfrr_ext_autoreg_p("PSG4", printfrr_psg);
3ea79430
DL
1597static ssize_t printfrr_psg(struct fbuf *buf, struct printfrr_eargs *ea,
1598 const void *ptr)
d52ec572
DL
1599{
1600 const struct prefix_sg *sg = ptr;
212e04e5 1601 ssize_t ret = 0;
d52ec572 1602
212e04e5 1603 if (!sg)
eba599a3 1604 return bputs(buf, "(null)");
8e2c653e 1605
212e04e5
DL
1606 if (sg->src.s_addr == INADDR_ANY)
1607 ret += bputs(buf, "(*,");
1608 else
1609 ret += bprintfrr(buf, "(%pI4,", &sg->src);
8e2c653e 1610
212e04e5
DL
1611 if (sg->grp.s_addr == INADDR_ANY)
1612 ret += bputs(buf, "*)");
1613 else
1614 ret += bprintfrr(buf, "%pI4)", &sg->grp);
d52ec572 1615
212e04e5 1616 return ret;
d52ec572 1617}