File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / lib / ip.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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>