]>
Commit | Line | Data |
---|---|---|
1 | // SPDX-License-Identifier: GPL-2.0-or-later | |
2 | /* | |
3 | * Prefix structure. | |
4 | * Copyright (C) 1998 Kunihiro Ishiguro | |
5 | */ | |
6 | ||
7 | #ifndef _ZEBRA_PREFIX_H | |
8 | #define _ZEBRA_PREFIX_H | |
9 | ||
10 | #ifdef GNU_LINUX | |
11 | #include <net/ethernet.h> | |
12 | #else | |
13 | #include <netinet/if_ether.h> | |
14 | #endif | |
15 | #include "sockunion.h" | |
16 | #include "ipaddr.h" | |
17 | #include "compiler.h" | |
18 | ||
19 | #ifdef __cplusplus | |
20 | extern "C" { | |
21 | #endif | |
22 | ||
23 | #ifndef ETH_ALEN | |
24 | #define ETH_ALEN 6 | |
25 | #endif | |
26 | ||
27 | /* EVPN route types. */ | |
28 | typedef enum { | |
29 | BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */ | |
30 | BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */ | |
31 | BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */ | |
32 | BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */ | |
33 | BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */ | |
34 | } bgp_evpn_route_type; | |
35 | ||
36 | /* value of first byte of ESI */ | |
37 | #define ESI_TYPE_ARBITRARY 0 /* */ | |
38 | #define ESI_TYPE_LACP 1 /* <> */ | |
39 | #define ESI_TYPE_BRIDGE 2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */ | |
40 | #define ESI_TYPE_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */ | |
41 | #define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */ | |
42 | #define ESI_TYPE_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */ | |
43 | ||
44 | #define MAX_ESI {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} | |
45 | ||
46 | ||
47 | #define EVPN_ETH_TAG_BYTES 4 | |
48 | #define ESI_BYTES 10 | |
49 | #define ESI_STR_LEN (3 * ESI_BYTES) | |
50 | #define EVPN_DF_ALG_STR_LEN 24 | |
51 | ||
52 | /* Maximum number of VTEPs per-ES - | |
53 | * XXX - temporary limit for allocating strings etc. | |
54 | */ | |
55 | #define ES_VTEP_MAX_CNT 10 | |
56 | #define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * 16) | |
57 | ||
58 | #define ETHER_ADDR_STRLEN (3*ETH_ALEN) | |
59 | /* | |
60 | * there isn't a portable ethernet address type. We define our | |
61 | * own to simplify internal handling | |
62 | */ | |
63 | struct ethaddr { | |
64 | uint8_t octet[ETH_ALEN]; | |
65 | } __attribute__((packed)); | |
66 | ||
67 | ||
68 | /* length is the number of valuable bits of prefix structure | |
69 | * 18 bytes is current length in structure, if address is ipv4 | |
70 | * 30 bytes is in case of ipv6 | |
71 | */ | |
72 | #define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8) | |
73 | #define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8) | |
74 | ||
75 | typedef struct esi_t_ { | |
76 | uint8_t val[ESI_BYTES]; | |
77 | } esi_t; | |
78 | ||
79 | struct evpn_ead_addr { | |
80 | esi_t esi; | |
81 | uint32_t eth_tag; | |
82 | struct ipaddr ip; | |
83 | uint16_t frag_id; | |
84 | }; | |
85 | ||
86 | struct evpn_macip_addr { | |
87 | uint32_t eth_tag; | |
88 | uint8_t ip_prefix_length; | |
89 | struct ethaddr mac; | |
90 | struct ipaddr ip; | |
91 | }; | |
92 | ||
93 | struct evpn_imet_addr { | |
94 | uint32_t eth_tag; | |
95 | uint8_t ip_prefix_length; | |
96 | struct ipaddr ip; | |
97 | }; | |
98 | ||
99 | struct evpn_es_addr { | |
100 | esi_t esi; | |
101 | uint8_t ip_prefix_length; | |
102 | struct ipaddr ip; | |
103 | }; | |
104 | ||
105 | struct evpn_prefix_addr { | |
106 | uint32_t eth_tag; | |
107 | uint8_t ip_prefix_length; | |
108 | struct ipaddr ip; | |
109 | }; | |
110 | ||
111 | /* EVPN address (RFC 7432) */ | |
112 | struct evpn_addr { | |
113 | uint8_t route_type; | |
114 | union { | |
115 | struct evpn_ead_addr _ead_addr; | |
116 | struct evpn_macip_addr _macip_addr; | |
117 | struct evpn_imet_addr _imet_addr; | |
118 | struct evpn_es_addr _es_addr; | |
119 | struct evpn_prefix_addr _prefix_addr; | |
120 | } u; | |
121 | #define ead_addr u._ead_addr | |
122 | #define macip_addr u._macip_addr | |
123 | #define imet_addr u._imet_addr | |
124 | #define es_addr u._es_addr | |
125 | #define prefix_addr u._prefix_addr | |
126 | }; | |
127 | ||
128 | /* | |
129 | * A struct prefix contains an address family, a prefix length, and an | |
130 | * address. This can represent either a 'network prefix' as defined | |
131 | * by CIDR, where the 'host bits' of the prefix are 0 | |
132 | * (e.g. AF_INET:10.0.0.0/8), or an address and netmask | |
133 | * (e.g. AF_INET:10.0.0.9/8), such as might be configured on an | |
134 | * interface. | |
135 | */ | |
136 | ||
137 | /* different OSes use different names */ | |
138 | #if defined(AF_PACKET) | |
139 | #define AF_ETHERNET AF_PACKET | |
140 | #else | |
141 | #if defined(AF_LINK) | |
142 | #define AF_ETHERNET AF_LINK | |
143 | #endif | |
144 | #endif | |
145 | ||
146 | /* The 'family' in the prefix structure is internal to FRR and need not | |
147 | * map to standard OS AF_ definitions except where needed for interacting | |
148 | * with the kernel. However, AF_ definitions are currently in use and | |
149 | * prevalent across the code. Define a new FRR-specific AF for EVPN to | |
150 | * distinguish between 'ethernet' (MAC-only) and 'evpn' prefixes and | |
151 | * ensure it does not conflict with any OS AF_ definition. | |
152 | */ | |
153 | #if !defined(AF_EVPN) | |
154 | #define AF_EVPN (AF_MAX + 1) | |
155 | #endif | |
156 | ||
157 | #if !defined(AF_FLOWSPEC) | |
158 | #define AF_FLOWSPEC (AF_MAX + 2) | |
159 | #endif | |
160 | ||
161 | struct flowspec_prefix { | |
162 | uint8_t family; | |
163 | uint16_t prefixlen; /* length in bytes */ | |
164 | uintptr_t ptr; | |
165 | }; | |
166 | ||
167 | /* FRR generic prefix structure. */ | |
168 | struct prefix { | |
169 | uint8_t family; | |
170 | uint16_t prefixlen; | |
171 | union { | |
172 | uint8_t prefix; | |
173 | struct in_addr prefix4; | |
174 | struct in6_addr prefix6; | |
175 | struct { | |
176 | struct in_addr id; | |
177 | struct in_addr adv_router; | |
178 | } lp; | |
179 | struct ethaddr prefix_eth; /* AF_ETHERNET */ | |
180 | uint8_t val[16]; | |
181 | uint32_t val32[4]; | |
182 | uintptr_t ptr; | |
183 | struct evpn_addr prefix_evpn; /* AF_EVPN */ | |
184 | struct flowspec_prefix prefix_flowspec; /* AF_FLOWSPEC */ | |
185 | } u __attribute__((aligned(8))); | |
186 | }; | |
187 | ||
188 | /* IPv4 prefix structure. */ | |
189 | struct prefix_ipv4 { | |
190 | uint8_t family; | |
191 | uint16_t prefixlen; | |
192 | struct in_addr prefix __attribute__((aligned(8))); | |
193 | }; | |
194 | ||
195 | /* IPv6 prefix structure. */ | |
196 | struct prefix_ipv6 { | |
197 | uint8_t family; | |
198 | uint16_t prefixlen; | |
199 | struct in6_addr prefix __attribute__((aligned(8))); | |
200 | }; | |
201 | ||
202 | struct prefix_ls { | |
203 | uint8_t family; | |
204 | uint16_t prefixlen; | |
205 | struct in_addr id __attribute__((aligned(8))); | |
206 | struct in_addr adv_router; | |
207 | }; | |
208 | ||
209 | /* Prefix for routing distinguisher. */ | |
210 | struct prefix_rd { | |
211 | uint8_t family; | |
212 | uint16_t prefixlen; | |
213 | uint8_t val[8] __attribute__((aligned(8))); | |
214 | }; | |
215 | ||
216 | /* Prefix for ethernet. */ | |
217 | struct prefix_eth { | |
218 | uint8_t family; | |
219 | uint16_t prefixlen; | |
220 | struct ethaddr eth_addr __attribute__((aligned(8))); /* AF_ETHERNET */ | |
221 | }; | |
222 | ||
223 | /* EVPN prefix structure. */ | |
224 | struct prefix_evpn { | |
225 | uint8_t family; | |
226 | uint16_t prefixlen; | |
227 | struct evpn_addr prefix __attribute__((aligned(8))); | |
228 | }; | |
229 | ||
230 | static inline int is_evpn_prefix_ipaddr_none(const struct prefix_evpn *evp) | |
231 | { | |
232 | if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) | |
233 | return IS_IPADDR_NONE(&(evp)->prefix.ead_addr.ip); | |
234 | if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) | |
235 | return IS_IPADDR_NONE(&(evp)->prefix.macip_addr.ip); | |
236 | if (evp->prefix.route_type == BGP_EVPN_IMET_ROUTE) | |
237 | return IS_IPADDR_NONE(&(evp)->prefix.imet_addr.ip); | |
238 | if (evp->prefix.route_type == BGP_EVPN_ES_ROUTE) | |
239 | return IS_IPADDR_NONE(&(evp)->prefix.es_addr.ip); | |
240 | if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) | |
241 | return IS_IPADDR_NONE(&(evp)->prefix.prefix_addr.ip); | |
242 | return 0; | |
243 | } | |
244 | ||
245 | static inline int is_evpn_prefix_ipaddr_v4(const struct prefix_evpn *evp) | |
246 | { | |
247 | if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) | |
248 | return IS_IPADDR_V4(&(evp)->prefix.ead_addr.ip); | |
249 | if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) | |
250 | return IS_IPADDR_V4(&(evp)->prefix.macip_addr.ip); | |
251 | if (evp->prefix.route_type == BGP_EVPN_IMET_ROUTE) | |
252 | return IS_IPADDR_V4(&(evp)->prefix.imet_addr.ip); | |
253 | if (evp->prefix.route_type == BGP_EVPN_ES_ROUTE) | |
254 | return IS_IPADDR_V4(&(evp)->prefix.es_addr.ip); | |
255 | if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) | |
256 | return IS_IPADDR_V4(&(evp)->prefix.prefix_addr.ip); | |
257 | return 0; | |
258 | } | |
259 | ||
260 | static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp) | |
261 | { | |
262 | if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) | |
263 | return IS_IPADDR_V6(&(evp)->prefix.ead_addr.ip); | |
264 | if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) | |
265 | return IS_IPADDR_V6(&(evp)->prefix.macip_addr.ip); | |
266 | if (evp->prefix.route_type == BGP_EVPN_IMET_ROUTE) | |
267 | return IS_IPADDR_V6(&(evp)->prefix.imet_addr.ip); | |
268 | if (evp->prefix.route_type == BGP_EVPN_ES_ROUTE) | |
269 | return IS_IPADDR_V6(&(evp)->prefix.es_addr.ip); | |
270 | if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) | |
271 | return IS_IPADDR_V6(&(evp)->prefix.prefix_addr.ip); | |
272 | return 0; | |
273 | } | |
274 | ||
275 | /* Prefix for a Flowspec entry */ | |
276 | struct prefix_fs { | |
277 | uint8_t family; | |
278 | uint16_t prefixlen; /* unused */ | |
279 | struct flowspec_prefix prefix __attribute__((aligned(8))); | |
280 | }; | |
281 | ||
282 | struct prefix_sg { | |
283 | uint8_t family; | |
284 | uint16_t prefixlen; | |
285 | struct in_addr src __attribute__((aligned(8))); | |
286 | struct in_addr grp; | |
287 | }; | |
288 | ||
289 | union prefixptr { | |
290 | prefixtype(prefixptr, struct prefix, p) | |
291 | prefixtype(prefixptr, struct prefix_ipv4, p4) | |
292 | prefixtype(prefixptr, struct prefix_ipv6, p6) | |
293 | prefixtype(prefixptr, struct prefix_evpn, evp) | |
294 | prefixtype(prefixptr, struct prefix_fs, fs) | |
295 | prefixtype(prefixptr, struct prefix_rd, rd) | |
296 | } TRANSPARENT_UNION; | |
297 | ||
298 | union prefixconstptr { | |
299 | prefixtype(prefixconstptr, const struct prefix, p) | |
300 | prefixtype(prefixconstptr, const struct prefix_ipv4, p4) | |
301 | prefixtype(prefixconstptr, const struct prefix_ipv6, p6) | |
302 | prefixtype(prefixconstptr, const struct prefix_evpn, evp) | |
303 | prefixtype(prefixconstptr, const struct prefix_fs, fs) | |
304 | prefixtype(prefixconstptr, const struct prefix_rd, rd) | |
305 | } TRANSPARENT_UNION; | |
306 | ||
307 | #ifndef INET_ADDRSTRLEN | |
308 | #define INET_ADDRSTRLEN 16 | |
309 | #endif /* INET_ADDRSTRLEN */ | |
310 | ||
311 | #ifndef INET6_ADDRSTRLEN | |
312 | /* dead:beef:dead:beef:dead:beef:dead:beef + \0 */ | |
313 | #define INET6_ADDRSTRLEN 46 | |
314 | #endif /* INET6_ADDRSTRLEN */ | |
315 | ||
316 | #ifndef INET6_BUFSIZ | |
317 | #define INET6_BUFSIZ 53 | |
318 | #endif /* INET6_BUFSIZ */ | |
319 | ||
320 | /* Maximum string length of the result of prefix2str */ | |
321 | #define PREFIX_STRLEN 80 | |
322 | ||
323 | /* | |
324 | * Longest possible length of a (S,G) string is 34 bytes | |
325 | * 123.123.123.123 = 15 * 2 | |
326 | * (,) = 3 | |
327 | * NULL Character at end = 1 | |
328 | * (123.123.123.123,123.123.123.123) | |
329 | */ | |
330 | #define PREFIX_SG_STR_LEN 34 | |
331 | ||
332 | /* Max bit/byte length of IPv4 address. */ | |
333 | #define IPV4_MAX_BYTELEN 4 | |
334 | #define IPV4_MAX_BITLEN 32 | |
335 | #define IPV4_ADDR_CMP(D,S) memcmp ((D), (S), IPV4_MAX_BYTELEN) | |
336 | ||
337 | static inline bool ipv4_addr_same(const struct in_addr *a, | |
338 | const struct in_addr *b) | |
339 | { | |
340 | return (a->s_addr == b->s_addr); | |
341 | } | |
342 | #define IPV4_ADDR_SAME(A,B) ipv4_addr_same((A), (B)) | |
343 | ||
344 | static inline void ipv4_addr_copy(struct in_addr *dst, | |
345 | const struct in_addr *src) | |
346 | { | |
347 | dst->s_addr = src->s_addr; | |
348 | } | |
349 | #define IPV4_ADDR_COPY(D,S) ipv4_addr_copy((D), (S)) | |
350 | ||
351 | #define IPV4_NET0(a) ((((uint32_t)(a)) & 0xff000000) == 0x00000000) | |
352 | #define IPV4_NET127(a) ((((uint32_t)(a)) & 0xff000000) == 0x7f000000) | |
353 | #define IPV4_LINKLOCAL(a) ((((uint32_t)(a)) & 0xffff0000) == 0xa9fe0000) | |
354 | #define IPV4_CLASS_D(a) ((((uint32_t)(a)) & 0xf0000000) == 0xe0000000) | |
355 | #define IPV4_CLASS_E(a) ((((uint32_t)(a)) & 0xf0000000) == 0xf0000000) | |
356 | #define IPV4_CLASS_DE(a) ((((uint32_t)(a)) & 0xe0000000) == 0xe0000000) | |
357 | #define IPV4_MC_LINKLOCAL(a) ((((uint32_t)(a)) & 0xffffff00) == 0xe0000000) | |
358 | ||
359 | /* Max bit/byte length of IPv6 address. */ | |
360 | #define IPV6_MAX_BYTELEN 16 | |
361 | #define IPV6_MAX_BITLEN 128 | |
362 | #define IPV6_ADDR_CMP(D,S) memcmp ((D), (S), IPV6_MAX_BYTELEN) | |
363 | #define IPV6_ADDR_SAME(D,S) (memcmp ((D), (S), IPV6_MAX_BYTELEN) == 0) | |
364 | #define IPV6_ADDR_COPY(D,S) memcpy ((D), (S), IPV6_MAX_BYTELEN) | |
365 | ||
366 | /* Count prefix size from mask length */ | |
367 | #define PSIZE(a) (((a) + 7) / (8)) | |
368 | ||
369 | #define BSIZE(a) ((a) * (8)) | |
370 | ||
371 | /* Prefix's family member. */ | |
372 | #define PREFIX_FAMILY(p) ((p)->family) | |
373 | ||
374 | /* glibc defines s6_addr32 to __in6_u.__u6_addr32 if __USE_{MISC || GNU} */ | |
375 | #ifndef s6_addr32 | |
376 | #define s6_addr32 __u6_addr.__u6_addr32 | |
377 | #endif /*s6_addr32*/ | |
378 | ||
379 | /* Prototypes. */ | |
380 | extern int str2family(const char *); | |
381 | extern int afi2family(afi_t); | |
382 | extern afi_t family2afi(int); | |
383 | extern const char *family2str(int family); | |
384 | extern const char *safi2str(safi_t safi); | |
385 | extern const char *afi2str(afi_t afi); | |
386 | extern const char *afi2str_lower(afi_t afi); | |
387 | ||
388 | static inline afi_t prefix_afi(union prefixconstptr pu) | |
389 | { | |
390 | return family2afi(pu.p->family); | |
391 | } | |
392 | ||
393 | /* | |
394 | * Check bit of the prefix. | |
395 | * | |
396 | * prefix | |
397 | * byte buffer | |
398 | * | |
399 | * bit_index | |
400 | * which bit to fetch from byte buffer, 0 indexed. | |
401 | */ | |
402 | extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t bit_index); | |
403 | ||
404 | extern struct prefix *prefix_new(void); | |
405 | extern void prefix_free(struct prefix **p); | |
406 | /* | |
407 | * Function to handle prefix_free being used as a del function. | |
408 | */ | |
409 | extern void prefix_free_lists(void *arg); | |
410 | extern const char *prefix_family_str(union prefixconstptr pu); | |
411 | extern int prefix_blen(union prefixconstptr pu); | |
412 | extern int str2prefix(const char *, struct prefix *); | |
413 | ||
414 | #define PREFIX2STR_BUFFER PREFIX_STRLEN | |
415 | ||
416 | extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr, | |
417 | char *buf, int buf_size); | |
418 | extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str); | |
419 | extern const char *prefix2str(union prefixconstptr, char *, int); | |
420 | extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx, | |
421 | const struct prefix *match_pfx); | |
422 | extern int prefix_match(union prefixconstptr unet, union prefixconstptr upfx); | |
423 | extern int prefix_match_network_statement(union prefixconstptr unet, | |
424 | union prefixconstptr upfx); | |
425 | extern int prefix_same(union prefixconstptr ua, union prefixconstptr ub); | |
426 | extern int prefix_cmp(union prefixconstptr ua, union prefixconstptr ub); | |
427 | extern int prefix_common_bits(union prefixconstptr ua, union prefixconstptr ub); | |
428 | extern void prefix_copy(union prefixptr udst, union prefixconstptr usrc); | |
429 | extern void apply_mask(union prefixptr pu); | |
430 | ||
431 | #ifdef __clang_analyzer__ | |
432 | /* clang-SA doesn't understand transparent unions, making it think that the | |
433 | * target of prefix_copy is uninitialized. So just memset the target. | |
434 | * cf. https://bugs.llvm.org/show_bug.cgi?id=42811 | |
435 | */ | |
436 | #define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); }) | |
437 | #endif | |
438 | ||
439 | extern struct prefix *sockunion2hostprefix(const union sockunion *, | |
440 | struct prefix *p); | |
441 | extern void prefix2sockunion(const struct prefix *, union sockunion *); | |
442 | ||
443 | extern int str2prefix_eth(const char *, struct prefix_eth *); | |
444 | ||
445 | extern struct prefix_ipv4 *prefix_ipv4_new(void); | |
446 | extern void prefix_ipv4_free(struct prefix_ipv4 **p); | |
447 | extern int str2prefix_ipv4(const char *, struct prefix_ipv4 *); | |
448 | extern void apply_mask_ipv4(struct prefix_ipv4 *); | |
449 | ||
450 | extern int prefix_ipv4_any(const struct prefix_ipv4 *); | |
451 | extern void apply_classful_mask_ipv4(struct prefix_ipv4 *); | |
452 | ||
453 | extern uint8_t ip_masklen(struct in_addr); | |
454 | extern void masklen2ip(const int, struct in_addr *); | |
455 | /* given the address of a host on a network and the network mask length, | |
456 | * calculate the broadcast address for that network; | |
457 | * special treatment for /31 according to RFC3021 section 3.3 */ | |
458 | extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen); | |
459 | ||
460 | extern int netmask_str2prefix_str(const char *, const char *, char *, size_t); | |
461 | ||
462 | extern struct prefix_ipv6 *prefix_ipv6_new(void); | |
463 | extern void prefix_ipv6_free(struct prefix_ipv6 **p); | |
464 | extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *); | |
465 | extern void apply_mask_ipv6(struct prefix_ipv6 *); | |
466 | ||
467 | extern int ip6_masklen(struct in6_addr); | |
468 | extern void masklen2ip6(const int, struct in6_addr *); | |
469 | ||
470 | extern int is_zero_mac(const struct ethaddr *mac); | |
471 | extern bool is_mcast_mac(const struct ethaddr *mac); | |
472 | extern bool is_bcast_mac(const struct ethaddr *mac); | |
473 | extern int prefix_str2mac(const char *str, struct ethaddr *mac); | |
474 | extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size); | |
475 | ||
476 | extern unsigned prefix_hash_key(const void *pp); | |
477 | ||
478 | extern int str_to_esi(const char *str, esi_t *esi); | |
479 | extern char *esi_to_str(const esi_t *esi, char *buf, int size); | |
480 | extern char *evpn_es_df_alg2str(uint8_t df_alg, char *buf, int buf_len); | |
481 | extern void prefix_evpn_hexdump(const struct prefix_evpn *p); | |
482 | extern bool ipv4_unicast_valid(const struct in_addr *addr); | |
483 | extern int evpn_prefix2prefix(const struct prefix *evpn, struct prefix *to); | |
484 | ||
485 | static inline int ipv6_martian(const struct in6_addr *addr) | |
486 | { | |
487 | struct in6_addr localhost_addr; | |
488 | ||
489 | inet_pton(AF_INET6, "::1", &localhost_addr); | |
490 | ||
491 | if (IPV6_ADDR_SAME(&localhost_addr, addr)) | |
492 | return 1; | |
493 | ||
494 | return 0; | |
495 | } | |
496 | ||
497 | extern int macstr2prefix_evpn(const char *str, struct prefix_evpn *p); | |
498 | ||
499 | /* NOTE: This routine expects the address argument in network byte order. */ | |
500 | static inline bool ipv4_martian(const struct in_addr *addr) | |
501 | { | |
502 | if (!ipv4_unicast_valid(addr)) | |
503 | return true; | |
504 | return false; | |
505 | } | |
506 | ||
507 | static inline bool is_default_prefix4(const struct prefix_ipv4 *p) | |
508 | { | |
509 | return p && p->family == AF_INET && p->prefixlen == 0 | |
510 | && p->prefix.s_addr == INADDR_ANY; | |
511 | } | |
512 | ||
513 | static inline bool is_default_prefix6(const struct prefix_ipv6 *p) | |
514 | { | |
515 | return p && p->family == AF_INET6 && p->prefixlen == 0 | |
516 | && memcmp(&p->prefix, &in6addr_any, sizeof(struct in6_addr)) | |
517 | == 0; | |
518 | } | |
519 | ||
520 | static inline bool is_default_prefix(const struct prefix *p) | |
521 | { | |
522 | if (p == NULL) | |
523 | return false; | |
524 | ||
525 | switch (p->family) { | |
526 | case AF_INET: | |
527 | return is_default_prefix4((const struct prefix_ipv4 *)p); | |
528 | case AF_INET6: | |
529 | return is_default_prefix6((const struct prefix_ipv6 *)p); | |
530 | } | |
531 | ||
532 | return false; | |
533 | } | |
534 | ||
535 | static inline int is_host_route(const struct prefix *p) | |
536 | { | |
537 | if (p->family == AF_INET) | |
538 | return (p->prefixlen == IPV4_MAX_BITLEN); | |
539 | else if (p->family == AF_INET6) | |
540 | return (p->prefixlen == IPV6_MAX_BITLEN); | |
541 | return 0; | |
542 | } | |
543 | ||
544 | static inline int is_default_host_route(const struct prefix *p) | |
545 | { | |
546 | if (p->family == AF_INET) { | |
547 | return (p->u.prefix4.s_addr == INADDR_ANY && | |
548 | p->prefixlen == IPV4_MAX_BITLEN); | |
549 | } else if (p->family == AF_INET6) { | |
550 | return ((!memcmp(&p->u.prefix6, &in6addr_any, | |
551 | sizeof(struct in6_addr))) && | |
552 | p->prefixlen == IPV6_MAX_BITLEN); | |
553 | } | |
554 | return 0; | |
555 | } | |
556 | ||
557 | static inline bool is_ipv6_global_unicast(const struct in6_addr *p) | |
558 | { | |
559 | if (IN6_IS_ADDR_UNSPECIFIED(p) || IN6_IS_ADDR_LOOPBACK(p) || | |
560 | IN6_IS_ADDR_LINKLOCAL(p) || IN6_IS_ADDR_MULTICAST(p)) | |
561 | return false; | |
562 | ||
563 | return true; | |
564 | } | |
565 | ||
566 | /* IPv6 scope values, usable for IPv4 too (cf. below) */ | |
567 | /* clang-format off */ | |
568 | enum { | |
569 | /* 0: reserved */ | |
570 | MCAST_SCOPE_IFACE = 0x1, | |
571 | MCAST_SCOPE_LINK = 0x2, | |
572 | MCAST_SCOPE_REALM = 0x3, | |
573 | MCAST_SCOPE_ADMIN = 0x4, | |
574 | MCAST_SCOPE_SITE = 0x5, | |
575 | /* 6-7: unassigned */ | |
576 | MCAST_SCOPE_ORG = 0x8, | |
577 | /* 9-d: unassigned */ | |
578 | MCAST_SCOPE_GLOBAL = 0xe, | |
579 | /* f: reserved */ | |
580 | }; | |
581 | /* clang-format on */ | |
582 | ||
583 | static inline uint8_t ipv6_mcast_scope(const struct in6_addr *addr) | |
584 | { | |
585 | return addr->s6_addr[1] & 0xf; | |
586 | } | |
587 | ||
588 | static inline bool ipv6_mcast_nofwd(const struct in6_addr *addr) | |
589 | { | |
590 | return (addr->s6_addr[1] & 0xf) <= MCAST_SCOPE_LINK; | |
591 | } | |
592 | ||
593 | static inline bool ipv6_mcast_ssm(const struct in6_addr *addr) | |
594 | { | |
595 | uint32_t bits = ntohl(addr->s6_addr32[0]); | |
596 | ||
597 | /* ff3x:0000::/32 */ | |
598 | return (bits & 0xfff0ffff) == 0xff300000; | |
599 | } | |
600 | ||
601 | static inline bool ipv6_mcast_reserved(const struct in6_addr *addr) | |
602 | { | |
603 | uint32_t bits = ntohl(addr->s6_addr32[0]); | |
604 | ||
605 | /* ffx2::/16 */ | |
606 | return (bits & 0xff0fffff) == 0xff020000; | |
607 | } | |
608 | ||
609 | static inline uint8_t ipv4_mcast_scope(const struct in_addr *addr) | |
610 | { | |
611 | uint32_t bits = ntohl(addr->s_addr); | |
612 | ||
613 | /* 224.0.0.0/24 - link scope */ | |
614 | if ((bits & 0xffffff00) == 0xe0000000) | |
615 | return MCAST_SCOPE_LINK; | |
616 | /* 239.0.0.0/8 - org scope */ | |
617 | if ((bits & 0xff000000) == 0xef000000) | |
618 | return MCAST_SCOPE_ORG; | |
619 | ||
620 | return MCAST_SCOPE_GLOBAL; | |
621 | } | |
622 | ||
623 | static inline bool ipv4_mcast_nofwd(const struct in_addr *addr) | |
624 | { | |
625 | uint32_t bits = ntohl(addr->s_addr); | |
626 | ||
627 | /* 224.0.0.0/24 */ | |
628 | return (bits & 0xffffff00) == 0xe0000000; | |
629 | } | |
630 | ||
631 | static inline bool ipv4_mcast_ssm(const struct in_addr *addr) | |
632 | { | |
633 | uint32_t bits = ntohl(addr->s_addr); | |
634 | ||
635 | /* 232.0.0.0/8 */ | |
636 | return (bits & 0xff000000) == 0xe8000000; | |
637 | } | |
638 | ||
639 | #ifdef _FRR_ATTRIBUTE_PRINTFRR | |
640 | #pragma FRR printfrr_ext "%pEA" (struct ethaddr *) | |
641 | ||
642 | #pragma FRR printfrr_ext "%pI4" (struct in_addr *) | |
643 | #pragma FRR printfrr_ext "%pI4" (in_addr_t *) | |
644 | ||
645 | #pragma FRR printfrr_ext "%pI6" (struct in6_addr *) | |
646 | ||
647 | #pragma FRR printfrr_ext "%pFX" (struct prefix *) | |
648 | #pragma FRR printfrr_ext "%pFX" (struct prefix_ipv4 *) | |
649 | #pragma FRR printfrr_ext "%pFX" (struct prefix_ipv6 *) | |
650 | #pragma FRR printfrr_ext "%pFX" (struct prefix_eth *) | |
651 | #pragma FRR printfrr_ext "%pFX" (struct prefix_evpn *) | |
652 | #pragma FRR printfrr_ext "%pFX" (struct prefix_fs *) | |
653 | #pragma FRR printfrr_ext "%pRDP" (struct prefix_rd *) | |
654 | /* RD with AS4B with dot and dot+ format */ | |
655 | #pragma FRR printfrr_ext "%pRDD" (struct prefix_rd *) | |
656 | #pragma FRR printfrr_ext "%pRDE" (struct prefix_rd *) | |
657 | ||
658 | #pragma FRR printfrr_ext "%pPSG4" (struct prefix_sg *) | |
659 | #endif | |
660 | ||
661 | #ifdef __cplusplus | |
662 | } | |
663 | #endif | |
664 | ||
665 | #endif /* _ZEBRA_PREFIX_H */ |