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