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