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>