diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2014-10-24 11:11:43 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2014-10-24 11:11:43 +0200 |
commit | 88a183c6c9a2b86b52f67e87bbc8b7edd32670c6 (patch) | |
tree | b1348b71e69f9ed0d919a4792549026c9e31b092 /lib/ipv6.c | |
parent | f8fefde318c6248ad94e7b6d60155deed9ab8eed (diff) |
Integrated IP functions.
Diffstat (limited to 'lib/ipv6.c')
-rw-r--r-- | lib/ipv6.c | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/lib/ipv6.c b/lib/ipv6.c deleted file mode 100644 index 623f6328..00000000 --- a/lib/ipv6.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * BIRD Library -- IPv6 Address Manipulation Functions - * - * (c) 1999 Martin Mares <mj@ucw.cz> - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#include <stdlib.h> - -#include "nest/bird.h" -#include "lib/ip.h" -#include "lib/bitops.h" -#include "lib/endian.h" -#include "lib/string.h" - -/* - * See RFC 2373 for explanation of IPv6 addressing issues. - */ - -ip_addr -ipv6_mkmask(unsigned n) -{ - ip_addr a; - int i; - - for(i=0; i<4; i++) - { - if (!n) - a.addr[i] = 0; - else if (n >= 32) - { - a.addr[i] = ~0; - n -= 32; - } - else - { - a.addr[i] = u32_mkmask(n); - n = 0; - } - } - return a; -} - -unsigned -ipv6_mklen(ip_addr *a) -{ - int i, j, n; - - for(i=0, n=0; i<4; i++, n+=32) - if (a->addr[i] != ~0U) - { - j = u32_masklen(a->addr[i]); - if (j < 0) - return j; - n += j; - while (++i < 4) - if (a->addr[i]) - return -1; - break; - } - return n; -} - -int -ipv6_classify(ip_addr *a) -{ - u32 x = a->addr[0]; - - if ((x & 0xe0000000) == 0x20000000) /* 2000::/3 Aggregatable Global Unicast Address */ - return IADDR_HOST | SCOPE_UNIVERSE; - if ((x & 0xffc00000) == 0xfe800000) /* fe80::/10 Link-Local Address */ - return IADDR_HOST | SCOPE_LINK; - if ((x & 0xffc00000) == 0xfec00000) /* fec0::/10 Site-Local Address */ - return IADDR_HOST | SCOPE_SITE; - if ((x & 0xfe000000) == 0xfc000000) /* fc00::/7 Unique Local Unicast Address (RFC 4193) */ - return IADDR_HOST | SCOPE_SITE; - if ((x & 0xff000000) == 0xff000000) /* ff00::/8 Multicast Address */ - { - unsigned int scope = (x >> 16) & 0x0f; - switch (scope) - { - case 1: return IADDR_MULTICAST | SCOPE_HOST; - case 2: return IADDR_MULTICAST | SCOPE_LINK; - case 5: return IADDR_MULTICAST | SCOPE_SITE; - case 8: return IADDR_MULTICAST | SCOPE_ORGANIZATION; - case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE; - default: return IADDR_MULTICAST | SCOPE_UNDEFINED; - } - } - if (!x && !a->addr[1] && !a->addr[2]) - { - u32 y = a->addr[3]; - if (y == 1) - return IADDR_HOST | SCOPE_HOST; /* Loopback address */ - /* IPv4 compatible addresses */ - if (y >= 0x7f000000 && y < 0x80000000) - return IADDR_HOST | SCOPE_HOST; - if ((y & 0xff000000) == 0x0a000000 || - (y & 0xffff0000) == 0xc0a80000 || - (y & 0xfff00000) == 0xac100000) - return IADDR_HOST | SCOPE_SITE; - if (y >= 0x01000000 && y < 0xe0000000) - return IADDR_HOST | SCOPE_UNIVERSE; - } - return IADDR_HOST | SCOPE_UNDEFINED; -} - -void -ipv6_hton(ip_addr *a) -{ - int i; - - for(i=0; i<4; i++) - a->addr[i] = htonl(a->addr[i]); -} - -void -ipv6_ntoh(ip_addr *a) -{ - int i; - - for(i=0; i<4; i++) - a->addr[i] = ntohl(a->addr[i]); -} - -int -ipv6_compare(ip_addr X, ip_addr Y) -{ - int i; - ip_addr *x = &X; - ip_addr *y = &Y; - - for(i=0; i<4; i++) - if (x->addr[i] > y->addr[i]) - return 1; - else if (x->addr[i] < y->addr[i]) - return -1; - return 0; -} - -/* - * Conversion of IPv6 address to presentation format and vice versa. - * Heavily inspired by routines written by Paul Vixie for the BIND project - * and of course by RFC 2373. - */ - -char * -ip_ntop(ip_addr a, char *b) -{ - u16 words[8]; - int bestpos, bestlen, curpos, curlen, i; - - /* First of all, preprocess the address and find the longest run of zeros */ - bestlen = bestpos = curpos = curlen = 0; - for(i=0; i<8; i++) - { - u32 x = a.addr[i/2]; - words[i] = ((i%2) ? x : (x >> 16)) & 0xffff; - if (words[i]) - curlen = 0; - else - { - if (!curlen) - curpos = i; - curlen++; - if (curlen > bestlen) - { - bestpos = curpos; - bestlen = curlen; - } - } - } - if (bestlen < 2) - bestpos = -1; - - /* Is it an encapsulated IPv4 address? */ - if (!bestpos && - (bestlen == 5 && a.addr[2] == 0xffff || - bestlen == 6)) - { - u32 x = a.addr[3]; - b += bsprintf(b, "::%s%d.%d.%d.%d", - a.addr[2] ? "ffff:" : "", - ((x >> 24) & 0xff), - ((x >> 16) & 0xff), - ((x >> 8) & 0xff), - (x & 0xff)); - return b; - } - - /* Normal IPv6 formatting, compress the largest sequence of zeros */ - for(i=0; i<8; i++) - { - if (i == bestpos) - { - i += bestlen - 1; - *b++ = ':'; - if (i == 7) - *b++ = ':'; - } - else - { - if (i) - *b++ = ':'; - b += bsprintf(b, "%x", words[i]); - } - } - *b = 0; - return b; -} - -char * -ip_ntox(ip_addr a, char *b) -{ - int i; - - for(i=0; i<4; i++) - { - if (i) - *b++ = '.'; - b += bsprintf(b, "%08x", a.addr[i]); - } - return b; -} - -int -ipv4_pton_u32(char *a, u32 *o) -{ - int i; - unsigned long int l; - u32 ia = 0; - - i=4; - while (i--) - { - char *d, *c = strchr(a, '.'); - if (!c != !i) - return 0; - l = strtoul(a, &d, 10); - if (d != c && *d || l > 255) - return 0; - ia = (ia << 8) | l; - if (c) - c++; - a = c; - } - *o = ia; - return 1; -} - -int -ip_pton(char *a, ip_addr *o) -{ - u16 words[8]; - int i, j, k, l, hfil; - char *start; - - if (a[0] == ':') /* Leading :: */ - { - if (a[1] != ':') - return 0; - a++; - } - hfil = -1; - i = 0; - while (*a) - { - if (*a == ':') /* :: */ - { - if (hfil >= 0) - return 0; - hfil = i; - a++; - continue; - } - j = 0; - l = 0; - start = a; - for(;;) - { - if (*a >= '0' && *a <= '9') - k = *a++ - '0'; - else if (*a >= 'A' && *a <= 'F') - k = *a++ - 'A' + 10; - else if (*a >= 'a' && *a <= 'f') - k = *a++ - 'a' + 10; - else - break; - j = (j << 4) + k; - if (j >= 0x10000 || ++l > 4) - return 0; - } - if (*a == ':' && a[1]) - a++; - else if (*a == '.' && (i == 6 || i < 6 && hfil >= 0)) - { /* Embedded IPv4 address */ - u32 x; - if (!ipv4_pton_u32(start, &x)) - return 0; - words[i++] = x >> 16; - words[i++] = x; - break; - } - else if (*a) - return 0; - if (i >= 8) - return 0; - words[i++] = j; - } - - /* Replace :: with an appropriate number of zeros */ - if (hfil >= 0) - { - j = 8 - i; - for(i=7; i-j >= hfil; i--) - words[i] = words[i-j]; - for(; i>=hfil; i--) - words[i] = 0; - } - - /* Convert the address to ip_addr format */ - for(i=0; i<4; i++) - o->addr[i] = (words[2*i] << 16) | words[2*i+1]; - return 1; -} - -void ipv6_absolutize(ip_addr *a, ip_addr *ifa) -{ - if ((a->addr[0] & 0xffc00000) == 0xfe800000 && /* a is link-scope */ - ((ifa->addr[0] & 0xe0000000) == 0x20000000 | /* ifa is AGU ... */ - (ifa->addr[0] & 0xffc00000) == 0xfec00000)) /* ... or site-scope */ - { - a->addr[0] = ifa->addr[0]; /* Copy the prefix, leave interface ID */ - a->addr[1] = ifa->addr[1]; - } -} - -#ifdef TEST - -#include "bitops.c" - -static void test(char *x) -{ - ip_addr a; - char c[STD_ADDRESS_P_LENGTH+1]; - - printf("%-40s ", x); - if (!ip_pton(x, &a)) - { - puts("BAD"); - return; - } - ip_ntop(a, c); - printf("%-40s %04x\n", c, ipv6_classify(&a)); -} - -int main(void) -{ - puts("Positive tests:"); - test("1:2:3:4:5:6:7:8"); - test("dead:beef:DEAD:BEEF::f00d"); - test("::"); - test("::1"); - test("1::"); - test("::1.234.5.6"); - test("::ffff:1.234.5.6"); - test("::fffe:1.234.5.6"); - test("1:2:3:4:5:6:7::8"); - test("2080::8:800:200c:417a"); - test("ff01::101"); - - puts("Negative tests:"); - test(":::"); - test("1:2:3:4:5:6:7:8:"); - test("1::2::3"); - test("::12345"); - test("::1.2.3.4:5"); - test(":1:2:3:4:5:6:7:8"); - test("g:1:2:3:4:5:6:7"); - return 0; -} - -#endif |