1 /* 2 ** Copyright (C) 2001-2020 by Carnegie Mellon University. 3 ** 4 ** @OPENSOURCE_LICENSE_START@ 5 ** See license information in ../../LICENSE.txt 6 ** @OPENSOURCE_LICENSE_END@ 7 */ 8 9 /* 10 ** skipaddr.h 11 ** 12 ** Macros and function declarations for handling IP addresses 13 ** (skipaddr_t and skIPUnion_t). 14 ** 15 */ 16 #ifndef _SKIPADDR_H 17 #define _SKIPADDR_H 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 #include <silk/silk.h> 23 24 RCSIDENTVAR(rcsID_SKIPADDR_H, "$SiLK: skipaddr.h ef14e54179be 2020-04-14 21:57:45Z mthomas $"); 25 26 #include <silk/silk_types.h> 27 28 /* 29 ** For reference. Defined in silk_types.h 30 ** 31 ** typedef union skipunion_un { 32 ** uint32_t ipu_ipv4; 33 ** #if SK_ENABLE_IPV6 34 ** uint8_t ipu_ipv6[16]; 35 ** #endif 36 ** } skIPUnion_t; 37 ** 38 ** 39 ** typedef struct skipaddr_st { 40 ** skIPUnion_t ip_ip; 41 ** #if SK_ENABLE_IPV6 42 ** unsigned ip_is_v6 :1; 43 ** #endif 44 ** } skipaddr_t; 45 */ 46 47 48 /* 49 * is_zero = SK_IPV6_IS_ZERO(ipv6); 50 * 51 * Return true if the specified ipv6 address is zero, where ipv6 52 * was defined as: 53 * 54 * uint8_t ipv6[16]; 55 */ 56 #define SK_IPV6_IS_ZERO(v6_byte_array) \ 57 (0 == memcmp((v6_byte_array), sk_ipv6_zero, SK_IPV6_ZERO_LEN)) 58 #define SK_IPV6_ZERO_LEN 16 59 extern const uint8_t sk_ipv6_zero[SK_IPV6_ZERO_LEN]; 60 61 62 /* 63 * is_v4_in_v6 = SK_IPV6_IS_V4INV6(ipv6); 64 * 65 * Return true if the specified ipv6 address represents an 66 * IPv6-encoded-IPv4 address, where ipv6 was defined as: 67 * 68 * uint8_t ipv6[16]; 69 */ 70 #define SK_IPV6_IS_V4INV6(v6_byte_array) \ 71 (0 == memcmp((v6_byte_array), sk_ipv6_v4inv6, SK_IPV6_V4INV6_LEN)) 72 #define SK_IPV6_V4INV6_LEN 12 73 extern const uint8_t sk_ipv6_v4inv6[SK_IPV6_V4INV6_LEN]; 74 75 76 /* **** skIPUnion_t **** */ 77 78 /* Macros dealing with skIPUnion_t's are typically for use by other 79 * SiLK macros and functions. These macros are subject to change at 80 * any time. */ 81 82 /* Get and Set the V4 part of the address structure */ 83 #define skIPUnionGetV4(ipu) \ 84 ((ipu)->ipu_ipv4) 85 86 #define skIPUnionSetV4(ipu, in_vp) \ 87 memcpy(&((ipu)->ipu_ipv4), (in_vp), 4) 88 89 #define skIPUnionApplyMaskV4(ipu, v4_mask) \ 90 do { ((ipu)->ipu_ipv4) &= (v4_mask); } while(0) 91 92 /* Get the 'cidr' most significant bits of the V4 address */ 93 #define skIPUnionGetCIDRV4(ipu, cidr) \ 94 (((cidr) >= 32) \ 95 ? ((ipu)->ipu_ipv4) \ 96 : (((ipu)->ipu_ipv4) & ~(UINT32_MAX >> cidr))) 97 98 /* Set the V4 address to its 'cidr' most significant bits. Assumes 99 * the following: 0 <= 'cidr' < 32 */ 100 #define skIPUnionApplyCIDRV4(ipu, cidr) \ 101 do { (((ipu)->ipu_ipv4) &= ~(UINT32_MAX >> cidr)); } while(0) 102 103 #if SK_ENABLE_IPV6 104 105 /* Get and Set the V6 parts of the address structure */ 106 #define skIPUnionGetV6(ipu, out_vp) \ 107 memcpy((out_vp), (ipu)->ipu_ipv6, 16) 108 109 #define skIPUnionSetV6(ipu, in_vp) \ 110 memcpy((ipu)->ipu_ipv6, (in_vp), 16) 111 112 /* Convert a pointer to a native uint32_t to an IPv6 byte array */ 113 #define skIPUnionU32ToV6(src_u32, dst_v6) \ 114 do { \ 115 uint32_t ipu32tov6 = htonl(*(src_u32)); \ 116 memcpy((dst_v6), sk_ipv6_v4inv6, SK_IPV6_V4INV6_LEN); \ 117 memcpy(((uint8_t*)(dst_v6)+SK_IPV6_V4INV6_LEN), &ipu32tov6, 4); \ 118 } while(0) 119 120 /* Write the V4 address into a V6 location. The two parameters can 121 * point to the same skIPUnion_t. */ 122 #define skIPUnionGetV4AsV6(ipu, ipv6) \ 123 skIPUnionU32ToV6(&((ipu)->ipu_ipv4), ipv6) 124 125 /* Convert a V4 skIPUnion_t to an V6 skIPUnion_t. The two parameters 126 * can point to the same skIPUnion_t. */ 127 #define skIPUnion4to6(src_ipu, dst_ipu) \ 128 skIPUnionU32ToV6(&((src_ipu)->ipu_ipv4), (dst_ipu)->ipu_ipv6) 129 130 #define skIPUnionApplyMaskV6(ipu, v6_mask) \ 131 do { \ 132 int ipuam; \ 133 for (ipuam = 0; ipuam < 16; ++ipuam) { \ 134 (ipu)->ipu_ipv6[ipuam] &= ((int8_t*)(v6_mask))[ipuam]; \ 135 } \ 136 } while(0) 137 138 139 /* Get the 'cidr' most significant bits of the V6 address */ 140 #define skIPUnionGetCIDRV6(ipu, out_vp, cidr) \ 141 if ((cidr) >= 128) { \ 142 skIPUnionGetV6((ipu), (out_vp)); \ 143 } else { \ 144 int ipugc6 = (cidr) >> 3; \ 145 memcpy((out_vp), (ipu)->ipu_ipv6, ipugc6); \ 146 ((uint8_t*)(out_vp))[ipugc6] = ((ipu)->ipu_ipv6[ipugc6] \ 147 & ~(0xFF >> (0x7 & (cidr)))); \ 148 memset(&((uint8_t*)(out_vp))[ipugc6+1], 0, 15 - ipugc6); \ 149 } 150 151 /* Set the V6 address to its 'cidr' most significant bits. assumes 152 * the following: 0 <= cidr < 128 */ 153 #define skIPUnionApplyCIDRV6(ipu, cidr) \ 154 do { \ 155 int ipugc6 = (cidr) >> 3; \ 156 (ipu)->ipu_ipv6[ipugc6] &= ~(0xFF >> (0x7 & (cidr))); \ 157 memset(&(ipu)->ipu_ipv6[ipugc6+1], 0, 15 - ipugc6); \ 158 } while(0) 159 #endif /* #if SK_ENABLE_IPV6 */ 160 161 162 /* **** skipaddr_t **** */ 163 164 /** 165 * is_v6 = skipaddrIsV6(ipaddr). 166 * 167 * Return 1 if the skipaddr_t 'ipaddr' is an IPv6 address. Return 168 * 0 otherwise. 169 */ 170 #if 0 171 int 172 skipaddrIsV6( 173 const skipaddr_t *ipaddr); 174 #endif /* 0 */ 175 #if !SK_ENABLE_IPV6 176 # define skipaddrIsV6(addr) 0 177 #else 178 # define skipaddrIsV6(addr) ((addr)->ip_is_v6) 179 #endif /* #else of #if !SK_ENABLE_IPV6 */ 180 181 182 /** 183 * skipaddrSetVersion(addr, is_v6); 184 * 185 * If 'is_v6' is non-zero, specify that the skipaddr_t 'addr' 186 * contains an IPv6 address. This does not modify the 187 * representation of the IP address. See also skipaddrV4toV6(). 188 */ 189 #if 0 190 void 191 skipaddrSetVersion( 192 skipaddr_t *ipaddr, 193 int is_v6); 194 #endif /* 0 */ 195 #if !SK_ENABLE_IPV6 196 # define skipaddrSetVersion(addr, is_v6) 197 #else 198 # define skipaddrSetVersion(addr, is_v6) \ 199 do { (addr)->ip_is_v6 = !!(is_v6); } while(0) 200 #endif /* #else of #if !SK_ENABLE_IPV6 */ 201 202 203 /** 204 * skipaddrCopy(dst, src); 205 * 206 * Copy the skipaddr_t pointed at by 'src' to the location of the 207 * skipaddr_t pointed at by 'dst'. 208 */ 209 #if 0 210 void 211 skipaddrCopy( 212 skipaddr_t *dst, 213 const skipaddr_t *src); 214 #endif /* 0 */ 215 #if !SK_ENABLE_IPV6 216 # define skipaddrCopy(dst, src) \ 217 do { \ 218 skIPUnionGetV4(&(dst)->ip_ip) = skIPUnionGetV4(&(src)->ip_ip); \ 219 } while(0) 220 #else 221 # define skipaddrCopy(dst, src) memcpy((dst), (src), sizeof(skipaddr_t)) 222 #endif /* #else of #if !SK_ENABLE_IPV6 */ 223 224 225 /** 226 * skipaddrClear(addr); 227 * 228 * Set all bits in the skipaddr_t pointed at by 'addr' to 0. This 229 * causes 'addr' to represent the IPv4 address 0.0.0.0. 230 */ 231 #if 0 232 void 233 skipaddrClear( 234 skipaddr_t *ipaddr); 235 #endif /* 0 */ 236 #if !SK_ENABLE_IPV6 237 # define skipaddrClear(addr) \ 238 do { skIPUnionGetV4(&(addr)->ip_ip) = 0; } while(0) 239 #else 240 # define skipaddrClear(addr) memset((addr), 0, sizeof(skipaddr_t)) 241 #endif /* #else of #if !SK_ENABLE_IPV6 */ 242 243 244 /** 245 * ipv4 = skipaddrGetV4(addr); 246 * 247 * Treat the skipaddr_t 'addr' as containing an IPv4 address and 248 * return that value in native (host) byte order. To properly 249 * handle the cases where 'addr' contains an IPv6 address, use 250 * skipaddrGetAsV4(). 251 */ 252 #if 0 253 uint32_t 254 skipaddrGetV4( 255 const skipaddr_t *addr); 256 #endif /* 0 */ 257 #define skipaddrGetV4(addr) (skIPUnionGetV4(&((addr)->ip_ip))) 258 259 260 /** 261 * is_v4_mapped_v6 = skipaddrIsV4MappedV6(addr); 262 * 263 * Return true if 'addr' is an IPv6 address and is in the 264 * ::ffff:0:0/96 netblock. That is, whether 'addr' is an 265 * IPv4-mapped IPv6 address. 266 * 267 * Return false if 'addr' is an IPv4 address. 268 * 269 * If the IPv4 address is wanted, use skipaddrGetAsV4() which 270 * extracts the IPv4 address and returns 0 if successful or returns 271 * -1 if the address is not IPv4 nor an IPv4-mapped IPv6 address. 272 * 273 * Since SiLK 3.17.0. 274 */ 275 #if 0 276 int 277 skipaddrIsV4MappedV6( 278 const skipaddr_t *ipaddr); 279 #endif /* 0 */ 280 #if !SK_ENABLE_IPV6 281 # define skipaddrIsV4MappedV6(addr) 0 282 #else 283 # define skipaddrIsV4MappedV6(addr) \ 284 ((addr)->ip_is_v6 && SK_IPV6_IS_V4INV6((addr)->ip_ip.ipu_ipv6)) 285 #endif /* #else of #if !SK_ENABLE_IPV6 */ 286 287 288 /** 289 * ok = skipaddrGetAsV4(addr, &ipv4); 290 * 291 * If the skipaddr_t 'addr' contains an IPv4 address or an 292 * IPv4-mapped IPv6 address (i.e., an address in the ::ffff:0:0/96 293 * netblock), set the value pointed at by the uint32_t 'ipv4' to 294 * the IPv4 address (in native (host) byte order) and return 0. 295 * Otherwise leave the value pointed at by 'ipv4' unchanged and 296 * return -1. 297 * 298 * If 'addr' is known to be IPv4, consider using skipaddrGetV4(). 299 * 300 * If 'addr' is known to be IPv6 and the IPv4-mapped address is not 301 * needed, you may check whether this function would return 0 by 302 * using skipaddrIsV4MappedV6(). 303 */ 304 #if !SK_ENABLE_IPV6 305 /* use comma expression so expression evaluates to 0 */ 306 # define skipaddrGetAsV4(addr, ipv4_ptr) \ 307 ((*(ipv4_ptr) = skipaddrGetV4(addr)), 0) 308 #else 309 int 310 skipaddrGetAsV4( 311 const skipaddr_t *addr, 312 uint32_t *ipv4); 313 #endif /* #else of #if !SK_ENABLE_IPV6 */ 314 315 316 /** 317 * skipaddrSetV4(addr, src); 318 * 319 * Copy the uint32_t refereneced by 'src' into the skipaddr_t 320 * 'addr' and set the 'addr' as containing an IPv4 address. 'src' 321 * should be in native (host) byte order. 322 */ 323 #if 0 324 void 325 skipaddrSetV4( 326 skipaddr_t *addr, 327 uint32_t src); 328 #endif /* 0 */ 329 #if !SK_ENABLE_IPV6 330 # define skipaddrSetV4(addr, in_vp) \ 331 skIPUnionSetV4(&((addr)->ip_ip), in_vp) 332 #else 333 #define skipaddrSetV4(addr, in_vp) \ 334 do { \ 335 skipaddrClear(addr); \ 336 skIPUnionSetV4(&((addr)->ip_ip), (in_vp)); \ 337 } while(0) 338 #endif /* #else of #if !SK_ENABLE_IPV6 */ 339 340 341 #if SK_ENABLE_IPV6 342 343 /** 344 * skipaddrGetV6(addr, dst); 345 * 346 * Treat 'addr' as containing an IPv6 address and copy that value 347 * into the uint8_t[16] refereneced by 'dst'. To properly handle 348 * the cases where 'addr' contains an IPv4 address, use 349 * skipaddrGetAsV6(). 350 */ 351 #if 0 352 void 353 skipaddrGetV6( 354 const skipaddr_t *addr, 355 uint8_t dst[16]); 356 #endif /* 0 */ 357 #define skipaddrGetV6(addr, out_vp) \ 358 skIPUnionGetV6(&((addr)->ip_ip), (out_vp)) 359 360 361 /** 362 * skipaddrGetAsV6(addr, dst); 363 * 364 * Copy an IPv6 representation of the skipaddr_t 'addr' to the 365 * uint8_t[16] referenced by 'dst'. If 'addr' contains an IPv4 366 * address, the result contains an IPv4-mapped IPv6 address (that 367 * is, an IPv6 address in the ::ffff:0:0/96 netblock). 368 * 369 * If 'addr' is known to be IPv6, consider using skipaddrGetV6(). 370 */ 371 #if 0 372 void 373 skipaddrGetAsV6( 374 const skipaddr_t *addr, 375 uint8_t dst[16]); 376 #endif /* 0 */ 377 #define skipaddrGetAsV6(addr, out_vp) \ 378 if (skipaddrIsV6(addr)) { \ 379 skIPUnionGetV6(&((addr)->ip_ip), (out_vp)); \ 380 } else { \ 381 skIPUnionGetV4AsV6(&((addr)->ip_ip), (out_vp)); \ 382 } 383 384 385 /** 386 * skipaddrSetV6(addr, src); 387 * 388 * Copy the uint8_t[16] refereneced by 'src' into the skipaddr_t 389 * 'addr' and set the 'addr' as containing an IPv6 address. 390 */ 391 #if 0 392 void 393 skipaddrSetV6( 394 skipaddr_t *addr, 395 uint8_t src[16]); 396 #endif /* 0 */ 397 #define skipaddrSetV6(addr, in_vp) \ 398 do { \ 399 skIPUnionSetV6(&((addr)->ip_ip), (in_vp)); \ 400 (addr)->ip_is_v6 = 1; \ 401 } while(0) 402 403 404 /** 405 * skipaddrSetV6FromUint32(addr, src); 406 * 407 * Treat the uint32_t refereneced by 'src' as an IPv4 address in 408 * native (host) byte order, convert it to an IPv6 address, and 409 * store the result in skipaddr_t 'addr'. 410 */ 411 #if 0 412 void 413 skipaddrSetV6FromUint32( 414 skipaddr_t *addr, 415 const uint32_t *src); 416 #endif /* 0 */ 417 #define skipaddrSetV6FromUint32(addr, in_vp) \ 418 do { \ 419 uint8_t v6fromu32[16]; \ 420 skIPUnionU32ToV6((in_vp), v6fromu32); \ 421 skIPUnionSetV6(&((addr)->ip_ip), v6fromu32); \ 422 (addr)->ip_is_v6 = 1; \ 423 } while(0) 424 425 /** 426 * skipaddrV4toV6(srcaddr, dstaddr); 427 * 428 * Assume the skipaddr_t 'srcaddr' contains an IPv4 address, 429 * convert that address to an IPv4-mapped IPv6 address (that is, an 430 * address in the ::ffff:0:0/96 netblock), and store the result in 431 * the skipaddr_t 'dstaddr'. 'srcaddr' and 'dstaddr' may point to 432 * the same skipaddr_t. 433 */ 434 #if 0 435 void 436 skipaddrV4toV6( 437 const skipaddr_t *srcaddr, 438 skipaddr_t *dstaddr); 439 #endif /* 0 */ 440 #define skipaddrV4toV6(srcaddr, dstaddr) \ 441 do { \ 442 skIPUnion4to6(&((srcaddr)->ip_ip), &((dstaddr)->ip_ip)); \ 443 (dstaddr)->ip_is_v6 = 1; \ 444 } while(0) 445 446 447 /** 448 * ok = skipaddrV6toV4(srcaddr, dstaddr); 449 * 450 * Assume the skipaddr_t 'srcaddr' contains an IPv6 address. If 451 * that address is an IPv4-mapped IPv6 address (that is, an address 452 * in the ::ffff:0:0/96 netblock), convert the address to IPv4, 453 * store the result in the skipaddr_t 'dstaddr', and return 0. 454 * Otherwise, return -1 and leave 'dstaddr' unchanged. 'srcaddr' 455 * and 'dstaddr' may point to the same skipaddr_t. 456 */ 457 int 458 skipaddrV6toV4( 459 const skipaddr_t *srcaddr, 460 skipaddr_t *dstaddr); 461 #endif /* #if SK_ENABLE_IPV6 */ 462 463 464 /** 465 * cmp = skipaddrCompare(addr1, addr2); 466 * 467 * Compare the value of the skipaddr_t objects 'addr1' and 'addr2'. 468 * 469 * Return 0 if 'addr1' is equal to 'addr2'; return a value less 470 * than 0 if 'addr1' is less than 'addr2'; return a value greater 471 * than 0 if 'addr1' is greater than 'addr2'. 472 * 473 * When IPv6 is enabled and either address is IPv6, the comparison 474 * is done as if both addresses were IPv6 by mapping an IPv4 475 * address to the ::ffff:0:0/96 netblock. 476 */ 477 #if !SK_ENABLE_IPV6 478 # define skipaddrCompare(addr1, addr2) \ 479 (((addr1)->ip_ip.ipu_ipv4 < (addr2)->ip_ip.ipu_ipv4) \ 480 ? -1 \ 481 : (((addr1)->ip_ip.ipu_ipv4 > (addr2)->ip_ip.ipu_ipv4) \ 482 ? 1 \ 483 : 0)) 484 #else 485 int 486 skipaddrCompare( 487 const skipaddr_t *addr1, 488 const skipaddr_t *addr2); 489 #endif /* #else of #if !SK_ENABLE_IPV6 */ 490 491 492 /** 493 * skipaddrMask(ipaddr, mask_ip); 494 * 495 * Apply the bit-mask in the skipaddr_t 'mask_ip' to the skipaddr_t 496 * 'ipaddr'. 497 * 498 * When both addresses are either IPv4 or IPv6, applying the mask 499 * is straightforward. 500 * 501 * When 'ipaddr' is IPv6 and 'mask_ip' is IPv4, the function 502 * converts 'mask_ip' to an IPv4-mapped IPv6 (i.e., an address in 503 * the ::ffff:0:0/96 netblock) and then applies the mask. The 504 * result is an IPv6 address. 505 * 506 * When 'ipaddr' is IPv4 and 'mask_ip' is IPv6, the function 507 * converts 'ipaddr' to an IPv4-mapped IPv6 address and performs 508 * the mask. If the result is still an IPv4-mapped IPv6 address, 509 * the function converts the result back to IPv4; otherwise the 510 * result remains an IPv6 address. 511 */ 512 #if !SK_ENABLE_IPV6 513 # define skipaddrMask(ipaddr, mask_ip) \ 514 do { \ 515 (ipaddr)->ip_ip.ipu_ipv4 &= (mask_ip)->ip_ip.ipu_ipv4; \ 516 } while(0) 517 #else 518 void 519 skipaddrMask( 520 skipaddr_t *ipaddr, 521 const skipaddr_t *mask_ip); 522 #endif /* #else of #if !SK_ENABLE_IPV6 */ 523 524 525 /** 526 * skipaddrApplyCIDR(ipaddr, cidr_prefix); 527 * 528 * Apply the numeric CIDR prefix 'cidr_prefix' to the skipaddr_t 529 * 'ipaddr', zeroing all but the most significant 'cidr_prefix' 530 * bits. 531 * 532 * If a CIDR prefix too large for the address is given, it will be 533 * ignored. 534 */ 535 #if 0 536 void 537 skipaddrApplyCIDR( 538 skipaddr_t *ipaddr, 539 uint32_t cidr_prefix); 540 #endif /* 0 */ 541 #if !SK_ENABLE_IPV6 542 # define skipaddrApplyCIDR(ipaddr, cidr) \ 543 if ((cidr) >= 32) { /* no-op */ } else { \ 544 skIPUnionApplyCIDRV4(&(ipaddr)->ip_ip, cidr); \ 545 } 546 #else 547 # define skipaddrApplyCIDR(ipaddr, cidr) \ 548 if (skipaddrIsV6(ipaddr)) { \ 549 if ((cidr) < 128) { \ 550 skIPUnionApplyCIDRV6(&((ipaddr)->ip_ip), cidr); \ 551 } \ 552 } else { \ 553 if ((cidr) < 32) { \ 554 skIPUnionApplyCIDRV4(&((ipaddr)->ip_ip), cidr); \ 555 } \ 556 } 557 #endif /* #else of #if !SK_ENABLE_IPV6 */ 558 559 560 /** 561 * skipaddrIncrement(ipaddr); 562 * 563 * Add one to the integer representation of the IP address in the 564 * skipaddr_t 'ipaddr'. If overflow occurs, wrap the value back to 565 * 0. 566 */ 567 #if 0 568 void 569 skipaddrIncrement( 570 skipaddr_t *ipaddr); 571 #endif /* 0 */ 572 #if !SK_ENABLE_IPV6 573 #define skipaddrIncrement(addr) \ 574 ((void)(++(addr)->ip_ip.ipu_ipv4)) 575 #else 576 #define skipaddrIncrement(addr) \ 577 if (!skipaddrIsV6(addr)) { \ 578 ++(addr)->ip_ip.ipu_ipv4; \ 579 } else { \ 580 int incr_idx; \ 581 for (incr_idx = 15; incr_idx >= 0; --incr_idx) { \ 582 if (UINT8_MAX != (addr)->ip_ip.ipu_ipv6[incr_idx]) { \ 583 ++(addr)->ip_ip.ipu_ipv6[incr_idx]; \ 584 break; \ 585 } \ 586 (addr)->ip_ip.ipu_ipv6[incr_idx] = 0; \ 587 } \ 588 } 589 #endif /* #else of #if !SK_ENABLE_IPV6 */ 590 591 592 /** 593 * skipaddrDecrement(ipaddr); 594 * 595 * Subtract one from the integer representation of the IP address 596 * in the skipaddr_t 'ipaddr'. If underflow occurs, wrap the value 597 * back to the maximum. 598 */ 599 #if 0 600 void 601 skipaddrDecrement( 602 skipaddr_t *ipaddr); 603 #endif /* 0 */ 604 #if !SK_ENABLE_IPV6 605 #define skipaddrDecrement(addr) \ 606 ((void)(--(addr)->ip_ip.ipu_ipv4)) 607 #else 608 #define skipaddrDecrement(addr) \ 609 if (!skipaddrIsV6(addr)) { \ 610 --(addr)->ip_ip.ipu_ipv4; \ 611 } else { \ 612 int decr_idx; \ 613 for (decr_idx = 15; decr_idx >= 0; --decr_idx) { \ 614 if (0 != (addr)->ip_ip.ipu_ipv6[decr_idx]) { \ 615 --(addr)->ip_ip.ipu_ipv6[decr_idx]; \ 616 break; \ 617 } \ 618 (addr)->ip_ip.ipu_ipv6[decr_idx] = UINT8_MAX; \ 619 } \ 620 } 621 #endif /* #else of #if !SK_ENABLE_IPV6 */ 622 623 624 /** 625 * is_zero = skipaddrIsZero(ipaddr); 626 * 627 * Return 1 if the IP address in the skipaddr_t 'ipaddr' contains 628 * no high bits. Return 0 otherwise. 629 * 630 * skipaddrIsZero(skipaddrClear(ipaddr)) returns 1. 631 */ 632 #if 0 633 int 634 skipaddrIsZero( 635 const skipaddr_t *ipaddr); 636 #endif /* 0 */ 637 #if !SK_ENABLE_IPV6 638 # define skipaddrIsZero(addr) (0 == (addr)->ip_ip.ipu_ipv4) 639 #else 640 # define skipaddrIsZero(addr) \ 641 (skipaddrIsV6(addr) \ 642 ? SK_IPV6_IS_ZERO((addr)->ip_ip.ipu_ipv6) \ 643 : (0 == (addr)->ip_ip.ipu_ipv4)) 644 #endif /* #else of #if !SK_ENABLE_IPV6 */ 645 646 647 /* **** skcidr_t **** */ 648 649 /** 650 * skcidr_t represents a CIDR block or net-block. The structure 651 * holds an IP address and the number of subnet bits. 652 */ 653 typedef union skcidr_un { 654 struct cidr_un_v4 { 655 /* whether this value contains an IPv6 mask */ 656 uint8_t is_ipv6; 657 /* length of the subnet (in bits). */ 658 uint8_t cidr_length; 659 /* placeholders for alignment */ 660 uint8_t unused2; 661 uint8_t unused3; 662 /* the base IP of the CIDR block */ 663 uint32_t ip; 664 /* pre-computed mask where the upper length bits are high */ 665 uint32_t mask; 666 } v4; 667 #if SK_ENABLE_IPV6 668 struct cidr_un_v6 { 669 /* whether this value contains an IPv6 mask */ 670 uint8_t is_ipv6; 671 /* length of the subnet (in bits). */ 672 uint8_t cidr_length; 673 /* number of bytes to memcmp() when comparing IP to CIDR */ 674 uint8_t byte_length; 675 /* pre-computed mask to use when comparing the 676 * "ip[byte_length-1]" byte */ 677 uint8_t mask; 678 /* the base IP of the CIDR block */ 679 uint8_t ip[16]; 680 } v6; 681 #endif /* #if SK_ENABLE_IPV6 */ 682 } skcidr_t; 683 684 685 /** 686 * in_cidr = skcidrCheckIP(cidr, ipaddr); 687 * 688 * Return a true value if 'ipaddr' is contained in the CIDR block 689 * represented by 'cidr'. Return false otherwise. 690 */ 691 #if !SK_ENABLE_IPV6 692 #define skcidrCheckIP(cidr, ipaddr) \ 693 ((skipaddrGetV4(ipaddr) & cidr->v4.mask) == (cidr)->v4.ip) 694 #else 695 int 696 skcidrCheckIP( 697 const skcidr_t *cidr, 698 const skipaddr_t *ipaddr); 699 #endif /* #else of #if !SK_ENABLE_IPV6 */ 700 701 702 /** 703 * skcidrClear(cidr); 704 * 705 * Set all bits in the skcidr_t pointed at by 'cidr' to 0. 706 */ 707 #if 0 708 void 709 skcidrClear( 710 skcidr_t *cidr); 711 #endif /* 0 */ 712 #define skcidrClear(cidr) memset(cidr, 0, sizeof(skcidr_t)) 713 714 715 /** 716 * skcidrGetIPAddr(cidr, ipaddr); 717 * 718 * Fill 'ipaddr' with the IP address contained by 'cidr'; that is, 719 * with the first IP address in the CIDR block represented by 720 * 'cidr'. 721 */ 722 void 723 skcidrGetIPAddr( 724 const skcidr_t *cidr, 725 skipaddr_t *ipaddr); 726 727 728 /** 729 * len = skcidrGetLength(cidr); 730 * 731 * Return the length of the subnet represented by 'cidr'. 732 */ 733 #if 0 734 uint8_t 735 skcidrGetLength( 736 const skcidr_t *cidr); 737 #endif /* 0 */ 738 #define skcidrGetLength(cidr) ((cidr)->v4.cidr_length) 739 740 741 /** 742 * skcidrIsV6(cidr); 743 * 744 * Return 1 if the skcidr_t pointed at by 'cidr' contains IPv6 745 * data. Return 0 otherwise. 746 */ 747 #if 0 748 int 749 skcidrIsV6( 750 const skcidr_t *cidr); 751 #endif /* 0 */ 752 #if !SK_ENABLE_IPV6 753 # define skcidrIsV6(cidr) (0) 754 #else 755 # define skcidrIsV6(cidr) ((cidr)->v4.is_ipv6) 756 #endif /* #else of #if !SK_ENABLE_IPV6 */ 757 758 759 /** 760 * ok = skcidrSetFromIPAddr(cidr, ipaddr, length); 761 * 762 * Set 'cidr' to the CIDR block that represents a subnet of 763 * 'length' bits that has the IP in 'ipaddr' as its base. Return 764 * -1 if 'length' is too long for the given 'ipaddr'. Return 0 765 * otherwise. 766 */ 767 int 768 skcidrSetFromIPAddr( 769 skcidr_t *cidr, 770 const skipaddr_t *ipaddr, 771 uint32_t cidr_len); 772 773 774 /** 775 * ok = skcidrSetV4(cidr, ipv4, length); 776 * 777 * Similar to skcidrSetFromIPAddr(), except use an integer 778 * representation of an IPv4 address. 779 */ 780 int 781 skcidrSetV4( 782 skcidr_t *cidr, 783 uint32_t ipv4, 784 uint32_t cidr_len); 785 786 #if SK_ENABLE_IPV6 787 /** 788 * ok = skcidrSetV6(cidr, ipv6, length); 789 * 790 * Similar to skcidrSetFromIPAddr(), except use an array 791 * representation of an IPv6 address. 792 */ 793 int 794 skcidrSetV6( 795 skcidr_t *cidr, 796 const uint8_t *ipv6, 797 uint32_t cidr_len); 798 #endif /* #if SK_ENABLE_IPV6 */ 799 800 801 /** 802 * ok = skipaddrToSockaddr(dest_sockaddr, len, src_ipaddr); 803 * 804 * Clear 'dest_sockaddr', and then set the family and address of 805 * 'dest_sockaddr' from 'src_ipaddr' where 'len' is the length of 806 * 'dest_sockaddr'. Return -1 if 'len' is too small, 0 otherwise. 807 */ 808 int 809 skipaddrToSockaddr( 810 struct sockaddr *dest_sockaddr, 811 size_t len, 812 const skipaddr_t *src_ipaddr); 813 814 /** 815 * ok = skipaddrFromSockaddr(dest_ipaddr, src) 816 * 817 * Set 'dest_ipaddr' to the address in 'src_sockaddr'. Return -1 818 * if 'src_sockaddr' does not represent an IP address, 0 otherwise. 819 */ 820 int 821 skipaddrFromSockaddr( 822 skipaddr_t *dest_ipaddr, 823 const struct sockaddr *src_sockaddr); 824 825 826 #ifdef __cplusplus 827 } 828 #endif 829 #endif /* _SKIPADDR_H */ 830 831 /* 832 ** Local Variables: 833 ** mode:c 834 ** indent-tabs-mode:nil 835 ** c-basic-offset:4 836 ** End: 837 */ 838