]>
Commit | Line | Data |
---|---|---|
c40e05a0 MM |
1 | /* |
2 | * BIRD Internet Routing Daemon -- The Internet Protocol | |
3 | * | |
4 | * (c) 1998 Martin Mares <mj@ucw.cz> | |
5 | * | |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #ifndef _BIRD_IP_H_ | |
10 | #define _BIRD_IP_H_ | |
11 | ||
7152e5ef | 12 | #include "sysdep/unix/endian.h" |
88a183c6 OZ |
13 | #include "lib/string.h" |
14 | #include "lib/bitops.h" | |
15 | #include "lib/unaligned.h" | |
16 | ||
17 | ||
8465dccb OZ |
18 | #define IP4_ALL_NODES ipa_build4(224, 0, 0, 1) |
19 | #define IP4_ALL_ROUTERS ipa_build4(224, 0, 0, 2) | |
88a183c6 OZ |
20 | #define IP4_OSPF_ALL_ROUTERS ipa_build4(224, 0, 0, 5) |
21 | #define IP4_OSPF_DES_ROUTERS ipa_build4(224, 0, 0, 6) | |
8465dccb | 22 | #define IP4_RIP_ROUTERS ipa_build4(224, 0, 0, 9) |
88a183c6 OZ |
23 | |
24 | #define IP6_ALL_NODES ipa_build6(0xFF020000, 0, 0, 1) | |
25 | #define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2) | |
26 | #define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5) | |
27 | #define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6) | |
28 | #define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9) | |
937e75d8 | 29 | #define IP6_BABEL_ROUTERS ipa_build6(0xFF020000, 0, 0, 0x00010006) |
88a183c6 OZ |
30 | |
31 | #define IP4_NONE _MI4(0) | |
32 | #define IP6_NONE _MI6(0,0,0,0) | |
33 | ||
fe9f1a6d OZ |
34 | #define IP4_MAX_PREFIX_LENGTH 32 |
35 | #define IP6_MAX_PREFIX_LENGTH 128 | |
36 | ||
7fd4143e MM |
37 | #define IP4_MAX_TEXT_LENGTH 15 /* "255.255.255.255" */ |
38 | #define IP6_MAX_TEXT_LENGTH 39 /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" */ | |
39 | #define IPA_MAX_TEXT_LENGTH 39 | |
40 | ||
88a183c6 OZ |
41 | #define IP4_MIN_MTU 576 |
42 | #define IP6_MIN_MTU 1280 | |
43 | ||
44 | #define IP_PREC_INTERNET_CONTROL 0xc0 | |
45 | ||
8465dccb OZ |
46 | #define IP4_HEADER_LENGTH 20 |
47 | #define IP6_HEADER_LENGTH 40 | |
48 | #define UDP_HEADER_LENGTH 8 | |
49 | ||
88a183c6 OZ |
50 | |
51 | #ifdef DEBUGGING | |
52 | ||
53 | typedef struct ip4_addr { | |
54 | u32 addr; | |
55 | } ip4_addr; | |
56 | ||
57 | #define _MI4(x) ((struct ip4_addr) { x }) | |
58 | #define _I(x) (x).addr | |
59 | ||
60 | #else | |
61 | ||
62 | typedef u32 ip4_addr; | |
63 | ||
df50598f | 64 | #define _MI4(x) ((u32) (x)) |
88a183c6 OZ |
65 | #define _I(x) (x) |
66 | ||
67 | #endif | |
68 | ||
69 | ||
70 | typedef struct ip6_addr { | |
71 | u32 addr[4]; | |
72 | } ip6_addr; | |
73 | ||
74 | #define _MI6(a,b,c,d) ((struct ip6_addr) {{ a, b, c, d }}) | |
75 | #define _I0(a) ((a).addr[0]) | |
76 | #define _I1(a) ((a).addr[1]) | |
77 | #define _I2(a) ((a).addr[2]) | |
78 | #define _I3(a) ((a).addr[3]) | |
79 | ||
80 | ||
88a183c6 OZ |
81 | /* Structure ip_addr may contain both IPv4 and IPv6 addresses */ |
82 | typedef ip6_addr ip_addr; | |
83 | #define IPA_NONE IP6_NONE | |
84 | ||
85 | #define ipa_from_ip4(x) _MI6(0,0,0xffff,_I(x)) | |
86 | #define ipa_from_ip6(x) x | |
87 | #define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x)) | |
88 | ||
89 | #define ipa_to_ip4(x) _MI4(_I3(x)) | |
90 | #define ipa_to_ip6(x) x | |
91 | #define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x)) | |
92 | ||
93 | #define ipa_is_ip4(a) ip6_is_v4mapped(a) | |
d15b0b0a | 94 | #define ipa_is_ip6(a) (! ip6_is_v4mapped(a)) |
88a183c6 | 95 | |
04632fd7 OZ |
96 | #define IPA_NONE4 ipa_from_ip4(IP4_NONE) |
97 | #define IPA_NONE6 ipa_from_ip6(IP6_NONE) | |
98 | ||
88a183c6 OZ |
99 | |
100 | /* | |
101 | * Public constructors | |
102 | */ | |
103 | ||
104 | #define ip4_from_u32(x) _MI4(x) | |
105 | #define ip4_to_u32(x) _I(x) | |
106 | ||
107 | #define ip4_build(a,b,c,d) _MI4(((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) | |
108 | #define ip6_build(a,b,c,d) _MI6(a,b,c,d) | |
109 | ||
110 | #define ipa_build4(a,b,c,d) ipa_from_ip4(ip4_build(a,b,c,d)) | |
111 | #define ipa_build6(a,b,c,d) ipa_from_ip6(ip6_build(a,b,c,d)) | |
112 | ||
113 | ||
114 | /* | |
115 | * Basic algebraic functions | |
116 | */ | |
117 | ||
118 | static inline int ip4_equal(ip4_addr a, ip4_addr b) | |
119 | { return _I(a) == _I(b); } | |
120 | ||
121 | static inline int ip4_zero(ip4_addr a) | |
122 | { return _I(a) == 0; } | |
123 | ||
124 | static inline int ip4_nonzero(ip4_addr a) | |
125 | { return _I(a) != 0; } | |
126 | ||
127 | static inline ip4_addr ip4_and(ip4_addr a, ip4_addr b) | |
128 | { return _MI4(_I(a) & _I(b)); } | |
129 | ||
130 | static inline ip4_addr ip4_or(ip4_addr a, ip4_addr b) | |
131 | { return _MI4(_I(a) | _I(b)); } | |
132 | ||
133 | static inline ip4_addr ip4_xor(ip4_addr a, ip4_addr b) | |
134 | { return _MI4(_I(a) ^ _I(b)); } | |
135 | ||
136 | static inline ip4_addr ip4_not(ip4_addr a) | |
137 | { return _MI4(~_I(a)); } | |
138 | ||
139 | ||
140 | static inline int ip6_equal(ip6_addr a, ip6_addr b) | |
141 | { return _I0(a) == _I0(b) && _I1(a) == _I1(b) && _I2(a) == _I2(b) && _I3(a) == _I3(b); } | |
142 | ||
143 | static inline int ip6_zero(ip6_addr a) | |
144 | { return !_I0(a) && !_I1(a) && !_I2(a) && !_I3(a); } | |
145 | ||
146 | static inline int ip6_nonzero(ip6_addr a) | |
147 | { return _I0(a) || _I1(a) || _I2(a) || _I3(a); } | |
148 | ||
149 | static inline ip6_addr ip6_and(ip6_addr a, ip6_addr b) | |
150 | { return _MI6(_I0(a) & _I0(b), _I1(a) & _I1(b), _I2(a) & _I2(b), _I3(a) & _I3(b)); } | |
151 | ||
152 | static inline ip6_addr ip6_or(ip6_addr a, ip6_addr b) | |
153 | { return _MI6(_I0(a) | _I0(b), _I1(a) | _I1(b), _I2(a) | _I2(b), _I3(a) | _I3(b)); } | |
154 | ||
155 | static inline ip6_addr ip6_xor(ip6_addr a, ip6_addr b) | |
156 | { return _MI6(_I0(a) ^ _I0(b), _I1(a) ^ _I1(b), _I2(a) ^ _I2(b), _I3(a) ^ _I3(b)); } | |
157 | ||
158 | static inline ip6_addr ip6_not(ip6_addr a) | |
159 | { return _MI6(~_I0(a), ~_I1(a), ~_I2(a), ~_I3(a)); } | |
160 | ||
161 | ||
88a183c6 OZ |
162 | #define ipa_equal(x,y) ip6_equal(x,y) |
163 | #define ipa_zero(x) ip6_zero(x) | |
164 | #define ipa_nonzero(x) ip6_nonzero(x) | |
165 | #define ipa_and(x,y) ip6_and(x,y) | |
166 | #define ipa_or(x,y) ip6_or(x,y) | |
167 | #define ipa_xor(x,y) ip6_xor(x,y) | |
168 | #define ipa_not(x) ip6_not(x) | |
88a183c6 OZ |
169 | |
170 | ||
88a183c6 OZ |
171 | /* |
172 | * A zero address is either a token for invalid/unused, or the prefix of default | |
173 | * routes. These functions should be used in the second case, where both IPv4 | |
174 | * and IPv6 zero addresses should be checked. | |
175 | */ | |
176 | ||
177 | static inline int ipa_zero2(ip_addr a) | |
178 | { return !_I0(a) && !_I1(a) && ((_I2(a) == 0) || (_I2(a) == 0xffff)) && !_I3(a); } | |
179 | ||
180 | static inline int ipa_nonzero2(ip_addr a) | |
181 | { return _I0(a) || _I1(a) || ((_I2(a) != 0) && (_I2(a) != 0xffff)) || _I3(a); } | |
182 | ||
88a183c6 OZ |
183 | |
184 | /* | |
185 | * Hash and compare functions | |
186 | */ | |
187 | ||
04632fd7 | 188 | static inline u32 ip4_hash(ip4_addr a) |
84661bf6 | 189 | { return u32_hash(_I(a)); } |
88a183c6 | 190 | |
04632fd7 | 191 | static inline u32 ip6_hash(ip6_addr a) |
88a183c6 OZ |
192 | { |
193 | /* Returns a 32-bit hash key, although low-order bits are not mixed */ | |
194 | u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a); | |
195 | return x ^ (x << 16) ^ (x << 24); | |
196 | } | |
197 | ||
198 | static inline int ip4_compare(ip4_addr a, ip4_addr b) | |
199 | { return (_I(a) > _I(b)) - (_I(a) < _I(b)); } | |
200 | ||
201 | int ip6_compare(ip6_addr a, ip6_addr b); | |
202 | ||
88a183c6 | 203 | #define ipa_hash(x) ip6_hash(x) |
88a183c6 | 204 | #define ipa_compare(x,y) ip6_compare(x,y) |
c40e05a0 | 205 | |
0fe3b28b | 206 | |
18c8241a | 207 | /* |
88a183c6 | 208 | * IP address classification |
18c8241a MM |
209 | */ |
210 | ||
88a183c6 | 211 | /* Address class */ |
18c8241a MM |
212 | #define IADDR_INVALID -1 |
213 | #define IADDR_SCOPE_MASK 0xfff | |
214 | #define IADDR_HOST 0x1000 | |
215 | #define IADDR_BROADCAST 0x2000 | |
216 | #define IADDR_MULTICAST 0x4000 | |
217 | ||
88a183c6 OZ |
218 | /* Address scope */ |
219 | #define SCOPE_HOST 0 | |
220 | #define SCOPE_LINK 1 | |
221 | #define SCOPE_SITE 2 | |
222 | #define SCOPE_ORGANIZATION 3 | |
223 | #define SCOPE_UNIVERSE 4 | |
224 | #define SCOPE_UNDEFINED 5 | |
225 | ||
226 | int ip4_classify(ip4_addr ad); | |
227 | int ip6_classify(ip6_addr *a); | |
228 | ||
229 | static inline int ip6_is_link_local(ip6_addr a) | |
230 | { return (_I0(a) & 0xffc00000) == 0xfe800000; } | |
231 | ||
232 | static inline int ip6_is_v4mapped(ip6_addr a) | |
233 | { return _I0(a) == 0 && _I1(a) == 0 && _I2(a) == 0xffff; } | |
234 | ||
88a183c6 OZ |
235 | #define ipa_classify(x) ip6_classify(&(x)) |
236 | #define ipa_is_link_local(x) ip6_is_link_local(x) | |
88a183c6 | 237 | |
318acb0f OZ |
238 | static inline int ip4_is_unicast(ip4_addr a) |
239 | { return _I(a) < 0xe0000000; } | |
240 | ||
0bf95f99 | 241 | /* XXXX remove */ |
88a183c6 OZ |
242 | static inline int ipa_classify_net(ip_addr a) |
243 | { return ipa_zero2(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); } | |
244 | ||
245 | ||
18c8241a | 246 | /* |
88a183c6 | 247 | * Miscellaneous IP prefix manipulation |
18c8241a MM |
248 | */ |
249 | ||
88a183c6 OZ |
250 | static inline ip4_addr ip4_mkmask(uint n) |
251 | { return _MI4(u32_mkmask(n)); } | |
252 | ||
fe9f1a6d | 253 | static inline uint ip4_masklen(ip4_addr a) |
88a183c6 OZ |
254 | { return u32_masklen(_I(a)); } |
255 | ||
256 | ip6_addr ip6_mkmask(uint n); | |
fe9f1a6d | 257 | uint ip6_masklen(ip6_addr *a); |
88a183c6 OZ |
258 | |
259 | /* ipX_pxlen() requires that x != y */ | |
260 | static inline uint ip4_pxlen(ip4_addr a, ip4_addr b) | |
261 | { return 31 - u32_log2(_I(a) ^ _I(b)); } | |
262 | ||
263 | static inline uint ip6_pxlen(ip6_addr a, ip6_addr b) | |
264 | { | |
265 | int i = 0; | |
266 | i += (a.addr[i] == b.addr[i]); | |
267 | i += (a.addr[i] == b.addr[i]); | |
268 | i += (a.addr[i] == b.addr[i]); | |
269 | i += (a.addr[i] == b.addr[i]); | |
270 | return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]); | |
271 | } | |
272 | ||
273 | static inline u32 ip4_getbit(ip4_addr a, uint pos) | |
274 | { return _I(a) & (0x80000000 >> pos); } | |
275 | ||
276 | static inline u32 ip6_getbit(ip6_addr a, uint pos) | |
277 | { return a.addr[pos / 32] & (0x80000000 >> (pos % 32)); } | |
278 | ||
fe9f1a6d OZ |
279 | static inline u32 ip4_setbit(ip4_addr *a, uint pos) |
280 | { return _I(*a) |= (0x80000000 >> pos); } | |
281 | ||
282 | static inline u32 ip6_setbit(ip6_addr *a, uint pos) | |
283 | { return a->addr[pos / 32] |= (0x80000000 >> (pos % 32)); } | |
284 | ||
285 | static inline u32 ip4_clrbit(ip4_addr *a, uint pos) | |
286 | { return _I(*a) &= ~(0x80000000 >> pos); } | |
287 | ||
288 | static inline u32 ip6_clrbit(ip6_addr *a, uint pos) | |
289 | { return a->addr[pos / 32] &= ~(0x80000000 >> (pos % 32)); } | |
290 | ||
88a183c6 OZ |
291 | static inline ip4_addr ip4_opposite_m1(ip4_addr a) |
292 | { return _MI4(_I(a) ^ 1); } | |
293 | ||
294 | static inline ip4_addr ip4_opposite_m2(ip4_addr a) | |
295 | { return _MI4(_I(a) ^ 3); } | |
296 | ||
297 | static inline ip6_addr ip6_opposite_m1(ip6_addr a) | |
298 | { return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 1); } | |
299 | ||
300 | static inline ip6_addr ip6_opposite_m2(ip6_addr a) | |
301 | { return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 3); } | |
302 | ||
303 | ip4_addr ip4_class_mask(ip4_addr ad); | |
304 | ||
88a183c6 OZ |
305 | #define ipa_opposite_m1(x) ip6_opposite_m1(x) |
306 | #define ipa_opposite_m2(x) ip6_opposite_m2(x) | |
18c8241a | 307 | |
ea32afb7 | 308 | |
25697773 | 309 | /* |
88a183c6 | 310 | * Host/network order conversions |
25697773 MM |
311 | */ |
312 | ||
88a183c6 OZ |
313 | static inline ip4_addr ip4_hton(ip4_addr a) |
314 | { return _MI4(htonl(_I(a))); } | |
315 | ||
316 | static inline ip4_addr ip4_ntoh(ip4_addr a) | |
317 | { return _MI4(ntohl(_I(a))); } | |
318 | ||
319 | static inline ip6_addr ip6_hton(ip6_addr a) | |
320 | { return _MI6(htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a))); } | |
321 | ||
322 | static inline ip6_addr ip6_ntoh(ip6_addr a) | |
323 | { return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); } | |
324 | ||
d14f8c3c | 325 | #define MPLS_MAX_LABEL_STACK 8 |
3c744164 MM |
326 | typedef struct mpls_label_stack { |
327 | uint len; | |
328 | u32 stack[MPLS_MAX_LABEL_STACK]; | |
329 | } mpls_label_stack; | |
330 | ||
d14f8c3c MM |
331 | static inline int |
332 | mpls_get(const char *buf, int buflen, u32 *stack) | |
333 | { | |
334 | for (int i=0; (i<MPLS_MAX_LABEL_STACK) && (i*4+3 < buflen); i++) | |
335 | { | |
336 | u32 s = get_u32(buf + i*4); | |
337 | stack[i] = s >> 12; | |
338 | if (s & 0x100) | |
339 | return i+1; | |
340 | } | |
341 | return -1; | |
342 | } | |
343 | ||
344 | static inline int | |
345 | mpls_put(char *buf, int len, u32 *stack) | |
346 | { | |
347 | for (int i=0; i<len; i++) | |
348 | put_u32(buf + i*4, stack[i] << 12 | (i+1 == len ? 0x100 : 0)); | |
349 | ||
350 | return len*4; | |
351 | } | |
88a183c6 OZ |
352 | |
353 | /* | |
354 | * Unaligned data access (in network order) | |
355 | */ | |
356 | ||
357 | static inline ip4_addr get_ip4(void *buf) | |
358 | { | |
359 | return _MI4(get_u32(buf)); | |
360 | } | |
361 | ||
362 | static inline ip6_addr get_ip6(void *buf) | |
363 | { | |
364 | ip6_addr a; | |
365 | memcpy(&a, buf, 16); | |
366 | return ip6_ntoh(a); | |
367 | } | |
368 | ||
369 | static inline void * put_ip4(void *buf, ip4_addr a) | |
370 | { | |
371 | put_u32(buf, _I(a)); | |
372 | return buf+4; | |
373 | } | |
374 | ||
375 | static inline void * put_ip6(void *buf, ip6_addr a) | |
376 | { | |
377 | a = ip6_hton(a); | |
378 | memcpy(buf, &a, 16); | |
379 | return buf+16; | |
380 | } | |
381 | ||
88a183c6 OZ |
382 | |
383 | /* | |
384 | * Binary/text form conversions | |
385 | */ | |
386 | ||
387 | char *ip4_ntop(ip4_addr a, char *b); | |
388 | char *ip6_ntop(ip6_addr a, char *b); | |
389 | ||
390 | static inline char * ip4_ntox(ip4_addr a, char *b) | |
391 | { return b + bsprintf(b, "%08x", _I(a)); } | |
392 | ||
393 | static inline char * ip6_ntox(ip6_addr a, char *b) | |
394 | { return b + bsprintf(b, "%08x.%08x.%08x.%08x", _I0(a), _I1(a), _I2(a), _I3(a)); } | |
395 | ||
e422ca0f OZ |
396 | int ip4_pton(const char *a, ip4_addr *o); |
397 | int ip6_pton(const char *a, ip6_addr *o); | |
88a183c6 | 398 | |
25697773 | 399 | |
6b5e06ab | 400 | /* |
88a183c6 | 401 | * Miscellaneous |
6b5e06ab MM |
402 | */ |
403 | ||
ae80a2de | 404 | char *ip_scope_text(uint); |
88a183c6 | 405 | |
c40e05a0 | 406 | #endif |