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