Annotation of embedaddon/quagga/lib/prefix.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Prefix related functions.
        !             3:  * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "prefix.h"
        !            26: #include "vty.h"
        !            27: #include "sockunion.h"
        !            28: #include "memory.h"
        !            29: #include "log.h"
        !            30: 
        !            31: /* Maskbit. */
        !            32: static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
        !            33:                                 0xf8, 0xfc, 0xfe, 0xff};
        !            34: 
        !            35: /* Number of bits in prefix type. */
        !            36: #ifndef PNBBY
        !            37: #define PNBBY 8
        !            38: #endif /* PNBBY */
        !            39: 
        !            40: #define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff)
        !            41: 
        !            42: /* Address Famiy Identifier to Address Family converter. */
        !            43: int
        !            44: afi2family (afi_t afi)
        !            45: {
        !            46:   if (afi == AFI_IP)
        !            47:     return AF_INET;
        !            48: #ifdef HAVE_IPV6
        !            49:   else if (afi == AFI_IP6)
        !            50:     return AF_INET6;
        !            51: #endif /* HAVE_IPV6 */
        !            52:   return 0;
        !            53: }
        !            54: 
        !            55: afi_t
        !            56: family2afi (int family)
        !            57: {
        !            58:   if (family == AF_INET)
        !            59:     return AFI_IP;
        !            60: #ifdef HAVE_IPV6
        !            61:   else if (family == AF_INET6)
        !            62:     return AFI_IP6;
        !            63: #endif /* HAVE_IPV6 */
        !            64:   return 0;
        !            65: }
        !            66: 
        !            67: /* If n includes p prefix then return 1 else return 0. */
        !            68: int
        !            69: prefix_match (const struct prefix *n, const struct prefix *p)
        !            70: {
        !            71:   int offset;
        !            72:   int shift;
        !            73:   const u_char *np, *pp;
        !            74: 
        !            75:   /* If n's prefix is longer than p's one return 0. */
        !            76:   if (n->prefixlen > p->prefixlen)
        !            77:     return 0;
        !            78: 
        !            79:   /* Set both prefix's head pointer. */
        !            80:   np = (const u_char *)&n->u.prefix;
        !            81:   pp = (const u_char *)&p->u.prefix;
        !            82:   
        !            83:   offset = n->prefixlen / PNBBY;
        !            84:   shift =  n->prefixlen % PNBBY;
        !            85: 
        !            86:   if (shift)
        !            87:     if (maskbit[shift] & (np[offset] ^ pp[offset]))
        !            88:       return 0;
        !            89:   
        !            90:   while (offset--)
        !            91:     if (np[offset] != pp[offset])
        !            92:       return 0;
        !            93:   return 1;
        !            94: }
        !            95: 
        !            96: /* Copy prefix from src to dest. */
        !            97: void
        !            98: prefix_copy (struct prefix *dest, const struct prefix *src)
        !            99: {
        !           100:   dest->family = src->family;
        !           101:   dest->prefixlen = src->prefixlen;
        !           102: 
        !           103:   if (src->family == AF_INET)
        !           104:     dest->u.prefix4 = src->u.prefix4;
        !           105: #ifdef HAVE_IPV6
        !           106:   else if (src->family == AF_INET6)
        !           107:     dest->u.prefix6 = src->u.prefix6;
        !           108: #endif /* HAVE_IPV6 */
        !           109:   else if (src->family == AF_UNSPEC)
        !           110:     {
        !           111:       dest->u.lp.id = src->u.lp.id;
        !           112:       dest->u.lp.adv_router = src->u.lp.adv_router;
        !           113:     }
        !           114:   else
        !           115:     {
        !           116:       zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
        !           117:              src->family);
        !           118:       assert (0);
        !           119:     }
        !           120: }
        !           121: 
        !           122: /* 
        !           123:  * Return 1 if the address/netmask contained in the prefix structure
        !           124:  * is the same, and else return 0.  For this routine, 'same' requires
        !           125:  * that not only the prefix length and the network part be the same,
        !           126:  * but also the host part.  Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
        !           127:  * the same.  Note that this routine has the same return value sense
        !           128:  * as '==' (which is different from prefix_cmp).
        !           129:  */
        !           130: int
        !           131: prefix_same (const struct prefix *p1, const struct prefix *p2)
        !           132: {
        !           133:   if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
        !           134:     {
        !           135:       if (p1->family == AF_INET)
        !           136:        if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
        !           137:          return 1;
        !           138: #ifdef HAVE_IPV6
        !           139:       if (p1->family == AF_INET6 )
        !           140:        if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
        !           141:          return 1;
        !           142: #endif /* HAVE_IPV6 */
        !           143:     }
        !           144:   return 0;
        !           145: }
        !           146: 
        !           147: /*
        !           148:  * Return 0 if the network prefixes represented by the struct prefix
        !           149:  * arguments are the same prefix, and 1 otherwise.  Network prefixes
        !           150:  * are considered the same if the prefix lengths are equal and the
        !           151:  * network parts are the same.  Host bits (which are considered masked
        !           152:  * by the prefix length) are not significant.  Thus, 10.0.0.1/8 and
        !           153:  * 10.0.0.2/8 are considered equivalent by this routine.  Note that
        !           154:  * this routine has the same return sense as strcmp (which is different
        !           155:  * from prefix_same).
        !           156:  */
        !           157: int
        !           158: prefix_cmp (const struct prefix *p1, const struct prefix *p2)
        !           159: {
        !           160:   int offset;
        !           161:   int shift;
        !           162: 
        !           163:   /* Set both prefix's head pointer. */
        !           164:   const u_char *pp1 = (const u_char *)&p1->u.prefix;
        !           165:   const u_char *pp2 = (const u_char *)&p2->u.prefix;
        !           166: 
        !           167:   if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
        !           168:     return 1;
        !           169: 
        !           170:   offset = p1->prefixlen / 8;
        !           171:   shift = p1->prefixlen % 8;
        !           172: 
        !           173:   if (shift)
        !           174:     if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
        !           175:       return 1;
        !           176: 
        !           177:   while (offset--)
        !           178:     if (pp1[offset] != pp2[offset])
        !           179:       return 1;
        !           180: 
        !           181:   return 0;
        !           182: }
        !           183: 
        !           184: /* Return prefix family type string. */
        !           185: const char *
        !           186: prefix_family_str (const struct prefix *p)
        !           187: {
        !           188:   if (p->family == AF_INET)
        !           189:     return "inet";
        !           190: #ifdef HAVE_IPV6
        !           191:   if (p->family == AF_INET6)
        !           192:     return "inet6";
        !           193: #endif /* HAVE_IPV6 */
        !           194:   return "unspec";
        !           195: }
        !           196: 
        !           197: /* Allocate new prefix_ipv4 structure. */
        !           198: struct prefix_ipv4 *
        !           199: prefix_ipv4_new ()
        !           200: {
        !           201:   struct prefix_ipv4 *p;
        !           202: 
        !           203:   /* Call prefix_new to allocate a full-size struct prefix to avoid problems
        !           204:      where the struct prefix_ipv4 is cast to struct prefix and unallocated
        !           205:      bytes were being referenced (e.g. in structure assignments). */
        !           206:   p = (struct prefix_ipv4 *)prefix_new();
        !           207:   p->family = AF_INET;
        !           208:   return p;
        !           209: }
        !           210: 
        !           211: /* Free prefix_ipv4 structure. */
        !           212: void
        !           213: prefix_ipv4_free (struct prefix_ipv4 *p)
        !           214: {
        !           215:   prefix_free((struct prefix *)p);
        !           216: }
        !           217: 
        !           218: /* When string format is invalid return 0. */
        !           219: int
        !           220: str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
        !           221: {
        !           222:   int ret;
        !           223:   int plen;
        !           224:   char *pnt;
        !           225:   char *cp;
        !           226: 
        !           227:   /* Find slash inside string. */
        !           228:   pnt = strchr (str, '/');
        !           229: 
        !           230:   /* String doesn't contail slash. */
        !           231:   if (pnt == NULL) 
        !           232:     {
        !           233:       /* Convert string to prefix. */
        !           234:       ret = inet_aton (str, &p->prefix);
        !           235:       if (ret == 0)
        !           236:        return 0;
        !           237: 
        !           238:       /* If address doesn't contain slash we assume it host address. */
        !           239:       p->family = AF_INET;
        !           240:       p->prefixlen = IPV4_MAX_BITLEN;
        !           241: 
        !           242:       return ret;
        !           243:     }
        !           244:   else
        !           245:     {
        !           246:       cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
        !           247:       strncpy (cp, str, pnt - str);
        !           248:       *(cp + (pnt - str)) = '\0';
        !           249:       ret = inet_aton (cp, &p->prefix);
        !           250:       XFREE (MTYPE_TMP, cp);
        !           251: 
        !           252:       /* Get prefix length. */
        !           253:       plen = (u_char) atoi (++pnt);
        !           254:       if (plen > IPV4_MAX_PREFIXLEN)
        !           255:        return 0;
        !           256: 
        !           257:       p->family = AF_INET;
        !           258:       p->prefixlen = plen;
        !           259:     }
        !           260: 
        !           261:   return ret;
        !           262: }
        !           263: 
        !           264: /* Convert masklen into IP address's netmask. */
        !           265: void
        !           266: masklen2ip (int masklen, struct in_addr *netmask)
        !           267: {
        !           268:   u_char *pnt;
        !           269:   int bit;
        !           270:   int offset;
        !           271: 
        !           272:   memset (netmask, 0, sizeof (struct in_addr));
        !           273:   pnt = (unsigned char *) netmask;
        !           274: 
        !           275:   offset = masklen / 8;
        !           276:   bit = masklen % 8;
        !           277:   
        !           278:   while (offset--)
        !           279:     *pnt++ = 0xff;
        !           280: 
        !           281:   if (bit)
        !           282:     *pnt = maskbit[bit];
        !           283: }
        !           284: 
        !           285: /* Convert IP address's netmask into integer. We assume netmask is
        !           286:    sequential one. Argument netmask should be network byte order. */
        !           287: u_char
        !           288: ip_masklen (struct in_addr netmask)
        !           289: {
        !           290:   u_char len;
        !           291:   u_char *pnt;
        !           292:   u_char *end;
        !           293:   u_char val;
        !           294: 
        !           295:   len = 0;
        !           296:   pnt = (u_char *) &netmask;
        !           297:   end = pnt + 4;
        !           298: 
        !           299:   while ((pnt < end) && (*pnt == 0xff))
        !           300:     {
        !           301:       len+= 8;
        !           302:       pnt++;
        !           303:     } 
        !           304: 
        !           305:   if (pnt < end)
        !           306:     {
        !           307:       val = *pnt;
        !           308:       while (val)
        !           309:        {
        !           310:          len++;
        !           311:          val <<= 1;
        !           312:        }
        !           313:     }
        !           314:   return len;
        !           315: }
        !           316: 
        !           317: /* Apply mask to IPv4 prefix. */
        !           318: void
        !           319: apply_mask_ipv4 (struct prefix_ipv4 *p)
        !           320: {
        !           321:   u_char *pnt;
        !           322:   int index;
        !           323:   int offset;
        !           324: 
        !           325:   index = p->prefixlen / 8;
        !           326: 
        !           327:   if (index < 4)
        !           328:     {
        !           329:       pnt = (u_char *) &p->prefix;
        !           330:       offset = p->prefixlen % 8;
        !           331: 
        !           332:       pnt[index] &= maskbit[offset];
        !           333:       index++;
        !           334: 
        !           335:       while (index < 4)
        !           336:        pnt[index++] = 0;
        !           337:     }
        !           338: }
        !           339: 
        !           340: /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
        !           341: int
        !           342: prefix_ipv4_any (const struct prefix_ipv4 *p)
        !           343: {
        !           344:   return (p->prefix.s_addr == 0 && p->prefixlen == 0);
        !           345: }
        !           346: 
        !           347: #ifdef HAVE_IPV6
        !           348: 
        !           349: /* Allocate a new ip version 6 route */
        !           350: struct prefix_ipv6 *
        !           351: prefix_ipv6_new (void)
        !           352: {
        !           353:   struct prefix_ipv6 *p;
        !           354: 
        !           355:   /* Allocate a full-size struct prefix to avoid problems with structure
        !           356:      size mismatches. */
        !           357:   p = (struct prefix_ipv6 *)prefix_new();
        !           358:   p->family = AF_INET6;
        !           359:   return p;
        !           360: }
        !           361: 
        !           362: /* Free prefix for IPv6. */
        !           363: void
        !           364: prefix_ipv6_free (struct prefix_ipv6 *p)
        !           365: {
        !           366:   prefix_free((struct prefix *)p);
        !           367: }
        !           368: 
        !           369: /* If given string is valid return pin6 else return NULL */
        !           370: int
        !           371: str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
        !           372: {
        !           373:   char *pnt;
        !           374:   char *cp;
        !           375:   int ret;
        !           376: 
        !           377:   pnt = strchr (str, '/');
        !           378: 
        !           379:   /* If string doesn't contain `/' treat it as host route. */
        !           380:   if (pnt == NULL) 
        !           381:     {
        !           382:       ret = inet_pton (AF_INET6, str, &p->prefix);
        !           383:       if (ret == 0)
        !           384:        return 0;
        !           385:       p->prefixlen = IPV6_MAX_BITLEN;
        !           386:     }
        !           387:   else 
        !           388:     {
        !           389:       int plen;
        !           390: 
        !           391:       cp = XMALLOC (0, (pnt - str) + 1);
        !           392:       strncpy (cp, str, pnt - str);
        !           393:       *(cp + (pnt - str)) = '\0';
        !           394:       ret = inet_pton (AF_INET6, cp, &p->prefix);
        !           395:       free (cp);
        !           396:       if (ret == 0)
        !           397:        return 0;
        !           398:       plen = (u_char) atoi (++pnt);
        !           399:       if (plen > 128)
        !           400:        return 0;
        !           401:       p->prefixlen = plen;
        !           402:     }
        !           403:   p->family = AF_INET6;
        !           404: 
        !           405:   return ret;
        !           406: }
        !           407: 
        !           408: /* Convert struct in6_addr netmask into integer.
        !           409:  * FIXME return u_char as ip_maskleni() does. */
        !           410: int
        !           411: ip6_masklen (struct in6_addr netmask)
        !           412: {
        !           413:   int len = 0;
        !           414:   unsigned char val;
        !           415:   unsigned char *pnt;
        !           416:   
        !           417:   pnt = (unsigned char *) & netmask;
        !           418: 
        !           419:   while ((*pnt == 0xff) && len < 128) 
        !           420:     {
        !           421:       len += 8;
        !           422:       pnt++;
        !           423:     } 
        !           424:   
        !           425:   if (len < 128) 
        !           426:     {
        !           427:       val = *pnt;
        !           428:       while (val) 
        !           429:        {
        !           430:          len++;
        !           431:          val <<= 1;
        !           432:        }
        !           433:     }
        !           434:   return len;
        !           435: }
        !           436: 
        !           437: void
        !           438: masklen2ip6 (int masklen, struct in6_addr *netmask)
        !           439: {
        !           440:   unsigned char *pnt;
        !           441:   int bit;
        !           442:   int offset;
        !           443: 
        !           444:   memset (netmask, 0, sizeof (struct in6_addr));
        !           445:   pnt = (unsigned char *) netmask;
        !           446: 
        !           447:   offset = masklen / 8;
        !           448:   bit = masklen % 8;
        !           449: 
        !           450:   while (offset--)
        !           451:     *pnt++ = 0xff;
        !           452: 
        !           453:   if (bit)
        !           454:     *pnt = maskbit[bit];
        !           455: }
        !           456: 
        !           457: void
        !           458: apply_mask_ipv6 (struct prefix_ipv6 *p)
        !           459: {
        !           460:   u_char *pnt;
        !           461:   int index;
        !           462:   int offset;
        !           463: 
        !           464:   index = p->prefixlen / 8;
        !           465: 
        !           466:   if (index < 16)
        !           467:     {
        !           468:       pnt = (u_char *) &p->prefix;
        !           469:       offset = p->prefixlen % 8;
        !           470: 
        !           471:       pnt[index] &= maskbit[offset];
        !           472:       index++;
        !           473: 
        !           474:       while (index < 16)
        !           475:        pnt[index++] = 0;
        !           476:     }
        !           477: }
        !           478: 
        !           479: void
        !           480: str2in6_addr (const char *str, struct in6_addr *addr)
        !           481: {
        !           482:   int i;
        !           483:   unsigned int x;
        !           484: 
        !           485:   /* %x must point to unsinged int */
        !           486:   for (i = 0; i < 16; i++)
        !           487:     {
        !           488:       sscanf (str + (i * 2), "%02x", &x);
        !           489:       addr->s6_addr[i] = x & 0xff;
        !           490:     }
        !           491: }
        !           492: #endif /* HAVE_IPV6 */
        !           493: 
        !           494: void
        !           495: apply_mask (struct prefix *p)
        !           496: {
        !           497:   switch (p->family)
        !           498:     {
        !           499:       case AF_INET:
        !           500:         apply_mask_ipv4 ((struct prefix_ipv4 *)p);
        !           501:         break;
        !           502: #ifdef HAVE_IPV6
        !           503:       case AF_INET6:
        !           504:         apply_mask_ipv6 ((struct prefix_ipv6 *)p);
        !           505:         break;
        !           506: #endif /* HAVE_IPV6 */
        !           507:       default:
        !           508:         break;
        !           509:     }
        !           510:   return;
        !           511: }
        !           512: 
        !           513: /* Utility function of convert between struct prefix <=> union sockunion.
        !           514:  * FIXME This function isn't used anywhere. */
        !           515: struct prefix *
        !           516: sockunion2prefix (const union sockunion *dest,
        !           517:                  const union sockunion *mask)
        !           518: {
        !           519:   if (dest->sa.sa_family == AF_INET)
        !           520:     {
        !           521:       struct prefix_ipv4 *p;
        !           522: 
        !           523:       p = prefix_ipv4_new ();
        !           524:       p->family = AF_INET;
        !           525:       p->prefix = dest->sin.sin_addr;
        !           526:       p->prefixlen = ip_masklen (mask->sin.sin_addr);
        !           527:       return (struct prefix *) p;
        !           528:     }
        !           529: #ifdef HAVE_IPV6
        !           530:   if (dest->sa.sa_family == AF_INET6)
        !           531:     {
        !           532:       struct prefix_ipv6 *p;
        !           533: 
        !           534:       p = prefix_ipv6_new ();
        !           535:       p->family = AF_INET6;
        !           536:       p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
        !           537:       memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
        !           538:       return (struct prefix *) p;
        !           539:     }
        !           540: #endif /* HAVE_IPV6 */
        !           541:   return NULL;
        !           542: }
        !           543: 
        !           544: /* Utility function of convert between struct prefix <=> union sockunion. */
        !           545: struct prefix *
        !           546: sockunion2hostprefix (const union sockunion *su)
        !           547: {
        !           548:   if (su->sa.sa_family == AF_INET)
        !           549:     {
        !           550:       struct prefix_ipv4 *p;
        !           551: 
        !           552:       p = prefix_ipv4_new ();
        !           553:       p->family = AF_INET;
        !           554:       p->prefix = su->sin.sin_addr;
        !           555:       p->prefixlen = IPV4_MAX_BITLEN;
        !           556:       return (struct prefix *) p;
        !           557:     }
        !           558: #ifdef HAVE_IPV6
        !           559:   if (su->sa.sa_family == AF_INET6)
        !           560:     {
        !           561:       struct prefix_ipv6 *p;
        !           562: 
        !           563:       p = prefix_ipv6_new ();
        !           564:       p->family = AF_INET6;
        !           565:       p->prefixlen = IPV6_MAX_BITLEN;
        !           566:       memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
        !           567:       return (struct prefix *) p;
        !           568:     }
        !           569: #endif /* HAVE_IPV6 */
        !           570:   return NULL;
        !           571: }
        !           572: 
        !           573: int
        !           574: prefix_blen (const struct prefix *p)
        !           575: {
        !           576:   switch (p->family) 
        !           577:     {
        !           578:     case AF_INET:
        !           579:       return IPV4_MAX_BYTELEN;
        !           580:       break;
        !           581: #ifdef HAVE_IPV6
        !           582:     case AF_INET6:
        !           583:       return IPV6_MAX_BYTELEN;
        !           584:       break;
        !           585: #endif /* HAVE_IPV6 */
        !           586:     }
        !           587:   return 0;
        !           588: }
        !           589: 
        !           590: /* Generic function for conversion string to struct prefix. */
        !           591: int
        !           592: str2prefix (const char *str, struct prefix *p)
        !           593: {
        !           594:   int ret;
        !           595: 
        !           596:   /* First we try to convert string to struct prefix_ipv4. */
        !           597:   ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
        !           598:   if (ret)
        !           599:     return ret;
        !           600: 
        !           601: #ifdef HAVE_IPV6
        !           602:   /* Next we try to convert string to struct prefix_ipv6. */
        !           603:   ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
        !           604:   if (ret)
        !           605:     return ret;
        !           606: #endif /* HAVE_IPV6 */
        !           607: 
        !           608:   return 0;
        !           609: }
        !           610: 
        !           611: int
        !           612: prefix2str (const struct prefix *p, char *str, int size)
        !           613: {
        !           614:   char buf[BUFSIZ];
        !           615: 
        !           616:   inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
        !           617:   snprintf (str, size, "%s/%d", buf, p->prefixlen);
        !           618:   return 0;
        !           619: }
        !           620: 
        !           621: struct prefix *
        !           622: prefix_new ()
        !           623: {
        !           624:   struct prefix *p;
        !           625: 
        !           626:   p = XCALLOC (MTYPE_PREFIX, sizeof *p);
        !           627:   return p;
        !           628: }
        !           629: 
        !           630: /* Free prefix structure. */
        !           631: void
        !           632: prefix_free (struct prefix *p)
        !           633: {
        !           634:   XFREE (MTYPE_PREFIX, p);
        !           635: }
        !           636: 
        !           637: /* Utility function.  Check the string only contains digit
        !           638:  * character.
        !           639:  * FIXME str.[c|h] would be better place for this function. */
        !           640: int
        !           641: all_digit (const char *str)
        !           642: {
        !           643:   for (; *str != '\0'; str++)
        !           644:     if (!isdigit ((int) *str))
        !           645:       return 0;
        !           646:   return 1;
        !           647: }
        !           648: 
        !           649: /* Utility function to convert ipv4 prefixes to Classful prefixes */
        !           650: void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
        !           651: {
        !           652: 
        !           653:   u_int32_t destination;
        !           654:   
        !           655:   destination = ntohl (p->prefix.s_addr);
        !           656:   
        !           657:   if (p->prefixlen == IPV4_MAX_PREFIXLEN);
        !           658:   /* do nothing for host routes */
        !           659:   else if (IN_CLASSC (destination)) 
        !           660:     {
        !           661:       p->prefixlen=24;
        !           662:       apply_mask_ipv4(p);
        !           663:     }
        !           664:   else if (IN_CLASSB(destination)) 
        !           665:     {
        !           666:       p->prefixlen=16;
        !           667:       apply_mask_ipv4(p);
        !           668:     }
        !           669:   else 
        !           670:     {
        !           671:       p->prefixlen=8;
        !           672:       apply_mask_ipv4(p);
        !           673:     }
        !           674: }
        !           675: 
        !           676: in_addr_t
        !           677: ipv4_network_addr (in_addr_t hostaddr, int masklen)
        !           678: {
        !           679:   struct in_addr mask;
        !           680: 
        !           681:   masklen2ip (masklen, &mask);
        !           682:   return hostaddr & mask.s_addr;
        !           683: }
        !           684: 
        !           685: in_addr_t
        !           686: ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
        !           687: {
        !           688:   struct in_addr mask;
        !           689: 
        !           690:   masklen2ip (masklen, &mask);
        !           691:   return (masklen != IPV4_MAX_PREFIXLEN-1) ?
        !           692:         /* normal case */
        !           693:          (hostaddr | ~mask.s_addr) :
        !           694:         /* special case for /31 */
        !           695:          (hostaddr ^ ~mask.s_addr);
        !           696: }
        !           697: 
        !           698: /* Utility function to convert ipv4 netmask to prefixes 
        !           699:    ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
        !           700:    ex.) "1.0.0.0" NULL => "1.0.0.0/8"                   */
        !           701: int
        !           702: netmask_str2prefix_str (const char *net_str, const char *mask_str,
        !           703:                        char *prefix_str)
        !           704: {
        !           705:   struct in_addr network;
        !           706:   struct in_addr mask;
        !           707:   u_char prefixlen;
        !           708:   u_int32_t destination;
        !           709:   int ret;
        !           710: 
        !           711:   ret = inet_aton (net_str, &network);
        !           712:   if (! ret)
        !           713:     return 0;
        !           714: 
        !           715:   if (mask_str)
        !           716:     {
        !           717:       ret = inet_aton (mask_str, &mask);
        !           718:       if (! ret)
        !           719:         return 0;
        !           720: 
        !           721:       prefixlen = ip_masklen (mask);
        !           722:     }
        !           723:   else 
        !           724:     {
        !           725:       destination = ntohl (network.s_addr);
        !           726: 
        !           727:       if (network.s_addr == 0)
        !           728:        prefixlen = 0;
        !           729:       else if (IN_CLASSC (destination))
        !           730:        prefixlen = 24;
        !           731:       else if (IN_CLASSB (destination))
        !           732:        prefixlen = 16;
        !           733:       else if (IN_CLASSA (destination))
        !           734:        prefixlen = 8;
        !           735:       else
        !           736:        return 0;
        !           737:     }
        !           738: 
        !           739:   sprintf (prefix_str, "%s/%d", net_str, prefixlen);
        !           740: 
        !           741:   return 1;
        !           742: }
        !           743: 
        !           744: #ifdef HAVE_IPV6
        !           745: /* Utility function for making IPv6 address string. */
        !           746: const char *
        !           747: inet6_ntoa (struct in6_addr addr)
        !           748: {
        !           749:   static char buf[INET6_ADDRSTRLEN];
        !           750: 
        !           751:   inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
        !           752:   return buf;
        !           753: }
        !           754: #endif /* HAVE_IPV6 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>