]>
Commit | Line | Data |
---|---|---|
fe9f1a6d OZ |
1 | /* |
2 | * BIRD Internet Routing Daemon -- Network addresses | |
3 | * | |
4 | * (c) 2015 Ondrej Zajicek <santiago@crfreenet.org> | |
5 | * (c) 2015 CZ.NIC z.s.p.o. | |
6 | * | |
7 | * Can be freely distributed and used under the terms of the GNU GPL. | |
8 | */ | |
9 | ||
10 | #ifndef _BIRD_NET_H_ | |
11 | #define _BIRD_NET_H_ | |
12 | ||
13 | #include "lib/ip.h" | |
14 | ||
15 | ||
16 | #define NET_IP4 1 | |
17 | #define NET_IP6 2 | |
18 | #define NET_VPN4 3 | |
19 | #define NET_VPN6 4 | |
de9b87f5 PT |
20 | #define NET_ROA4 5 |
21 | #define NET_ROA6 6 | |
77234bbb OZ |
22 | #define NET_FLOW4 7 |
23 | #define NET_FLOW6 8 | |
be17805c OZ |
24 | #define NET_IP6_SADR 9 |
25 | #define NET_MPLS 10 | |
26 | #define NET_MAX 11 | |
fe9f1a6d | 27 | |
f4a60a9b OZ |
28 | #define NB_IP4 (1 << NET_IP4) |
29 | #define NB_IP6 (1 << NET_IP6) | |
30 | #define NB_VPN4 (1 << NET_VPN4) | |
31 | #define NB_VPN6 (1 << NET_VPN6) | |
286e2011 OZ |
32 | #define NB_ROA4 (1 << NET_ROA4) |
33 | #define NB_ROA6 (1 << NET_ROA6) | |
77234bbb OZ |
34 | #define NB_FLOW4 (1 << NET_FLOW4) |
35 | #define NB_FLOW6 (1 << NET_FLOW6) | |
be17805c | 36 | #define NB_IP6_SADR (1 << NET_IP6_SADR) |
33ad6e01 | 37 | #define NB_MPLS (1 << NET_MPLS) |
f4a60a9b OZ |
38 | |
39 | #define NB_IP (NB_IP4 | NB_IP6) | |
1e37e35c OZ |
40 | #define NB_VPN (NB_VPN4 | NB_VPN6) |
41 | #define NB_FLOW (NB_FLOW4 | NB_FLOW6) | |
be17805c | 42 | #define NB_DEST (NB_IP | NB_IP6_SADR | NB_VPN | NB_MPLS) |
f4a60a9b OZ |
43 | #define NB_ANY 0xffffffff |
44 | ||
45 | ||
fe9f1a6d OZ |
46 | typedef struct net_addr { |
47 | u8 type; | |
48 | u8 pxlen; | |
49 | u16 length; | |
67a2eb91 | 50 | u8 data[20]; |
fe9f1a6d | 51 | u64 align[0]; |
fe9f1a6d OZ |
52 | } net_addr; |
53 | ||
54 | typedef struct net_addr_ip4 { | |
55 | u8 type; | |
56 | u8 pxlen; | |
57 | u16 length; | |
58 | ip4_addr prefix; | |
59 | } net_addr_ip4; | |
60 | ||
61 | typedef struct net_addr_ip6 { | |
62 | u8 type; | |
63 | u8 pxlen; | |
64 | u16 length; | |
65 | ip6_addr prefix; | |
66 | } net_addr_ip6; | |
67 | ||
68 | typedef struct net_addr_vpn4 { | |
69 | u8 type; | |
70 | u8 pxlen; | |
71 | u16 length; | |
72 | ip4_addr prefix; | |
73 | u64 rd; | |
74 | } net_addr_vpn4; | |
75 | ||
76 | typedef struct net_addr_vpn6 { | |
77 | u8 type; | |
78 | u8 pxlen; | |
79 | u16 length; | |
80 | ip6_addr prefix; | |
67a2eb91 | 81 | u32 padding; |
fe9f1a6d OZ |
82 | u64 rd; |
83 | } net_addr_vpn6; | |
84 | ||
de9b87f5 PT |
85 | typedef struct net_addr_roa4 { |
86 | u8 type; | |
87 | u8 pxlen; | |
88 | u16 length; | |
89 | ip4_addr prefix; | |
f9d729ab | 90 | u32 max_pxlen; |
de9b87f5 | 91 | u32 asn; |
de9b87f5 PT |
92 | } net_addr_roa4; |
93 | ||
94 | typedef struct net_addr_roa6 { | |
95 | u8 type; | |
96 | u8 pxlen; | |
97 | u16 length; | |
98 | ip6_addr prefix; | |
f9d729ab | 99 | u32 max_pxlen; |
de9b87f5 | 100 | u32 asn; |
de9b87f5 | 101 | } net_addr_roa6; |
fe9f1a6d | 102 | |
77234bbb OZ |
103 | typedef struct net_addr_flow4 { |
104 | u8 type; | |
105 | u8 pxlen; | |
106 | u16 length; | |
107 | ip4_addr prefix; | |
108 | byte data[0]; | |
109 | } net_addr_flow4; | |
110 | ||
111 | typedef struct net_addr_flow6 { | |
112 | u8 type; | |
113 | u8 pxlen; | |
114 | u16 length; | |
115 | ip6_addr prefix; | |
116 | byte data[0]; | |
117 | } net_addr_flow6; | |
118 | ||
33ad6e01 MM |
119 | typedef struct net_addr_mpls { |
120 | u8 type; | |
121 | u8 pxlen; | |
122 | u16 length; | |
123 | u32 label; | |
124 | } net_addr_mpls; | |
125 | ||
be17805c OZ |
126 | typedef struct net_addr_ip6_sadr { |
127 | u8 type; | |
128 | u8 dst_pxlen; | |
129 | u16 length; | |
130 | ip6_addr dst_prefix; | |
131 | s32 src_pxlen; /* s32 to avoid padding */ | |
132 | ip6_addr src_prefix; | |
133 | } net_addr_ip6_sadr; | |
134 | ||
fe9f1a6d OZ |
135 | typedef union net_addr_union { |
136 | net_addr n; | |
137 | net_addr_ip4 ip4; | |
138 | net_addr_ip6 ip6; | |
139 | net_addr_vpn4 vpn4; | |
140 | net_addr_vpn6 vpn6; | |
de9b87f5 PT |
141 | net_addr_roa4 roa4; |
142 | net_addr_roa6 roa6; | |
77234bbb OZ |
143 | net_addr_flow4 flow4; |
144 | net_addr_flow6 flow6; | |
be17805c | 145 | net_addr_ip6_sadr ip6_sadr; |
33ad6e01 | 146 | net_addr_mpls mpls; |
fe9f1a6d OZ |
147 | } net_addr_union; |
148 | ||
149 | ||
f4a60a9b | 150 | extern const char * const net_label[]; |
fe9f1a6d | 151 | extern const u16 net_addr_length[]; |
7fd4143e MM |
152 | extern const u8 net_max_prefix_length[]; |
153 | extern const u16 net_max_text_length[]; | |
154 | ||
77234bbb | 155 | #define NET_MAX_TEXT_LENGTH 256 |
7fd4143e | 156 | |
fe9f1a6d OZ |
157 | |
158 | #define NET_ADDR_IP4(prefix,pxlen) \ | |
159 | ((net_addr_ip4) { NET_IP4, pxlen, sizeof(net_addr_ip4), prefix }) | |
160 | ||
161 | #define NET_ADDR_IP6(prefix,pxlen) \ | |
162 | ((net_addr_ip6) { NET_IP6, pxlen, sizeof(net_addr_ip6), prefix }) | |
163 | ||
164 | #define NET_ADDR_VPN4(prefix,pxlen,rd) \ | |
165 | ((net_addr_vpn4) { NET_VPN4, pxlen, sizeof(net_addr_vpn4), prefix, rd }) | |
166 | ||
167 | #define NET_ADDR_VPN6(prefix,pxlen,rd) \ | |
67a2eb91 | 168 | ((net_addr_vpn6) { NET_VPN6, pxlen, sizeof(net_addr_vpn6), prefix, 0, rd }) |
fe9f1a6d | 169 | |
a820ae10 PT |
170 | #define NET_ADDR_ROA4(prefix,pxlen,max_pxlen,asn) \ |
171 | ((net_addr_roa4) { NET_ROA4, pxlen, sizeof(net_addr_roa4), prefix, max_pxlen, asn }) | |
172 | ||
173 | #define NET_ADDR_ROA6(prefix,pxlen,max_pxlen,asn) \ | |
174 | ((net_addr_roa6) { NET_ROA6, pxlen, sizeof(net_addr_roa6), prefix, max_pxlen, asn }) | |
175 | ||
77234bbb OZ |
176 | #define NET_ADDR_FLOW4(prefix,pxlen,dlen) \ |
177 | ((net_addr_flow4) { NET_FLOW4, pxlen, sizeof(net_addr_ip4) + dlen, prefix }) | |
178 | ||
179 | #define NET_ADDR_FLOW6(prefix,pxlen,dlen) \ | |
180 | ((net_addr_flow6) { NET_FLOW6, pxlen, sizeof(net_addr_ip6) + dlen, prefix }) | |
181 | ||
be17805c OZ |
182 | #define NET_ADDR_IP6_SADR(dst_prefix,dst_pxlen,src_prefix,src_pxlen) \ |
183 | ((net_addr_ip6_sadr) { NET_IP6_SADR, dst_pxlen, sizeof(net_addr_ip6_sadr), dst_prefix, src_pxlen, src_prefix }) | |
184 | ||
33ad6e01 MM |
185 | #define NET_ADDR_MPLS(label) \ |
186 | ((net_addr_mpls) { NET_MPLS, 20, sizeof(net_addr_mpls), label }) | |
a820ae10 | 187 | |
fe9f1a6d OZ |
188 | |
189 | static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen) | |
190 | { *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); } | |
191 | ||
192 | static inline void net_fill_ip6(net_addr *a, ip6_addr prefix, uint pxlen) | |
193 | { *(net_addr_ip6 *)a = NET_ADDR_IP6(prefix, pxlen); } | |
194 | ||
195 | static inline void net_fill_vpn4(net_addr *a, ip4_addr prefix, uint pxlen, u64 rd) | |
196 | { *(net_addr_vpn4 *)a = NET_ADDR_VPN4(prefix, pxlen, rd); } | |
197 | ||
198 | static inline void net_fill_vpn6(net_addr *a, ip6_addr prefix, uint pxlen, u64 rd) | |
199 | { *(net_addr_vpn6 *)a = NET_ADDR_VPN6(prefix, pxlen, rd); } | |
200 | ||
a820ae10 PT |
201 | static inline void net_fill_roa4(net_addr *a, ip4_addr prefix, uint pxlen, uint max_pxlen, u32 asn) |
202 | { *(net_addr_roa4 *)a = NET_ADDR_ROA4(prefix, pxlen, max_pxlen, asn); } | |
203 | ||
204 | static inline void net_fill_roa6(net_addr *a, ip6_addr prefix, uint pxlen, uint max_pxlen, u32 asn) | |
205 | { *(net_addr_roa6 *)a = NET_ADDR_ROA6(prefix, pxlen, max_pxlen, asn); } | |
206 | ||
be17805c OZ |
207 | static inline void net_fill_ip6_sadr(net_addr *a, ip6_addr dst_prefix, uint dst_pxlen, ip6_addr src_prefix, uint src_pxlen) |
208 | { *(net_addr_ip6_sadr *)a = NET_ADDR_IP6_SADR(dst_prefix, dst_pxlen, src_prefix, src_pxlen); } | |
209 | ||
33ad6e01 MM |
210 | static inline void net_fill_mpls(net_addr *a, u32 label) |
211 | { *(net_addr_mpls *)a = NET_ADDR_MPLS(label); } | |
212 | ||
fe9f1a6d OZ |
213 | static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen) |
214 | { | |
215 | if (ipa_is_ip4(prefix)) | |
216 | net_fill_ip4(a, ipa_to_ip4(prefix), pxlen); | |
217 | else | |
218 | net_fill_ip6(a, ipa_to_ip6(prefix), pxlen); | |
219 | } | |
220 | ||
04632fd7 OZ |
221 | static inline void net_fill_ip_host(net_addr *a, ip_addr prefix) |
222 | { | |
223 | if (ipa_is_ip4(prefix)) | |
224 | net_fill_ip4(a, ipa_to_ip4(prefix), IP4_MAX_PREFIX_LENGTH); | |
225 | else | |
226 | net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH); | |
227 | } | |
228 | ||
77234bbb OZ |
229 | static inline void net_fill_flow4(net_addr *a, ip4_addr prefix, uint pxlen, byte *data, uint dlen) |
230 | { | |
231 | net_addr_flow4 *f = (void *) a; | |
232 | *f = NET_ADDR_FLOW4(prefix, pxlen, dlen); | |
233 | memcpy(f->data, data, dlen); | |
234 | } | |
235 | ||
236 | static inline void net_fill_flow6(net_addr *a, ip6_addr prefix, uint pxlen, byte *data, uint dlen) | |
237 | { | |
238 | net_addr_flow6 *f = (void *) a; | |
239 | *f = NET_ADDR_FLOW6(prefix, pxlen, dlen); | |
240 | memcpy(f->data, data, dlen); | |
241 | } | |
f4a60a9b | 242 | |
be17805c OZ |
243 | /* Make NET_IP6_SADR from NET_IP6, assuming there is enough space */ |
244 | static inline void net_make_ip6_sadr(net_addr *a) | |
245 | { | |
246 | net_addr_ip6_sadr *n = (void *) a; | |
247 | n->type = NET_IP6_SADR; | |
248 | n->length = sizeof(net_addr_ip6_sadr); | |
249 | n->src_pxlen = 0; | |
250 | n->src_prefix = IP6_NONE; | |
251 | } | |
252 | ||
f4a60a9b OZ |
253 | static inline int net_val_match(u8 type, u32 mask) |
254 | { return !!((1 << type) & mask); } | |
255 | ||
256 | static inline int net_type_match(const net_addr *a, u32 mask) | |
257 | { return net_val_match(a->type, mask); } | |
258 | ||
04632fd7 OZ |
259 | static inline int net_is_ip(const net_addr *a) |
260 | { return (a->type == NET_IP4) || (a->type == NET_IP6); } | |
261 | ||
7fc55925 OZ |
262 | static inline int net_is_vpn(const net_addr *a) |
263 | { return (a->type == NET_VPN4) || (a->type == NET_VPN6); } | |
264 | ||
69ae5784 PT |
265 | static inline int net_is_roa(const net_addr *a) |
266 | { return (a->type == NET_ROA4) || (a->type == NET_ROA6); } | |
267 | ||
7fc55925 OZ |
268 | static inline int net_is_flow(const net_addr *a) |
269 | { return (a->type == NET_FLOW4) || (a->type == NET_FLOW6); } | |
8c9986d3 | 270 | |
b24b7811 OZ |
271 | static inline int net_is_sadr(const net_addr *a) |
272 | { return (a->type == NET_IP6_SADR); } | |
7fd4143e | 273 | |
fe9f1a6d OZ |
274 | static inline ip4_addr net4_prefix(const net_addr *a) |
275 | { return ((net_addr_ip4 *) a)->prefix; } | |
276 | ||
277 | static inline ip6_addr net6_prefix(const net_addr *a) | |
278 | { return ((net_addr_ip6 *) a)->prefix; } | |
279 | ||
280 | static inline ip_addr net_prefix(const net_addr *a) | |
281 | { | |
282 | switch (a->type) | |
283 | { | |
284 | case NET_IP4: | |
de9b87f5 PT |
285 | case NET_VPN4: |
286 | case NET_ROA4: | |
77234bbb | 287 | case NET_FLOW4: |
de9b87f5 PT |
288 | return ipa_from_ip4(net4_prefix(a)); |
289 | ||
fe9f1a6d | 290 | case NET_IP6: |
de9b87f5 PT |
291 | case NET_VPN6: |
292 | case NET_ROA6: | |
77234bbb | 293 | case NET_FLOW6: |
be17805c | 294 | case NET_IP6_SADR: |
de9b87f5 PT |
295 | return ipa_from_ip6(net6_prefix(a)); |
296 | ||
33ad6e01 | 297 | case NET_MPLS: |
de9b87f5 PT |
298 | default: |
299 | return IPA_NONE; | |
fe9f1a6d OZ |
300 | } |
301 | } | |
302 | ||
d14f8c3c MM |
303 | static inline u32 net_mpls(const net_addr *a) |
304 | { | |
305 | if (a->type == NET_MPLS) | |
306 | return ((net_addr_mpls *) a)->label; | |
307 | ||
308 | bug("Can't call net_mpls on non-mpls net_addr"); | |
309 | } | |
310 | ||
fe9f1a6d OZ |
311 | static inline uint net4_pxlen(const net_addr *a) |
312 | { return a->pxlen; } | |
313 | ||
314 | static inline uint net6_pxlen(const net_addr *a) | |
315 | { return a->pxlen; } | |
316 | ||
317 | static inline uint net_pxlen(const net_addr *a) | |
318 | { return a->pxlen; } | |
319 | ||
9b136840 MM |
320 | ip_addr net_pxmask(const net_addr *a); |
321 | ||
8c9986d3 MM |
322 | static inline u64 net_rd(const net_addr *a) |
323 | { | |
324 | switch (a->type) | |
325 | { | |
326 | case NET_VPN4: | |
327 | return ((net_addr_vpn4 *)a)->rd; | |
328 | case NET_VPN6: | |
329 | return ((net_addr_vpn6 *)a)->rd; | |
330 | } | |
331 | return 0; | |
332 | } | |
333 | ||
fe9f1a6d OZ |
334 | |
335 | static inline int net_equal(const net_addr *a, const net_addr *b) | |
336 | { return (a->length == b->length) && !memcmp(a, b, a->length); } | |
337 | ||
338 | static inline int net_equal_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) | |
339 | { return !memcmp(a, b, sizeof(net_addr_ip4)); } | |
340 | ||
341 | static inline int net_equal_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) | |
342 | { return !memcmp(a, b, sizeof(net_addr_ip6)); } | |
343 | ||
344 | static inline int net_equal_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b) | |
345 | { return !memcmp(a, b, sizeof(net_addr_vpn4)); } | |
346 | ||
347 | static inline int net_equal_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b) | |
348 | { return !memcmp(a, b, sizeof(net_addr_vpn6)); } | |
349 | ||
de9b87f5 PT |
350 | static inline int net_equal_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) |
351 | { return !memcmp(a, b, sizeof(net_addr_roa4)); } | |
352 | ||
353 | static inline int net_equal_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) | |
354 | { return !memcmp(a, b, sizeof(net_addr_roa6)); } | |
355 | ||
77234bbb OZ |
356 | static inline int net_equal_flow4(const net_addr_flow4 *a, const net_addr_flow4 *b) |
357 | { return net_equal((const net_addr *) a, (const net_addr *) b); } | |
358 | ||
359 | static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b) | |
360 | { return net_equal((const net_addr *) a, (const net_addr *) b); } | |
361 | ||
be17805c OZ |
362 | static inline int net_equal_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) |
363 | { return !memcmp(a, b, sizeof(net_addr_ip6_sadr)); } | |
364 | ||
62e64905 OZ |
365 | static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b) |
366 | { return !memcmp(a, b, sizeof(net_addr_mpls)); } | |
367 | ||
77234bbb | 368 | |
286e2011 OZ |
369 | static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) |
370 | { return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } | |
371 | ||
372 | static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) | |
373 | { return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); } | |
374 | ||
be17805c OZ |
375 | static inline int net_equal_dst_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) |
376 | { return ip6_equal(a->dst_prefix, b->dst_prefix) && (a->dst_pxlen == b->dst_pxlen); } | |
377 | ||
378 | static inline int net_equal_src_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) | |
379 | { return ip6_equal(a->src_prefix, b->src_prefix) && (a->src_pxlen == b->src_pxlen); } | |
380 | ||
fe9f1a6d OZ |
381 | |
382 | static inline int net_zero_ip4(const net_addr_ip4 *a) | |
383 | { return !a->pxlen && ip4_zero(a->prefix); } | |
384 | ||
385 | static inline int net_zero_ip6(const net_addr_ip6 *a) | |
386 | { return !a->pxlen && ip6_zero(a->prefix); } | |
387 | ||
388 | static inline int net_zero_vpn4(const net_addr_vpn4 *a) | |
389 | { return !a->pxlen && ip4_zero(a->prefix) && !a->rd; } | |
390 | ||
391 | static inline int net_zero_vpn6(const net_addr_vpn6 *a) | |
392 | { return !a->pxlen && ip6_zero(a->prefix) && !a->rd; } | |
393 | ||
de9b87f5 | 394 | static inline int net_zero_roa4(const net_addr_roa4 *a) |
a820ae10 | 395 | { return !a->pxlen && ip4_zero(a->prefix) && !a->max_pxlen && !a->asn; } |
de9b87f5 PT |
396 | |
397 | static inline int net_zero_roa6(const net_addr_roa6 *a) | |
a820ae10 | 398 | { return !a->pxlen && ip6_zero(a->prefix) && !a->max_pxlen && !a->asn; } |
de9b87f5 | 399 | |
77234bbb | 400 | static inline int net_zero_flow4(const net_addr_flow4 *a) |
ac48e72b | 401 | { return !a->pxlen && ip4_zero(a->prefix) && (a->length == sizeof(net_addr_flow4)); } |
77234bbb OZ |
402 | |
403 | static inline int net_zero_flow6(const net_addr_flow6 *a) | |
ac48e72b | 404 | { return !a->pxlen && ip6_zero(a->prefix) && (a->length == sizeof(net_addr_flow6)); } |
77234bbb | 405 | |
33ad6e01 MM |
406 | static inline int net_zero_mpls(const net_addr_mpls *a) |
407 | { return !a->label; } | |
77234bbb | 408 | |
fe9f1a6d | 409 | |
5e173e9f MM |
410 | static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) |
411 | { return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } | |
412 | ||
413 | static inline int net_compare_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) | |
414 | { return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } | |
415 | ||
416 | static inline int net_compare_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b) | |
417 | { return u64_cmp(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } | |
418 | ||
419 | static inline int net_compare_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b) | |
420 | { return u64_cmp(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); } | |
421 | ||
de9b87f5 | 422 | static inline int net_compare_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b) |
a820ae10 | 423 | { return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); } |
de9b87f5 PT |
424 | |
425 | static inline int net_compare_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b) | |
a820ae10 | 426 | { return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); } |
de9b87f5 | 427 | |
77234bbb OZ |
428 | static inline int net_compare_flow4(const net_addr_flow4 *a, const net_addr_flow4 *b) |
429 | { return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->length, b->length) ?: memcmp(a->data, b->data, a->length - sizeof(net_addr_flow4)); } | |
430 | ||
431 | static inline int net_compare_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b) | |
432 | { return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->length, b->length) ?: memcmp(a->data, b->data, a->length - sizeof(net_addr_flow6)); } | |
433 | ||
be17805c OZ |
434 | static inline int net_compare_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) |
435 | { | |
436 | return | |
437 | ip6_compare(a->dst_prefix, b->dst_prefix) ?: uint_cmp(a->dst_pxlen, b->dst_pxlen) ?: | |
438 | ip6_compare(a->src_prefix, b->src_prefix) ?: uint_cmp(a->src_pxlen, b->src_pxlen); | |
439 | } | |
440 | ||
33ad6e01 MM |
441 | static inline int net_compare_mpls(const net_addr_mpls *a, const net_addr_mpls *b) |
442 | { return uint_cmp(a->label, b->label); } | |
443 | ||
5e173e9f MM |
444 | int net_compare(const net_addr *a, const net_addr *b); |
445 | ||
446 | ||
fe9f1a6d OZ |
447 | static inline void net_copy(net_addr *dst, const net_addr *src) |
448 | { memcpy(dst, src, src->length); } | |
449 | ||
450 | static inline void net_copy_ip4(net_addr_ip4 *dst, const net_addr_ip4 *src) | |
451 | { memcpy(dst, src, sizeof(net_addr_ip4)); } | |
452 | ||
453 | static inline void net_copy_ip6(net_addr_ip6 *dst, const net_addr_ip6 *src) | |
454 | { memcpy(dst, src, sizeof(net_addr_ip6)); } | |
455 | ||
456 | static inline void net_copy_vpn4(net_addr_vpn4 *dst, const net_addr_vpn4 *src) | |
457 | { memcpy(dst, src, sizeof(net_addr_vpn4)); } | |
458 | ||
459 | static inline void net_copy_vpn6(net_addr_vpn6 *dst, const net_addr_vpn6 *src) | |
460 | { memcpy(dst, src, sizeof(net_addr_vpn6)); } | |
461 | ||
de9b87f5 PT |
462 | static inline void net_copy_roa4(net_addr_roa4 *dst, const net_addr_roa4 *src) |
463 | { memcpy(dst, src, sizeof(net_addr_roa4)); } | |
464 | ||
465 | static inline void net_copy_roa6(net_addr_roa6 *dst, const net_addr_roa6 *src) | |
466 | { memcpy(dst, src, sizeof(net_addr_roa6)); } | |
467 | ||
77234bbb OZ |
468 | static inline void net_copy_flow4(net_addr_flow4 *dst, const net_addr_flow4 *src) |
469 | { memcpy(dst, src, src->length); } | |
470 | ||
471 | static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src) | |
472 | { memcpy(dst, src, src->length); } | |
473 | ||
be17805c OZ |
474 | static inline void net_copy_ip6_sadr(net_addr_ip6_sadr *dst, const net_addr_ip6_sadr *src) |
475 | { memcpy(dst, src, sizeof(net_addr_ip6_sadr)); } | |
476 | ||
33ad6e01 MM |
477 | static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src) |
478 | { memcpy(dst, src, sizeof(net_addr_mpls)); } | |
fe9f1a6d | 479 | |
62e64905 OZ |
480 | |
481 | /* XXXX */ | |
482 | static inline u32 u64_hash(u64 a) | |
483 | { return u32_hash(a); } | |
484 | ||
fe9f1a6d | 485 | static inline u32 net_hash_ip4(const net_addr_ip4 *n) |
04632fd7 | 486 | { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
fe9f1a6d OZ |
487 | |
488 | static inline u32 net_hash_ip6(const net_addr_ip6 *n) | |
04632fd7 | 489 | { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
fe9f1a6d | 490 | |
fe9f1a6d | 491 | static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) |
04632fd7 | 492 | { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } |
fe9f1a6d OZ |
493 | |
494 | static inline u32 net_hash_vpn6(const net_addr_vpn6 *n) | |
04632fd7 | 495 | { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } |
fe9f1a6d | 496 | |
de9b87f5 | 497 | static inline u32 net_hash_roa4(const net_addr_roa4 *n) |
a820ae10 | 498 | { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
de9b87f5 PT |
499 | |
500 | static inline u32 net_hash_roa6(const net_addr_roa6 *n) | |
a820ae10 | 501 | { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
de9b87f5 | 502 | |
77234bbb OZ |
503 | static inline u32 net_hash_flow4(const net_addr_flow4 *n) |
504 | { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } | |
505 | ||
506 | static inline u32 net_hash_flow6(const net_addr_flow6 *n) | |
507 | { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } | |
508 | ||
be17805c OZ |
509 | static inline u32 net_hash_ip6_sadr(const net_addr_ip6_sadr *n) |
510 | { return net_hash_ip6((net_addr_ip6 *) n); } | |
511 | ||
33ad6e01 MM |
512 | static inline u32 net_hash_mpls(const net_addr_mpls *n) |
513 | { return n->label; } | |
514 | ||
d15b0b0a OZ |
515 | u32 net_hash(const net_addr *a); |
516 | ||
fe9f1a6d | 517 | |
4278abfe OZ |
518 | static inline int net_validate_px4(const ip4_addr prefix, uint pxlen) |
519 | { | |
520 | return (pxlen <= IP4_MAX_PREFIX_LENGTH) && | |
521 | ip4_zero(ip4_and(prefix, ip4_not(ip4_mkmask(pxlen)))); | |
522 | } | |
523 | ||
524 | static inline int net_validate_px6(const ip6_addr prefix, uint pxlen) | |
5e173e9f | 525 | { |
4278abfe OZ |
526 | return (pxlen <= IP6_MAX_PREFIX_LENGTH) && |
527 | ip6_zero(ip6_and(prefix, ip6_not(ip6_mkmask(pxlen)))); | |
5e173e9f MM |
528 | } |
529 | ||
4278abfe OZ |
530 | static inline int net_validate_ip4(const net_addr_ip4 *n) |
531 | { return net_validate_px4(n->prefix, n->pxlen); } | |
532 | ||
5e173e9f | 533 | static inline int net_validate_ip6(const net_addr_ip6 *n) |
4278abfe OZ |
534 | { return net_validate_px6(n->prefix, n->pxlen); } |
535 | ||
536 | static inline int net_validate_vpn4(const net_addr_vpn4 *n) | |
537 | { return net_validate_px4(n->prefix, n->pxlen); } | |
538 | ||
539 | static inline int net_validate_vpn6(const net_addr_vpn6 *n) | |
540 | { return net_validate_px6(n->prefix, n->pxlen); } | |
541 | ||
542 | static inline int net_validate_roa4(const net_addr_roa4 *n) | |
5e173e9f | 543 | { |
4278abfe OZ |
544 | return net_validate_px4(n->prefix, n->pxlen) && |
545 | (n->pxlen <= n->max_pxlen) && (n->max_pxlen <= IP4_MAX_PREFIX_LENGTH); | |
5e173e9f MM |
546 | } |
547 | ||
4278abfe | 548 | static inline int net_validate_roa6(const net_addr_roa6 *n) |
33ad6e01 | 549 | { |
4278abfe OZ |
550 | return net_validate_px6(n->prefix, n->pxlen) && |
551 | (n->pxlen <= n->max_pxlen) && (n->max_pxlen <= IP6_MAX_PREFIX_LENGTH); | |
33ad6e01 MM |
552 | } |
553 | ||
4278abfe OZ |
554 | // FIXME: Better check, call flow_validate? |
555 | static inline int net_validate_flow4(const net_addr_flow4 *n) | |
556 | { return net_validate_px4(n->prefix, n->pxlen); } | |
557 | ||
558 | static inline int net_validate_flow6(const net_addr_flow6 *n) | |
559 | { return net_validate_px6(n->prefix, n->pxlen); } | |
560 | ||
561 | static inline int net_validate_mpls(const net_addr_mpls *n) | |
562 | { return n->label < (1 << 20); } | |
563 | ||
be17805c OZ |
564 | static inline int net_validate_ip6_sadr(const net_addr_ip6_sadr *n) |
565 | { return net_validate_px6(n->dst_prefix, n->dst_pxlen) && net_validate_px6(n->src_prefix, n->src_pxlen); } | |
566 | ||
5e173e9f MM |
567 | int net_validate(const net_addr *N); |
568 | ||
569 | ||
fe9f1a6d OZ |
570 | static inline void net_normalize_ip4(net_addr_ip4 *n) |
571 | { n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); } | |
572 | ||
573 | static inline void net_normalize_ip6(net_addr_ip6 *n) | |
574 | { n->prefix = ip6_and(n->prefix, ip6_mkmask(n->pxlen)); } | |
575 | ||
1e37e35c OZ |
576 | static inline void net_normalize_vpn4(net_addr_vpn4 *n) |
577 | { net_normalize_ip4((net_addr_ip4 *) n); } | |
578 | ||
579 | static inline void net_normalize_vpn6(net_addr_vpn6 *n) | |
580 | { net_normalize_ip6((net_addr_ip6 *) n); } | |
581 | ||
be17805c OZ |
582 | static inline void net_normalize_ip6_sadr(net_addr_ip6_sadr *n) |
583 | { | |
584 | n->dst_prefix = ip6_and(n->dst_prefix, ip6_mkmask(n->dst_pxlen)); | |
585 | n->src_prefix = ip6_and(n->src_prefix, ip6_mkmask(n->src_pxlen)); | |
586 | } | |
587 | ||
fe9f1a6d OZ |
588 | void net_normalize(net_addr *N); |
589 | ||
9b136840 | 590 | |
fe9f1a6d | 591 | int net_classify(const net_addr *N); |
9b136840 | 592 | int net_format(const net_addr *N, char *buf, int buflen); |
8c9986d3 | 593 | int rd_format(const u64 rd, char *buf, int buflen); |
fe9f1a6d | 594 | |
be17805c OZ |
595 | static inline int ipa_in_px4(ip4_addr a, ip4_addr prefix, uint pxlen) |
596 | { return ip4_zero(ip4_and(ip4_xor(a, prefix), ip4_mkmask(pxlen))); } | |
4ff15a75 | 597 | |
be17805c OZ |
598 | static inline int ipa_in_px6(ip6_addr a, ip6_addr prefix, uint pxlen) |
599 | { return ip6_zero(ip6_and(ip6_xor(a, prefix), ip6_mkmask(pxlen))); } | |
600 | ||
601 | static inline int ipa_in_net_ip4(ip4_addr a, const net_addr_ip4 *n) | |
602 | { return ipa_in_px4(a, n->prefix, n->pxlen); } | |
4ff15a75 OZ |
603 | |
604 | static inline int ipa_in_net_ip6(ip6_addr a, const net_addr_ip6 *n) | |
be17805c OZ |
605 | { return ipa_in_px6(a, n->prefix, n->pxlen); } |
606 | ||
607 | static inline int net_in_net_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) | |
608 | { return (a->pxlen >= b->pxlen) && ipa_in_px4(a->prefix, b->prefix, b->pxlen); } | |
4ff15a75 OZ |
609 | |
610 | static inline int net_in_net_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) | |
be17805c OZ |
611 | { return (a->pxlen >= b->pxlen) && ipa_in_px6(a->prefix, b->prefix, b->pxlen); } |
612 | ||
613 | static inline int net_in_net_dst_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) | |
614 | { return (a->dst_pxlen >= b->dst_pxlen) && ipa_in_px6(a->dst_prefix, b->dst_prefix, b->dst_pxlen); } | |
615 | ||
616 | static inline int net_in_net_src_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_ip6_sadr *b) | |
617 | { return (a->src_pxlen >= b->src_pxlen) && ipa_in_px6(a->src_prefix, b->src_prefix, b->src_pxlen); } | |
4ff15a75 | 618 | |
d44e686e OZ |
619 | int ipa_in_netX(const ip_addr A, const net_addr *N); |
620 | int net_in_netX(const net_addr *A, const net_addr *N); | |
621 | ||
67a2eb91 | 622 | void net_init(void); |
fe9f1a6d OZ |
623 | |
624 | #endif |