Annotation of embedaddon/quagga/lib/prefix.c, revision 1.1.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>