Annotation of embedaddon/bird/lib/ip.c, revision 1.1
1.1 ! misho 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: 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(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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>