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