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. */ 32static 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#ifdef FOX_SUPPORT 43/* Address Famiy Identifier to Address Family converter. */ 44int 45afi2family (int afi) 46{ 47 if (afi == AFI_IP) 48 return AF_INET; 49#ifdef HAVE_IPV6 50 else if (afi == AFI_IP6) 51 return AF_INET6; 52#endif /* HAVE_IPV6 */ 53 return 0; 54} 55 56int 57family2afi (int family) 58{ 59 if (family == AF_INET) 60 return AFI_IP; 61#ifdef HAVE_IPV6 62 else if (family == AF_INET6) 63 return AFI_IP6; 64#endif /* HAVE_IPV6 */ 65 return 0; 66} 67#endif /* FOX_SUPPORT */ 68 69/* If n includes p prefix then return 1 else return 0. */ 70int 71prefix_match (struct prefix *n, struct prefix *p) 72{ 73 int offset; 74 int shift; 75 76 /* Set both prefix's head pointer. */ 77 u_char *np = (u_char *)&n->u.prefix; 78 u_char *pp = (u_char *)&p->u.prefix; 79 80 /* If n's prefix is longer than p's one return 0. */ 81 if (n->prefixlen > p->prefixlen) 82 return 0; 83 84 offset = n->prefixlen / PNBBY; 85 shift = n->prefixlen % PNBBY; 86 87 if (shift) 88 if (maskbit[shift] & (np[offset] ^ pp[offset])) 89 return 0; 90 91 while (offset--) 92 if (np[offset] != pp[offset]) 93 return 0; 94 return 1; 95} 96 97/* Copy prefix from src to dest. */ 98void 99prefix_copy (struct prefix *dest, struct prefix *src) 100{ 101 dest->family = src->family; 102 dest->prefixlen = src->prefixlen; 103 104 if (src->family == AF_INET) 105 dest->u.prefix4 = src->u.prefix4; 106#ifdef HAVE_IPV6 107 else if (src->family == AF_INET6) 108 dest->u.prefix6 = src->u.prefix6; 109#endif /* HAVE_IPV6 */ 110 else if (src->family == AF_UNSPEC) 111 { 112 dest->u.lp.id = src->u.lp.id; 113 dest->u.lp.adv_router = src->u.lp.adv_router; 114 } 115 else 116 { 117#ifdef FOX_RIP_DEBUG 118 zlog (NULL, LOG_INFO, "prefix_copy(): Unknown address family %d", 119 src->family); 120#endif /* FOX_RIP_DEBUG */ 121 assert (0); 122 } 123} 124 125/* If both prefix structure is same then return 1 else return 0. */ 126int 127prefix_same (struct prefix *p1, struct prefix *p2) 128{ 129 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) 130 { 131 if (p1->family == AF_INET) 132 if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) 133 return 1; 134#ifdef HAVE_IPV6 135 if (p1->family == AF_INET6 ) 136 if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix)) 137 return 1; 138#endif /* HAVE_IPV6 */ 139 } 140 return 0; 141} 142#ifdef FOX_SUPPORT 143/* When both prefix structure is not same, but will be same after 144 applying mask, return 0. otherwise, return 1 */ 145int 146prefix_cmp (struct prefix *p1, struct prefix *p2) 147{ 148 int offset; 149 int shift; 150 151 /* Set both prefix's head pointer. */ 152 u_char *pp1 = (u_char *)&p1->u.prefix; 153 u_char *pp2 = (u_char *)&p2->u.prefix; 154 155 if (p1->family != p2->family || p1->prefixlen != p2->prefixlen) 156 return 1; 157 158 offset = p1->prefixlen / 8; 159 shift = p1->prefixlen % 8; 160 161 if (shift) 162 if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) 163 return 1; 164 165 while (offset--) 166 if (pp1[offset] != pp2[offset]) 167 return 1; 168 169 return 0; 170} 171#endif 172 173#if defined(FOX_CMD_SUPPORT) || defined(FOX_RIP_DEBUG) 174/* Return prefix family type string. */ 175char * 176prefix_family_str (struct prefix *p) 177{ 178 if (p->family == AF_INET) 179 return "inet"; 180#ifdef HAVE_IPV6 181 if (p->family == AF_INET6) 182 return "inet6"; 183#endif /* HAVE_IPV6 */ 184 return "unspec"; 185} 186#endif /* FOX_SUPPORT */ 187 188/* Allocate new prefix_ipv4 structure. */ 189struct prefix_ipv4 * 190prefix_ipv4_new () 191{ 192 struct prefix_ipv4 *p; 193 194 p = XCALLOC (MTYPE_PREFIX_IPV4, sizeof *p); 195 p->family = AF_INET; 196 return p; 197} 198 199/* Free prefix_ipv4 structure. */ 200void 201prefix_ipv4_free (struct prefix_ipv4 *p) 202{ 203 XFREE (MTYPE_PREFIX_IPV4, p); 204} 205 206/* When string format is invalid return 0. */ 207int 208str2prefix_ipv4 (char *str, struct prefix_ipv4 *p) 209{ 210 int ret; 211 int plen; 212 char *pnt; 213 char *cp; 214 215 /* Find slash inside string. */ 216 pnt = strchr (str, '/'); 217 218 /* String doesn't contail slash. */ 219 if (pnt == NULL) 220 { 221 /* Convert string to prefix. */ 222 ret = inet_aton (str, &p->prefix); 223 if (ret == 0) 224 return 0; 225 226 /* If address doesn't contain slash we assume it host address. */ 227 p->family = AF_INET; 228 p->prefixlen = IPV4_MAX_BITLEN; 229 230 return ret; 231 } 232 else 233 { 234 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); 235 strncpy (cp, str, pnt - str); 236 *(cp + (pnt - str)) = '\0'; 237 ret = inet_aton (cp, &p->prefix); 238 XFREE (MTYPE_TMP, cp); 239 240 /* Get prefix length. */ 241 plen = (u_char) atoi (++pnt); 242 if (plen > 32) 243 return 0; 244 245 p->family = AF_INET; 246 p->prefixlen = plen; 247 } 248 249 return ret; 250} 251 252/* Convert masklen into IP address's netmask. */ 253void 254masklen2ip (int masklen, struct in_addr *netmask) 255{ 256 u_char *pnt; 257 int bit; 258 int offset; 259 260 memset (netmask, 0, sizeof (struct in_addr)); 261 pnt = (unsigned char *) netmask; 262 263 offset = masklen / 8; 264 bit = masklen % 8; 265 266 while (offset--) 267 *pnt++ = 0xff; 268 269 if (bit) 270 *pnt = maskbit[bit]; 271} 272 273/* Convert IP address's netmask into integer. We assume netmask is 274 sequential one. Argument netmask should be network byte order. */ 275u_char 276ip_masklen (struct in_addr netmask) 277{ 278 u_char len; 279 u_char *pnt; 280 u_char *end; 281 u_char val; 282 283 len = 0; 284 pnt = (u_char *) &netmask; 285 end = pnt + 4; 286 287 while ((*pnt == 0xff) && pnt < end) 288 { 289 len+= 8; 290 pnt++; 291 } 292 293 if (pnt < end) 294 { 295 val = *pnt; 296 while (val) 297 { 298 len++; 299 val <<= 1; 300 } 301 } 302 return len; 303} 304 305/* Apply mask to IPv4 prefix. */ 306void 307apply_mask_ipv4 (struct prefix_ipv4 *p) 308{ 309 u_char *pnt; 310 int index; 311 int offset; 312 313 index = p->prefixlen / 8; 314 315 if (index < 4) 316 { 317 pnt = (u_char *) &p->prefix; 318 offset = p->prefixlen % 8; 319 320 pnt[index] &= maskbit[offset]; 321 index++; 322 323 while (index < 4) 324 pnt[index++] = 0; 325 } 326} 327 328/* If prefix is 0.0.0.0/0 then return 1 else return 0. */ 329int 330prefix_ipv4_any (struct prefix_ipv4 *p) 331{ 332 return (p->prefix.s_addr == 0 && p->prefixlen == 0); 333} 334 335#ifdef HAVE_IPV6 336 337/* Allocate a new ip version 6 route */ 338struct prefix_ipv6 * 339prefix_ipv6_new () 340{ 341 struct prefix_ipv6 *p; 342 343 p = XCALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6)); 344 p->family = AF_INET6; 345 return p; 346} 347 348/* Free prefix for IPv6. */ 349void 350prefix_ipv6_free (struct prefix_ipv6 *p) 351{ 352 XFREE (MTYPE_PREFIX_IPV6, p); 353} 354 355/* If given string is valid return pin6 else return NULL */ 356int 357str2prefix_ipv6 (char *str, struct prefix_ipv6 *p) 358{ 359 char *pnt; 360 char *cp; 361 int ret; 362 363 pnt = strchr (str, '/'); 364 365 /* If string doesn't contain `/' treat it as host route. */ 366 if (pnt == NULL) 367 { 368 ret = inet_pton (AF_INET6, str, &p->prefix); 369 if (ret != 1) 370 return 0; 371 p->prefixlen = IPV6_MAX_BITLEN; 372 } 373 else 374 { 375 int plen; 376 377 cp = XMALLOC (0, (pnt - str) + 1); 378 strncpy (cp, str, pnt - str); 379 *(cp + (pnt - str)) = '\0'; 380 ret = inet_pton (AF_INET6, cp, &p->prefix); 381 free (cp); 382 if (ret != 1) 383 return 0; 384 plen = (u_char) atoi (++pnt); 385 if (plen > 128) 386 return 0; 387 p->prefixlen = plen; 388 } 389 p->family = AF_INET6; 390 391 return ret; 392} 393 394/* Convert struct in6_addr netmask into integer. */ 395int 396ip6_masklen (struct in6_addr netmask) 397{ 398 int len = 0; 399 unsigned char val; 400 unsigned char *pnt; 401 402 pnt = (unsigned char *) & netmask; 403 404 while ((*pnt == 0xff) && len < 128) 405 { 406 len += 8; 407 pnt++; 408 } 409 410 if (len < 128) 411 { 412 val = *pnt; 413 while (val) 414 { 415 len++; 416 val <<= 1; 417 } 418 } 419 return len; 420} 421 422void 423masklen2ip6 (int masklen, struct in6_addr *netmask) 424{ 425 unsigned char *pnt; 426 int bit; 427 int offset; 428 429 memset (netmask, 0, sizeof (struct in6_addr)); 430 pnt = (unsigned char *) netmask; 431 432 offset = masklen / 8; 433 bit = masklen % 8; 434 435 while (offset--) 436 *pnt++ = 0xff; 437 438 if (bit) 439 *pnt = maskbit[bit]; 440} 441 442void 443apply_mask_ipv6 (struct prefix_ipv6 *p) 444{ 445 u_char *pnt; 446 int index; 447 int offset; 448 449 index = p->prefixlen / 8; 450 451 if (index < 16) 452 { 453 pnt = (u_char *) &p->prefix; 454 offset = p->prefixlen % 8; 455 456 pnt[index] &= maskbit[offset]; 457 index++; 458 459 while (index < 16) 460 pnt[index++] = 0; 461 } 462} 463 464void 465str2in6_addr (char *str, struct in6_addr *addr) 466{ 467 int i; 468 unsigned int x; 469 470 /* %x must point to unsinged int */ 471 for (i = 0; i < 16; i++) 472 { 473 sscanf (str + (i * 2), "%02x", &x); 474 addr->s6_addr[i] = x & 0xff; 475 } 476} 477#endif /* HAVE_IPV6 */ 478 479void 480apply_mask (struct prefix *p) 481{ 482 switch (p->family) 483 { 484 case AF_INET: 485 apply_mask_ipv4 ((struct prefix_ipv4 *)p); 486 break; 487#ifdef HAVE_IPV6 488 case AF_INET6: 489 apply_mask_ipv6 ((struct prefix_ipv6 *)p); 490 break; 491#endif /* HAVE_IPV6 */ 492 default: 493 break; 494 } 495 return; 496} 497 498#ifdef FOX_SUPPORT 499 500/* Utility function of convert between struct prefix <=> union sockunion */ 501struct prefix * 502sockunion2prefix (union sockunion *dest, 503 union sockunion *mask) 504{ 505 if (dest->sa.sa_family == AF_INET) 506 { 507 struct prefix_ipv4 *p; 508 509 p = prefix_ipv4_new (); 510 p->family = AF_INET; 511 p->prefix = dest->sin.sin_addr; 512 p->prefixlen = ip_masklen (mask->sin.sin_addr); 513 return (struct prefix *) p; 514 } 515#ifdef HAVE_IPV6 516 if (dest->sa.sa_family == AF_INET6) 517 { 518 struct prefix_ipv6 *p; 519 520 p = prefix_ipv6_new (); 521 p->family = AF_INET6; 522 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr); 523 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); 524 return (struct prefix *) p; 525 } 526#endif /* HAVE_IPV6 */ 527 return NULL; 528} 529 530/* Utility function of convert between struct prefix <=> union sockunion */ 531struct prefix * 532sockunion2hostprefix (union sockunion *su) 533{ 534 if (su->sa.sa_family == AF_INET) 535 { 536 struct prefix_ipv4 *p; 537 538 p = prefix_ipv4_new (); 539 p->family = AF_INET; 540 p->prefix = su->sin.sin_addr; 541 p->prefixlen = IPV4_MAX_BITLEN; 542 return (struct prefix *) p; 543 } 544#ifdef HAVE_IPV6 545 if (su->sa.sa_family == AF_INET6) 546 { 547 struct prefix_ipv6 *p; 548 549 p = prefix_ipv6_new (); 550 p->family = AF_INET6; 551 p->prefixlen = IPV6_MAX_BITLEN; 552 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr)); 553 return (struct prefix *) p; 554 } 555#endif /* HAVE_IPV6 */ 556 return NULL; 557} 558#endif /* FOX_SUPPORT */ 559 560int 561prefix_blen (struct prefix *p) 562{ 563 switch (p->family) 564 { 565 case AF_INET: 566 return IPV4_MAX_BYTELEN; 567 break; 568#ifdef HAVE_IPV6 569 case AF_INET6: 570 return IPV6_MAX_BYTELEN; 571 break; 572#endif /* HAVE_IPV6 */ 573 } 574 return 0; 575} 576 577#ifdef FOX_SUPPORT 578/* Generic function for conversion string to struct prefix. */ 579int 580str2prefix (char *str, struct prefix *p) 581{ 582 int ret; 583 584 /* First we try to convert string to struct prefix_ipv4. */ 585 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p); 586 if (ret) 587 return ret; 588 589#ifdef HAVE_IPV6 590 /* Next we try to convert string to struct prefix_ipv6. */ 591 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p); 592 if (ret) 593 return ret; 594#endif /* HAVE_IPV6 */ 595 596 return 0; 597} 598 599int 600prefix2str (struct prefix *p, char *str, int size) 601{ 602 char buf[BUFSIZ]; 603 604 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); 605 snprintf (str, size, "%s/%d", buf, p->prefixlen); 606 return 0; 607} 608#endif /* FOX_SUPPORT */ 609 610struct prefix * 611prefix_new () 612{ 613 struct prefix *p; 614 615 p = XCALLOC (MTYPE_PREFIX, sizeof *p); 616 return p; 617} 618 619/* Free prefix structure. */ 620void 621prefix_free (struct prefix *p) 622{ 623 XFREE (MTYPE_PREFIX, p); 624} 625 626#ifdef FOX_SUPPORT 627/* Utility function. Check the string only contains digit 628 character. */ 629int 630all_digit (char *str) 631{ 632 for (; *str != '\0'; str++) 633 if (!isdigit ((int) *str)) 634 return 0; 635 return 1; 636} 637#endif /* FOX_SUPPORT */ 638 639/* Utility function to convert ipv4 prefixes to Classful prefixes */ 640void apply_classful_mask_ipv4 (struct prefix_ipv4 *p) 641{ 642 643 u_int32_t destination; 644 645 destination = ntohl (p->prefix.s_addr); 646 647 if (p->prefixlen == 32); 648 /* do nothing for host routes */ 649 else if (IN_CLASSC (destination)) 650 { 651 p->prefixlen=24; 652 apply_mask_ipv4(p); 653 } 654 else if (IN_CLASSB(destination)) 655 { 656 p->prefixlen=16; 657 apply_mask_ipv4(p); 658 } 659 else 660 { 661 p->prefixlen=8; 662 apply_mask_ipv4(p); 663 } 664} 665#ifdef FOX_SUPPORT 666/* Utility function to convert ipv4 netmask to prefixes 667 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" 668 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ 669int 670netmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str) 671{ 672 struct in_addr network; 673 struct in_addr mask; 674 u_char prefixlen; 675 u_int32_t destination; 676 int ret; 677 678 ret = inet_aton (net_str, &network); 679 if (! ret) 680 return 0; 681 682 if (mask_str) 683 { 684 ret = inet_aton (mask_str, &mask); 685 if (! ret) 686 return 0; 687 688 prefixlen = ip_masklen (mask); 689 } 690 else 691 { 692 destination = ntohl (network.s_addr); 693 694 if (network.s_addr == 0) 695 prefixlen = 0; 696 else if (IN_CLASSC (destination)) 697 prefixlen = 24; 698 else if (IN_CLASSB (destination)) 699 prefixlen = 16; 700 else if (IN_CLASSA (destination)) 701 prefixlen = 8; 702 else 703 return 0; 704 } 705 706 sprintf (prefix_str, "%s/%d", net_str, prefixlen); 707 708 return 1; 709} 710 711#endif /* FOX_SUPPORT */ 712