iof-bird-daemon / lib / ip.c @ 04632fd7
History | View | Annotate | Download (12.3 KB)
1 |
/*
|
---|---|
2 |
* BIRD Library -- IP address functions
|
3 |
*
|
4 |
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
5 |
*
|
6 |
* Can be freely distributed and used under the terms of the GNU GPL.
|
7 |
*/
|
8 |
|
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
|
15 |
* they must be manipulated using the following functions and macros.
|
16 |
*/
|
17 |
|
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 |
uint |
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 == 255) |
71 |
return j;
|
72 |
n += j; |
73 |
while (++i < 4) |
74 |
if (a->addr[i])
|
75 |
return 255; |
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(const 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(const char *a, ip6_addr *o) |
262 |
{ |
263 |
u16 words[8];
|
264 |
int i, j, k, l, hfil;
|
265 |
const 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 |
|
345 |
/**
|
346 |
* ip_scope_text - get textual representation of address scope
|
347 |
* @scope: scope (%SCOPE_xxx)
|
348 |
*
|
349 |
* Returns a pointer to a textual name of the scope given.
|
350 |
*/
|
351 |
char *
|
352 |
ip_scope_text(uint scope) |
353 |
{ |
354 |
static char *scope_table[] = { "host", "link", "site", "org", "univ", "undef" }; |
355 |
|
356 |
if (scope > SCOPE_UNDEFINED)
|
357 |
return "?"; |
358 |
else
|
359 |
return scope_table[scope];
|
360 |
} |
361 |
|
362 |
ip4_addr |
363 |
ip4_class_mask(ip4_addr ad) |
364 |
{ |
365 |
u32 m, a = _I(ad); |
366 |
|
367 |
if (a == 0x00000000) |
368 |
m = 0x00000000;
|
369 |
else if (a < 0x80000000) |
370 |
m = 0xff000000;
|
371 |
else if (a < 0xc0000000) |
372 |
m = 0xffff0000;
|
373 |
else
|
374 |
m = 0xffffff00;
|
375 |
if (a & ~m)
|
376 |
m = 0xffffffff;
|
377 |
|
378 |
return _MI4(m);
|
379 |
} |
380 |
|
381 |
#if 0
|
382 |
/**
|
383 |
* ipa_equal - compare two IP addresses for equality
|
384 |
* @x: IP address
|
385 |
* @y: IP address
|
386 |
*
|
387 |
* ipa_equal() returns 1 if @x and @y represent the same IP address, else 0.
|
388 |
*/
|
389 |
int ipa_equal(ip_addr x, ip_addr y) { DUMMY }
|
390 |
|
391 |
/**
|
392 |
* ipa_nonzero - test if an IP address is defined
|
393 |
* @x: IP address
|
394 |
*
|
395 |
* ipa_nonzero returns 1 if @x is a defined IP address (not all bits are zero),
|
396 |
* else 0.
|
397 |
*
|
398 |
* The undefined all-zero address is reachable as a |IPA_NONE| macro.
|
399 |
*/
|
400 |
int ipa_nonzero(ip_addr x) { DUMMY }
|
401 |
|
402 |
/**
|
403 |
* ipa_and - compute bitwise and of two IP addresses
|
404 |
* @x: IP address
|
405 |
* @y: IP address
|
406 |
*
|
407 |
* This function returns a bitwise and of @x and @y. It's primarily
|
408 |
* used for network masking.
|
409 |
*/
|
410 |
ip_addr ipa_and(ip_addr x, ip_addr y) { DUMMY }
|
411 |
|
412 |
/**
|
413 |
* ipa_or - compute bitwise or of two IP addresses
|
414 |
* @x: IP address
|
415 |
* @y: IP address
|
416 |
*
|
417 |
* This function returns a bitwise or of @x and @y.
|
418 |
*/
|
419 |
ip_addr ipa_or(ip_addr x, ip_addr y) { DUMMY }
|
420 |
|
421 |
/**
|
422 |
* ipa_xor - compute bitwise xor of two IP addresses
|
423 |
* @x: IP address
|
424 |
* @y: IP address
|
425 |
*
|
426 |
* This function returns a bitwise xor of @x and @y.
|
427 |
*/
|
428 |
ip_addr ipa_xor(ip_addr x, ip_addr y) { DUMMY }
|
429 |
|
430 |
/**
|
431 |
* ipa_not - compute bitwise negation of two IP addresses
|
432 |
* @x: IP address
|
433 |
*
|
434 |
* This function returns a bitwise negation of @x.
|
435 |
*/
|
436 |
ip_addr ipa_not(ip_addr x) { DUMMY }
|
437 |
|
438 |
/**
|
439 |
* ipa_mkmask - create a netmask
|
440 |
* @x: prefix length
|
441 |
*
|
442 |
* This function returns an &ip_addr corresponding of a netmask
|
443 |
* of an address prefix of size @x.
|
444 |
*/
|
445 |
ip_addr ipa_mkmask(int x) { DUMMY }
|
446 |
|
447 |
/**
|
448 |
* ipa_masklen - calculate netmask length
|
449 |
* @x: IP address
|
450 |
*
|
451 |
* This function checks whether @x represents a valid netmask and
|
452 |
* returns the size of the associate network prefix or -1 for invalid
|
453 |
* mask.
|
454 |
*/
|
455 |
int ipa_masklen(ip_addr x) { DUMMY }
|
456 |
|
457 |
/**
|
458 |
* ipa_hash - hash IP addresses
|
459 |
* @x: IP address
|
460 |
*
|
461 |
* ipa_hash() returns a 16-bit hash value of the IP address @x.
|
462 |
*/
|
463 |
int ipa_hash(ip_addr x) { DUMMY }
|
464 |
|
465 |
/**
|
466 |
* ipa_hton - convert IP address to network order
|
467 |
* @x: IP address
|
468 |
*
|
469 |
* Converts the IP address @x to the network byte order.
|
470 |
*
|
471 |
* Beware, this is a macro and it alters the argument!
|
472 |
*/
|
473 |
void ipa_hton(ip_addr x) { DUMMY }
|
474 |
|
475 |
/**
|
476 |
* ipa_ntoh - convert IP address to host order
|
477 |
* @x: IP address
|
478 |
*
|
479 |
* Converts the IP address @x from the network byte order.
|
480 |
*
|
481 |
* Beware, this is a macro and it alters the argument!
|
482 |
*/
|
483 |
void ipa_ntoh(ip_addr x) { DUMMY }
|
484 |
|
485 |
/**
|
486 |
* ipa_classify - classify an IP address
|
487 |
* @x: IP address
|
488 |
*
|
489 |
* ipa_classify() returns an address class of @x, that is a bitwise or
|
490 |
* of address type (%IADDR_INVALID, %IADDR_HOST, %IADDR_BROADCAST, %IADDR_MULTICAST)
|
491 |
* with address scope (%SCOPE_HOST to %SCOPE_UNIVERSE) or -1 (%IADDR_INVALID)
|
492 |
* for an invalid address.
|
493 |
*/
|
494 |
int ipa_classify(ip_addr x) { DUMMY }
|
495 |
|
496 |
/**
|
497 |
* ip4_class_mask - guess netmask according to address class
|
498 |
* @x: IPv4 address
|
499 |
*
|
500 |
* This function (available in IPv4 version only) returns a
|
501 |
* network mask according to the address class of @x. Although
|
502 |
* classful addressing is nowadays obsolete, there still live
|
503 |
* routing protocols transferring no prefix lengths nor netmasks
|
504 |
* and this function could be useful to them.
|
505 |
*/
|
506 |
ip4_addr ip4_class_mask(ip4_addr x) { DUMMY }
|
507 |
|
508 |
/**
|
509 |
* ipa_from_u32 - convert IPv4 address to an integer
|
510 |
* @x: IP address
|
511 |
*
|
512 |
* This function takes an IPv4 address and returns its numeric
|
513 |
* representation.
|
514 |
*/
|
515 |
u32 ipa_from_u32(ip_addr x) { DUMMY }
|
516 |
|
517 |
/**
|
518 |
* ipa_to_u32 - convert integer to IPv4 address
|
519 |
* @x: a 32-bit integer
|
520 |
*
|
521 |
* ipa_to_u32() takes a numeric representation of an IPv4 address
|
522 |
* and converts it to the corresponding &ip_addr.
|
523 |
*/
|
524 |
ip_addr ipa_to_u32(u32 x) { DUMMY }
|
525 |
|
526 |
/**
|
527 |
* ipa_compare - compare two IP addresses for order
|
528 |
* @x: IP address
|
529 |
* @y: IP address
|
530 |
*
|
531 |
* The ipa_compare() function takes two IP addresses and returns
|
532 |
* -1 if @x is less than @y in canonical ordering (lexicographical
|
533 |
* order of the bit strings), 1 if @x is greater than @y and 0
|
534 |
* if they are the same.
|
535 |
*/
|
536 |
int ipa_compare(ip_addr x, ip_addr y) { DUMMY }
|
537 |
|
538 |
/**
|
539 |
* ipa_build6 - build an IPv6 address from parts
|
540 |
* @a1: part #1
|
541 |
* @a2: part #2
|
542 |
* @a3: part #3
|
543 |
* @a4: part #4
|
544 |
*
|
545 |
* ipa_build() takes @a1 to @a4 and assembles them to a single IPv6
|
546 |
* address. It's used for example when a protocol wants to bind its
|
547 |
* socket to a hard-wired multicast address.
|
548 |
*/
|
549 |
ip_addr ipa_build6(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY }
|
550 |
|
551 |
/**
|
552 |
* ip_ntop - convert IP address to textual representation
|
553 |
* @a: IP address
|
554 |
* @buf: buffer of size at least %STD_ADDRESS_P_LENGTH
|
555 |
*
|
556 |
* This function takes an IP address and creates its textual
|
557 |
* representation for presenting to the user.
|
558 |
*/
|
559 |
char *ip_ntop(ip_addr a, char *buf) { DUMMY }
|
560 |
|
561 |
/**
|
562 |
* ip_ntox - convert IP address to hexadecimal representation
|
563 |
* @a: IP address
|
564 |
* @buf: buffer of size at least %STD_ADDRESS_P_LENGTH
|
565 |
*
|
566 |
* This function takes an IP address and creates its hexadecimal
|
567 |
* textual representation. Primary use: debugging dumps.
|
568 |
*/
|
569 |
char *ip_ntox(ip_addr a, char *buf) { DUMMY }
|
570 |
|
571 |
/**
|
572 |
* ip_pton - parse textual representation of IP address
|
573 |
* @a: textual representation
|
574 |
* @o: where to put the resulting address
|
575 |
*
|
576 |
* This function parses a textual IP address representation and
|
577 |
* stores the decoded address to a variable pointed to by @o.
|
578 |
* Returns 0 if a parse error has occurred, else 0.
|
579 |
*/
|
580 |
int ip_pton(char *a, ip_addr *o) { DUMMY }
|
581 |
|
582 |
#endif
|