]>
Commit | Line | Data |
---|---|---|
ea32afb7 | 1 | /* |
88a183c6 | 2 | * BIRD Library -- IP address functions |
ea32afb7 | 3 | * |
7722938d | 4 | * (c) 1998--2000 Martin Mares <mj@ucw.cz> |
ea32afb7 MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
7722938d MM |
9 | /** |
10 | * DOC: IP addresses | |
11 | * | |
12 | * BIRD uses its own abstraction of IP address in order to share the same | |
13 | * code for both IPv4 and IPv6. IP addresses are represented as entities | |
14 | * of type &ip_addr which are never to be treated as numbers and instead | |
725270cb | 15 | * they must be manipulated using the following functions and macros. |
7722938d MM |
16 | */ |
17 | ||
88a183c6 OZ |
18 | #include <stdlib.h> |
19 | ||
20 | #include "nest/bird.h" | |
21 | #include "lib/ip.h" | |
22 | ||
23 | ||
24 | int | |
25 | ip6_compare(ip6_addr a, ip6_addr b) | |
26 | { | |
27 | int i; | |
28 | for (i=0; i<4; i++) | |
29 | if (a.addr[i] > b.addr[i]) | |
30 | return 1; | |
31 | else if (a.addr[i] < b.addr[i]) | |
32 | return -1; | |
33 | return 0; | |
34 | } | |
35 | ||
36 | ip6_addr | |
37 | ip6_mkmask(uint n) | |
38 | { | |
39 | ip6_addr a; | |
40 | int i; | |
41 | ||
42 | for (i=0; i<4; i++) | |
43 | { | |
44 | if (!n) | |
45 | a.addr[i] = 0; | |
46 | else if (n >= 32) | |
47 | { | |
48 | a.addr[i] = ~0; | |
49 | n -= 32; | |
50 | } | |
51 | else | |
52 | { | |
53 | a.addr[i] = u32_mkmask(n); | |
54 | n = 0; | |
55 | } | |
56 | } | |
57 | ||
58 | return a; | |
59 | } | |
60 | ||
61 | int | |
62 | ip6_masklen(ip6_addr *a) | |
63 | { | |
64 | int i, j, n; | |
65 | ||
66 | for (i=0, n=0; i<4; i++, n+=32) | |
67 | if (a->addr[i] != ~0U) | |
68 | { | |
69 | j = u32_masklen(a->addr[i]); | |
70 | if (j < 0) | |
71 | return j; | |
72 | n += j; | |
73 | while (++i < 4) | |
74 | if (a->addr[i]) | |
75 | return -1; | |
76 | break; | |
77 | } | |
78 | ||
79 | return n; | |
80 | } | |
81 | ||
82 | int | |
83 | ip4_classify(ip4_addr ad) | |
84 | { | |
85 | u32 a = _I(ad); | |
86 | u32 b = a >> 24U; | |
87 | ||
88 | if (b && b <= 0xdf) | |
89 | { | |
90 | if (b == 0x7f) | |
91 | return IADDR_HOST | SCOPE_HOST; | |
92 | else if ((b == 0x0a) || | |
93 | ((a & 0xffff0000) == 0xc0a80000) || | |
94 | ((a & 0xfff00000) == 0xac100000)) | |
95 | return IADDR_HOST | SCOPE_SITE; | |
96 | else | |
97 | return IADDR_HOST | SCOPE_UNIVERSE; | |
98 | } | |
99 | ||
100 | if (b >= 0xe0 && b <= 0xef) | |
101 | return IADDR_MULTICAST | SCOPE_UNIVERSE; | |
102 | ||
103 | if (a == 0xffffffff) | |
104 | return IADDR_BROADCAST | SCOPE_LINK; | |
105 | ||
106 | return IADDR_INVALID; | |
107 | } | |
108 | ||
109 | int | |
110 | ip6_classify(ip6_addr *a) | |
111 | { | |
112 | u32 x = a->addr[0]; | |
113 | ||
114 | if ((x & 0xe0000000) == 0x20000000) /* 2000::/3 Aggregatable Global Unicast Address */ | |
115 | return IADDR_HOST | SCOPE_UNIVERSE; | |
116 | if ((x & 0xffc00000) == 0xfe800000) /* fe80::/10 Link-Local Address */ | |
117 | return IADDR_HOST | SCOPE_LINK; | |
118 | if ((x & 0xffc00000) == 0xfec00000) /* fec0::/10 Site-Local Address */ | |
119 | return IADDR_HOST | SCOPE_SITE; | |
120 | if ((x & 0xfe000000) == 0xfc000000) /* fc00::/7 Unique Local Unicast Address (RFC 4193) */ | |
121 | return IADDR_HOST | SCOPE_SITE; | |
122 | if ((x & 0xff000000) == 0xff000000) /* ff00::/8 Multicast Address */ | |
123 | { | |
124 | uint scope = (x >> 16) & 0x0f; | |
125 | switch (scope) | |
126 | { | |
127 | case 1: return IADDR_MULTICAST | SCOPE_HOST; | |
128 | case 2: return IADDR_MULTICAST | SCOPE_LINK; | |
129 | case 5: return IADDR_MULTICAST | SCOPE_SITE; | |
130 | case 8: return IADDR_MULTICAST | SCOPE_ORGANIZATION; | |
131 | case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE; | |
132 | default: return IADDR_MULTICAST | SCOPE_UNDEFINED; | |
133 | } | |
134 | } | |
135 | ||
136 | if (!x && !a->addr[1]) | |
137 | { | |
138 | u32 a2 = a->addr[2]; | |
139 | u32 a3 = a->addr[3]; | |
140 | ||
141 | if (a2 == 0 && a3 == 1) | |
142 | return IADDR_HOST | SCOPE_HOST; /* Loopback address */ | |
143 | if (a2 == 0) | |
144 | return ip4_classify(_MI4(a3)); /* IPv4 compatible addresses */ | |
145 | if (a2 == 0xffff) | |
146 | return ip4_classify(_MI4(a3)); /* IPv4 mapped addresses */ | |
147 | ||
148 | return IADDR_INVALID; | |
149 | } | |
150 | ||
151 | return IADDR_HOST | SCOPE_UNDEFINED; | |
152 | } | |
153 | ||
154 | ||
155 | ||
156 | /* | |
157 | * Conversion of IPv6 address to presentation format and vice versa. | |
158 | * Heavily inspired by routines written by Paul Vixie for the BIND project | |
159 | * and of course by RFC 2373. | |
160 | */ | |
161 | ||
162 | ||
163 | char * | |
164 | ip4_ntop(ip4_addr a, char *b) | |
165 | { | |
166 | u32 x = _I(a); | |
167 | return b + bsprintf(b, "%d.%d.%d.%d", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); | |
168 | } | |
169 | ||
170 | ||
171 | char * | |
172 | ip6_ntop(ip6_addr a, char *b) | |
173 | { | |
174 | u16 words[8]; | |
175 | int bestpos, bestlen, curpos, curlen, i; | |
176 | ||
177 | /* First of all, preprocess the address and find the longest run of zeros */ | |
178 | bestlen = bestpos = curpos = curlen = 0; | |
179 | for (i=0; i<8; i++) | |
180 | { | |
181 | u32 x = a.addr[i/2]; | |
182 | words[i] = ((i%2) ? x : (x >> 16)) & 0xffff; | |
183 | if (words[i]) | |
184 | curlen = 0; | |
185 | else | |
186 | { | |
187 | if (!curlen) | |
188 | curpos = i; | |
189 | curlen++; | |
190 | if (curlen > bestlen) | |
191 | { | |
192 | bestpos = curpos; | |
193 | bestlen = curlen; | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | if (bestlen < 2) | |
199 | bestpos = -1; | |
200 | ||
201 | /* Is it an encapsulated IPv4 address? */ | |
202 | if (!bestpos && ((bestlen == 5 && a.addr[2] == 0xffff) || (bestlen == 6))) | |
203 | { | |
204 | u32 x = a.addr[3]; | |
205 | b += bsprintf(b, "::%s%d.%d.%d.%d", | |
206 | a.addr[2] ? "ffff:" : "", | |
207 | (x >> 24) & 0xff, | |
208 | (x >> 16) & 0xff, | |
209 | (x >> 8) & 0xff, | |
210 | x & 0xff); | |
211 | return b; | |
212 | } | |
213 | ||
214 | /* Normal IPv6 formatting, compress the largest sequence of zeros */ | |
215 | for (i=0; i<8; i++) | |
216 | { | |
217 | if (i == bestpos) | |
218 | { | |
219 | i += bestlen - 1; | |
220 | *b++ = ':'; | |
221 | if (i == 7) | |
222 | *b++ = ':'; | |
223 | } | |
224 | else | |
225 | { | |
226 | if (i) | |
227 | *b++ = ':'; | |
228 | b += bsprintf(b, "%x", words[i]); | |
229 | } | |
230 | } | |
231 | *b = 0; | |
232 | return b; | |
233 | } | |
234 | ||
235 | int | |
236 | ip4_pton(char *a, ip4_addr *o) | |
237 | { | |
238 | int i; | |
239 | unsigned long int l; | |
240 | u32 ia = 0; | |
241 | ||
242 | i=4; | |
243 | while (i--) | |
244 | { | |
245 | char *d, *c = strchr(a, '.'); | |
246 | if (!c != !i) | |
247 | return 0; | |
248 | l = strtoul(a, &d, 10); | |
249 | if (d != c && *d || l > 255) | |
250 | return 0; | |
251 | ia = (ia << 8) | l; | |
252 | if (c) | |
253 | c++; | |
254 | a = c; | |
255 | } | |
256 | *o = ip4_from_u32(ia); | |
257 | return 1; | |
258 | } | |
259 | ||
260 | int | |
261 | ip6_pton(char *a, ip6_addr *o) | |
262 | { | |
263 | u16 words[8]; | |
264 | int i, j, k, l, hfil; | |
265 | char *start; | |
266 | ||
267 | if (a[0] == ':') /* Leading :: */ | |
268 | { | |
269 | if (a[1] != ':') | |
270 | return 0; | |
271 | a++; | |
272 | } | |
273 | ||
274 | hfil = -1; | |
275 | i = 0; | |
276 | while (*a) | |
277 | { | |
278 | if (*a == ':') /* :: */ | |
279 | { | |
280 | if (hfil >= 0) | |
281 | return 0; | |
282 | ||
283 | hfil = i; | |
284 | a++; | |
285 | continue; | |
286 | } | |
287 | ||
288 | j = 0; | |
289 | l = 0; | |
290 | start = a; | |
291 | for (;;) | |
292 | { | |
293 | if (*a >= '0' && *a <= '9') | |
294 | k = *a++ - '0'; | |
295 | else if (*a >= 'A' && *a <= 'F') | |
296 | k = *a++ - 'A' + 10; | |
297 | else if (*a >= 'a' && *a <= 'f') | |
298 | k = *a++ - 'a' + 10; | |
299 | else | |
300 | break; | |
301 | ||
302 | j = (j << 4) + k; | |
303 | if (j >= 0x10000 || ++l > 4) | |
304 | return 0; | |
305 | } | |
306 | ||
307 | if (*a == ':' && a[1]) | |
308 | a++; | |
309 | else if (*a == '.' && (i == 6 || i < 6 && hfil >= 0)) | |
310 | { /* Embedded IPv4 address */ | |
311 | ip4_addr x; | |
312 | if (!ip4_pton(start, &x)) | |
313 | return 0; | |
314 | words[i++] = _I(x) >> 16; | |
315 | words[i++] = _I(x); | |
316 | break; | |
317 | } | |
318 | else if (*a) | |
319 | return 0; | |
320 | ||
321 | if (i >= 8) | |
322 | return 0; | |
323 | ||
324 | words[i++] = j; | |
325 | } | |
326 | ||
327 | /* Replace :: with an appropriate number of zeros */ | |
328 | if (hfil >= 0) | |
329 | { | |
330 | j = 8 - i; | |
331 | for (i=7; i-j >= hfil; i--) | |
332 | words[i] = words[i-j]; | |
333 | for (; i>=hfil; i--) | |
334 | words[i] = 0; | |
335 | } | |
336 | ||
337 | /* Convert the address to ip6_addr format */ | |
338 | for (i=0; i<4; i++) | |
339 | o->addr[i] = (words[2*i] << 16) | words[2*i+1]; | |
340 | ||
341 | return 1; | |
342 | } | |
343 | ||
344 | ||
7722938d | 345 | /** |
2e9b2421 | 346 | * ip_scope_text - get textual representation of address scope |
7722938d MM |
347 | * @scope: scope (%SCOPE_xxx) |
348 | * | |
349 | * Returns a pointer to a textual name of the scope given. | |
350 | */ | |
ea32afb7 | 351 | char * |
88a183c6 | 352 | ip_scope_text(uint scope) |
ea32afb7 | 353 | { |
bf6d91dc | 354 | static char *scope_table[] = { "host", "link", "site", "org", "univ", "undef" }; |
ea32afb7 | 355 | |
bf6d91dc | 356 | if (scope > SCOPE_UNDEFINED) |
ea32afb7 MM |
357 | return "?"; |
358 | else | |
359 | return scope_table[scope]; | |
360 | } | |
7722938d | 361 | |
88a183c6 OZ |
362 | ip4_addr |
363 | ip4_class_mask(ip4_addr ad) | |
364 | { | |
365 | u32 m, a = _I(ad); | |
366 | ||
367 | if (a < 0x80000000) | |
368 | m = 0xff000000; | |
369 | else if (a < 0xc0000000) | |
370 | m = 0xffff0000; | |
371 | else | |
372 | m = 0xffffff00; | |
373 | if (a & ~m) | |
374 | m = 0xffffffff; | |
375 | ||
376 | return _MI4(m); | |
377 | } | |
378 | ||
7722938d MM |
379 | #if 0 |
380 | /** | |
381 | * ipa_equal - compare two IP addresses for equality | |
382 | * @x: IP address | |
383 | * @y: IP address | |
384 | * | |
385 | * ipa_equal() returns 1 if @x and @y represent the same IP address, else 0. | |
386 | */ | |
387 | int ipa_equal(ip_addr x, ip_addr y) { DUMMY } | |
388 | ||
389 | /** | |
390 | * ipa_nonzero - test if an IP address is defined | |
391 | * @x: IP address | |
392 | * | |
393 | * ipa_nonzero returns 1 if @x is a defined IP address (not all bits are zero), | |
394 | * else 0. | |
395 | * | |
396 | * The undefined all-zero address is reachable as a |IPA_NONE| macro. | |
397 | */ | |
398 | int ipa_nonzero(ip_addr x) { DUMMY } | |
399 | ||
400 | /** | |
401 | * ipa_and - compute bitwise and of two IP addresses | |
402 | * @x: IP address | |
403 | * @y: IP address | |
404 | * | |
405 | * This function returns a bitwise and of @x and @y. It's primarily | |
406 | * used for network masking. | |
407 | */ | |
408 | ip_addr ipa_and(ip_addr x, ip_addr y) { DUMMY } | |
409 | ||
410 | /** | |
411 | * ipa_or - compute bitwise or of two IP addresses | |
412 | * @x: IP address | |
413 | * @y: IP address | |
414 | * | |
415 | * This function returns a bitwise or of @x and @y. | |
416 | */ | |
417 | ip_addr ipa_or(ip_addr x, ip_addr y) { DUMMY } | |
418 | ||
419 | /** | |
420 | * ipa_xor - compute bitwise xor of two IP addresses | |
421 | * @x: IP address | |
422 | * @y: IP address | |
423 | * | |
424 | * This function returns a bitwise xor of @x and @y. | |
425 | */ | |
426 | ip_addr ipa_xor(ip_addr x, ip_addr y) { DUMMY } | |
427 | ||
428 | /** | |
429 | * ipa_not - compute bitwise negation of two IP addresses | |
430 | * @x: IP address | |
431 | * | |
432 | * This function returns a bitwise negation of @x. | |
433 | */ | |
434 | ip_addr ipa_not(ip_addr x) { DUMMY } | |
435 | ||
436 | /** | |
437 | * ipa_mkmask - create a netmask | |
438 | * @x: prefix length | |
439 | * | |
440 | * This function returns an &ip_addr corresponding of a netmask | |
441 | * of an address prefix of size @x. | |
442 | */ | |
443 | ip_addr ipa_mkmask(int x) { DUMMY } | |
444 | ||
445 | /** | |
88a183c6 | 446 | * ipa_masklen - calculate netmask length |
7722938d MM |
447 | * @x: IP address |
448 | * | |
449 | * This function checks whether @x represents a valid netmask and | |
450 | * returns the size of the associate network prefix or -1 for invalid | |
451 | * mask. | |
452 | */ | |
88a183c6 | 453 | int ipa_masklen(ip_addr x) { DUMMY } |
7722938d MM |
454 | |
455 | /** | |
456 | * ipa_hash - hash IP addresses | |
457 | * @x: IP address | |
458 | * | |
459 | * ipa_hash() returns a 16-bit hash value of the IP address @x. | |
460 | */ | |
461 | int ipa_hash(ip_addr x) { DUMMY } | |
462 | ||
463 | /** | |
464 | * ipa_hton - convert IP address to network order | |
465 | * @x: IP address | |
466 | * | |
467 | * Converts the IP address @x to the network byte order. | |
468 | * | |
469 | * Beware, this is a macro and it alters the argument! | |
470 | */ | |
471 | void ipa_hton(ip_addr x) { DUMMY } | |
472 | ||
473 | /** | |
474 | * ipa_ntoh - convert IP address to host order | |
475 | * @x: IP address | |
476 | * | |
477 | * Converts the IP address @x from the network byte order. | |
478 | * | |
479 | * Beware, this is a macro and it alters the argument! | |
480 | */ | |
481 | void ipa_ntoh(ip_addr x) { DUMMY } | |
482 | ||
483 | /** | |
484 | * ipa_classify - classify an IP address | |
485 | * @x: IP address | |
486 | * | |
487 | * ipa_classify() returns an address class of @x, that is a bitwise or | |
488 | * of address type (%IADDR_INVALID, %IADDR_HOST, %IADDR_BROADCAST, %IADDR_MULTICAST) | |
2e9b2421 | 489 | * with address scope (%SCOPE_HOST to %SCOPE_UNIVERSE) or -1 (%IADDR_INVALID) |
7722938d MM |
490 | * for an invalid address. |
491 | */ | |
492 | int ipa_classify(ip_addr x) { DUMMY } | |
493 | ||
7722938d | 494 | /** |
88a183c6 OZ |
495 | * ip4_class_mask - guess netmask according to address class |
496 | * @x: IPv4 address | |
7722938d MM |
497 | * |
498 | * This function (available in IPv4 version only) returns a | |
499 | * network mask according to the address class of @x. Although | |
500 | * classful addressing is nowadays obsolete, there still live | |
501 | * routing protocols transferring no prefix lengths nor netmasks | |
502 | * and this function could be useful to them. | |
503 | */ | |
88a183c6 | 504 | ip4_addr ip4_class_mask(ip4_addr x) { DUMMY } |
7722938d MM |
505 | |
506 | /** | |
507 | * ipa_from_u32 - convert IPv4 address to an integer | |
508 | * @x: IP address | |
509 | * | |
510 | * This function takes an IPv4 address and returns its numeric | |
511 | * representation. | |
512 | */ | |
513 | u32 ipa_from_u32(ip_addr x) { DUMMY } | |
514 | ||
515 | /** | |
516 | * ipa_to_u32 - convert integer to IPv4 address | |
517 | * @x: a 32-bit integer | |
518 | * | |
519 | * ipa_to_u32() takes a numeric representation of an IPv4 address | |
520 | * and converts it to the corresponding &ip_addr. | |
521 | */ | |
522 | ip_addr ipa_to_u32(u32 x) { DUMMY } | |
523 | ||
524 | /** | |
525 | * ipa_compare - compare two IP addresses for order | |
526 | * @x: IP address | |
527 | * @y: IP address | |
528 | * | |
529 | * The ipa_compare() function takes two IP addresses and returns | |
530 | * -1 if @x is less than @y in canonical ordering (lexicographical | |
531 | * order of the bit strings), 1 if @x is greater than @y and 0 | |
532 | * if they are the same. | |
533 | */ | |
534 | int ipa_compare(ip_addr x, ip_addr y) { DUMMY } | |
535 | ||
536 | /** | |
88a183c6 | 537 | * ipa_build6 - build an IPv6 address from parts |
7722938d MM |
538 | * @a1: part #1 |
539 | * @a2: part #2 | |
540 | * @a3: part #3 | |
541 | * @a4: part #4 | |
542 | * | |
543 | * ipa_build() takes @a1 to @a4 and assembles them to a single IPv6 | |
544 | * address. It's used for example when a protocol wants to bind its | |
545 | * socket to a hard-wired multicast address. | |
546 | */ | |
88a183c6 | 547 | ip_addr ipa_build6(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY } |
7722938d MM |
548 | |
549 | /** | |
550 | * ip_ntop - convert IP address to textual representation | |
551 | * @a: IP address | |
552 | * @buf: buffer of size at least %STD_ADDRESS_P_LENGTH | |
553 | * | |
554 | * This function takes an IP address and creates its textual | |
555 | * representation for presenting to the user. | |
556 | */ | |
557 | char *ip_ntop(ip_addr a, char *buf) { DUMMY } | |
558 | ||
559 | /** | |
560 | * ip_ntox - convert IP address to hexadecimal representation | |
561 | * @a: IP address | |
562 | * @buf: buffer of size at least %STD_ADDRESS_P_LENGTH | |
563 | * | |
564 | * This function takes an IP address and creates its hexadecimal | |
565 | * textual representation. Primary use: debugging dumps. | |
566 | */ | |
567 | char *ip_ntox(ip_addr a, char *buf) { DUMMY } | |
568 | ||
569 | /** | |
570 | * ip_pton - parse textual representation of IP address | |
571 | * @a: textual representation | |
572 | * @o: where to put the resulting address | |
573 | * | |
574 | * This function parses a textual IP address representation and | |
575 | * stores the decoded address to a variable pointed to by @o. | |
2e9b2421 | 576 | * Returns 0 if a parse error has occurred, else 0. |
7722938d MM |
577 | */ |
578 | int ip_pton(char *a, ip_addr *o) { DUMMY } | |
579 | ||
580 | #endif |