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>