1 /* 2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Oliver Tappe, zooey@hirschkaefer.de 8 * Atis Elsts, the.kfx@gmail.com 9 */ 10 11 12 #include <net_datalink.h> 13 14 #include <NetUtilities.h> 15 16 #include <memory.h> 17 #include <netinet6/in6.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 #include "ipv6_address.h" 22 #include "ipv6_utils.h" 23 #include "jenkins.h" 24 25 26 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 27 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; 28 29 30 static void 31 ipv6_mask_adress_inplace(sockaddr *address, const sockaddr *mask) 32 { 33 in6_addr &i6addr = ((sockaddr_in6 *)address)->sin6_addr; 34 const in6_addr &i6mask = ((const sockaddr_in6 *)mask)->sin6_addr; 35 36 for (uint32 i = 0; i < sizeof(in6_addr); i++) 37 i6addr.s6_addr[i] &= i6mask.s6_addr[i]; 38 } 39 40 41 /*! Routing utility function: copies address \a from into a new address 42 that is put into \a to. 43 If \a replaceWithZeros is set \a from will be replaced by an empty 44 address. 45 If a \a mask is given it is applied to \a from (such that \a to is the 46 result of \a from & \a mask). 47 \return B_OK if the address could be copied 48 \return B_NO_MEMORY if the new address could not be allocated 49 \return B_BAD_VALUE if any of \a from or \a mask refers to an uninitialized 50 address 51 \return B_MISMATCHED_VALUES if \a address does not match family AF_INET 52 */ 53 static status_t 54 ipv6_copy_address(const sockaddr *from, sockaddr **to, 55 bool replaceWithZeros = false, const sockaddr *mask = NULL) 56 { 57 if (replaceWithZeros) { 58 *to = (sockaddr *)malloc(sizeof(sockaddr_in6)); 59 if (*to == NULL) 60 return B_NO_MEMORY; 61 62 memset(*to, 0, sizeof(sockaddr_in6)); 63 (*to)->sa_family = AF_INET6; 64 (*to)->sa_len = sizeof(sockaddr_in6); 65 } else { 66 if (from == NULL) 67 return B_OK; 68 if (from->sa_len == 0 || (mask != NULL && mask->sa_len == 0)) 69 return B_BAD_VALUE; 70 if (from->sa_family != AF_INET6) 71 return B_MISMATCHED_VALUES; 72 73 *to = (sockaddr *)malloc(sizeof(sockaddr_in6)); 74 if (*to == NULL) 75 return B_NO_MEMORY; 76 77 memcpy(*to, from, sizeof(sockaddr_in6)); 78 79 if (mask != NULL) 80 ipv6_mask_adress_inplace(*to, mask); 81 } 82 return B_OK; 83 } 84 85 86 /*! Routing utility function: applies \a mask to given \a address and puts 87 the resulting address into \a result. 88 \return B_OK if the mask has been applied 89 \return B_BAD_VALUE if \a address is NULL or if any of \a address or \a mask 90 refers to an uninitialized address 91 */ 92 static status_t 93 ipv6_mask_address(const sockaddr *address, const sockaddr *mask, 94 sockaddr *result) 95 { 96 if (address == NULL || address->sa_len == 0 || result == NULL 97 || (mask != NULL && mask->sa_len == 0)) 98 return B_BAD_VALUE; 99 100 memcpy(result, address, sizeof(sockaddr_in6)); 101 if (mask != NULL) 102 ipv6_mask_adress_inplace(result, mask); 103 104 return B_OK; 105 } 106 107 108 /*! Checks if the given \a address is the empty address. By default, the port 109 is checked, too, but you can avoid that by passing \a checkPort = false. 110 \return true if \a address is NULL, uninitialized or the empty address, 111 false if not 112 */ 113 static bool 114 ipv6_is_empty_address(const sockaddr *_address, bool checkPort) 115 { 116 if (_address == NULL || _address->sa_len == 0 117 || _address->sa_family == AF_UNSPEC) 118 return true; 119 120 const sockaddr_in6 *address = (const sockaddr_in6 *)_address; 121 if (checkPort && address->sin6_port != 0) return false; 122 return IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr); 123 } 124 125 126 /*! Checks if the given \a address is an Ipv6 address. 127 \return false if \a address is NULL, or with family different from AF_INET 128 true if it has AF_INET address family 129 */ 130 static bool 131 ipv6_is_same_family(const sockaddr *address) 132 { 133 if (address == NULL) 134 return false; 135 136 return address->sa_family == AF_INET6; 137 } 138 139 140 /*! Compares the IP-addresses of the two given address structures \a a and \a b. 141 \return true if IP-addresses of \a a and \a b are equal, false if not 142 */ 143 static bool 144 ipv6_equal_addresses(const sockaddr *a, const sockaddr *b) 145 { 146 if (a == NULL && b == NULL) 147 return true; 148 if (a != NULL && b == NULL) 149 return ipv6_is_empty_address(a, false); 150 if (a == NULL && b != NULL) 151 return ipv6_is_empty_address(b, false); 152 153 const sockaddr_in6 *i6a = (const sockaddr_in6 *)a; 154 const sockaddr_in6 *i6b = (const sockaddr_in6 *)b; 155 return !memcmp(&i6a->sin6_addr, &i6b->sin6_addr, sizeof(in6_addr)); 156 } 157 158 159 /*! Compares the ports of the two given address structures \a a and \a b. 160 \return true if ports of \a a and \a b are equal, false if not 161 */ 162 static bool 163 ipv6_equal_ports(const sockaddr *a, const sockaddr *b) 164 { 165 uint16 portA = a ? ((sockaddr_in6 *)a)->sin6_port : 0; 166 uint16 portB = b ? ((sockaddr_in6 *)b)->sin6_port : 0; 167 return portA == portB; 168 } 169 170 171 /*! Compares the IP-addresses and ports of the two given address structures 172 \a a and \a b. 173 \return true if IP-addresses and ports of \a a and \a b are equal, false if 174 not 175 */ 176 static bool 177 ipv6_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b) 178 { 179 if (a == NULL && b == NULL) 180 return true; 181 if (a != NULL && b == NULL) 182 return ipv6_is_empty_address(a, true); 183 if (a == NULL && b != NULL) 184 return ipv6_is_empty_address(b, true); 185 186 const sockaddr_in6 *i6a = (const sockaddr_in6 *)a; 187 const sockaddr_in6 *i6b = (const sockaddr_in6 *)b; 188 return i6a->sin6_port == i6b->sin6_port 189 && !memcmp(&i6a->sin6_addr, &i6b->sin6_addr, sizeof(in6_addr)); 190 } 191 192 193 /*! Applies the given \a mask two \a a and \a b and then checks whether 194 the masked addresses match. 195 \return true if \a a matches \a b after masking both, false if not 196 */ 197 static bool 198 ipv6_equal_masked_addresses(const sockaddr *a, const sockaddr *b, 199 const sockaddr *mask) 200 { 201 if (a == NULL && b == NULL) 202 return true; 203 204 const in6_addr *i6a; 205 if (a == NULL) 206 i6a = &in6addr_any; 207 else 208 i6a = &((const sockaddr_in6*)a)->sin6_addr; 209 210 const in6_addr *i6b; 211 if (b == NULL) 212 i6b = &in6addr_any; 213 else 214 i6b = &((const sockaddr_in6*)b)->sin6_addr; 215 216 if (!mask) 217 return !memcmp(i6a, i6b, sizeof(in6_addr)); 218 219 const uint8 *pmask = ((const sockaddr_in6 *)mask)->sin6_addr.s6_addr; 220 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 221 if (pmask[i] != 0xff) { 222 return (i6a->s6_addr[i] & pmask[i]) 223 == (i6b->s6_addr[i] & pmask[i]); 224 } 225 226 if (i6a->s6_addr[i] != i6b->s6_addr[i]) 227 return false; 228 } 229 230 return true; 231 } 232 233 234 /*! Routing utility function: determines the least significant bit that is set 235 in the given \a mask. 236 \return the number of the first bit that is set (0-32, where 32 means 237 that there's no bit set in the mask). 238 */ 239 static int32 240 ipv6_first_mask_bit(const sockaddr *_mask) 241 { 242 if (_mask == NULL) 243 return 0; 244 245 const uint8 *pmask = ((const sockaddr_in6 *)_mask)->sin6_addr.s6_addr; 246 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 247 if (pmask[i] == 0xff) 248 continue; 249 250 for (uint8 bit = 0; bit < 8; bit++) { 251 if ((pmask[i] & (1 << (7 - bit))) == 0) 252 return i * 8 + bit; 253 } 254 } 255 256 return 128; 257 } 258 259 260 /*! Routing utility function: checks the given \a mask for correctness (which 261 means that (starting with LSB) consists zero or more unset bits, followed 262 by bits that are all set). 263 \return true if \a mask is ok, false if not 264 */ 265 static bool 266 ipv6_check_mask(const sockaddr *_mask) 267 { 268 if (_mask == NULL) 269 return true; 270 271 bool zero = false; 272 const uint8 *pmask = ((const sockaddr_in6 *)_mask)->sin6_addr.s6_addr; 273 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 274 if (pmask[i] == 0xff) { 275 if (zero) 276 return false; 277 } else if (pmask[i] == 0) { 278 zero = true; 279 } else { 280 for (int8 bit = 7; bit >= 0; bit--) { 281 if (pmask[i] & (1 << bit)) { 282 if (zero) 283 return false; 284 } else { 285 zero = true; 286 } 287 } 288 } 289 } 290 291 return true; 292 } 293 294 295 /*! Creates a buffer for the given \a address and prints the address into 296 it (hexadecimal representation in network byte order or '<none>'). 297 If \a printPort is set, the port is printed, too. 298 \return B_OK if the address could be printed, \a buffer will point to 299 the resulting string 300 \return B_BAD_VALUE if no buffer has been given 301 \return B_NO_MEMORY if the buffer could not be allocated, 302 or does not have enogh space 303 */ 304 static status_t 305 ipv6_print_address_buffer(const sockaddr *_address, char *buffer, 306 size_t bufferSize, bool printPort) 307 { 308 const sockaddr_in6 *address = (const sockaddr_in6 *)_address; 309 310 if (buffer == NULL) 311 return B_BAD_VALUE; 312 313 if (address == NULL) { 314 if (bufferSize < sizeof("<none>")) 315 return B_NO_MEMORY; 316 strcpy(buffer, "<none>"); 317 } else { 318 if (printPort && bufferSize > 0) { 319 *buffer = '['; 320 buffer++; 321 bufferSize--; 322 } 323 324 if (!ip6_sprintf(&address->sin6_addr, buffer, bufferSize)) 325 return B_NO_MEMORY; 326 327 if (printPort) { 328 char port[7]; 329 sprintf(port, "]:%d", ntohs(address->sin6_port)); 330 if (bufferSize - strlen(buffer) < strlen(port) + 1) 331 return B_NO_MEMORY; 332 strcat(buffer, port); 333 } 334 } 335 336 return B_OK; 337 } 338 339 340 static status_t 341 ipv6_print_address(const sockaddr *_address, char **_buffer, bool printPort) 342 { 343 if (_buffer == NULL) 344 return B_BAD_VALUE; 345 346 char tmp[64]; 347 ipv6_print_address_buffer(_address, tmp, sizeof(tmp), printPort); 348 349 *_buffer = strdup(tmp); 350 if (*_buffer == NULL) 351 return B_NO_MEMORY; 352 353 return B_OK; 354 } 355 356 357 /*! Determines the port of the given \a address. 358 \return uint16 representing the port-nr 359 */ 360 static uint16 361 ipv6_get_port(const sockaddr *address) 362 { 363 if (address == NULL || address->sa_len == 0) 364 return 0; 365 366 return ((sockaddr_in6 *)address)->sin6_port; 367 } 368 369 370 /*! Sets the port of the given \a address to \a port. 371 \return B_OK if the port has been set 372 \return B_BAD_VALUE if \a address is NULL or has not been initialized 373 */ 374 static status_t 375 ipv6_set_port(sockaddr *address, uint16 port) 376 { 377 if (address == NULL || address->sa_len == 0) 378 return B_BAD_VALUE; 379 380 ((sockaddr_in6 *)address)->sin6_port = port; 381 return B_OK; 382 } 383 384 385 /*! Sets \a address to \a from. 386 \return B_OK if \a from has been copied into \a address 387 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 388 address given in from has not been initialized 389 \return B_MISMATCHED_VALUES if from is not of family AF_INET6 390 */ 391 static status_t 392 ipv6_set_to(sockaddr *address, const sockaddr *from) 393 { 394 if (address == NULL || from == NULL || from->sa_len == 0) 395 return B_BAD_VALUE; 396 397 if (from->sa_family != AF_INET6) 398 return B_MISMATCHED_VALUES; 399 400 memcpy(address, from, sizeof(sockaddr_in6)); 401 address->sa_len = sizeof(sockaddr_in6); 402 return B_OK; 403 } 404 405 406 /*! Updates missing parts in \a address with the values in \a from. 407 \return B_OK if \a address has been updated from \a from 408 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 409 address given in from has not been initialized 410 \return B_MISMATCHED_VALUES if from is not of family AF_INET6 411 */ 412 static status_t 413 ipv6_update_to(sockaddr *_address, const sockaddr *_from) 414 { 415 sockaddr_in6 *address = (sockaddr_in6 *)_address; 416 const sockaddr_in6 *from = (const sockaddr_in6 *)_from; 417 418 if (address == NULL || from == NULL || from->sin6_len == 0) 419 return B_BAD_VALUE; 420 421 if (from->sin6_family != AF_INET6) 422 return B_BAD_VALUE; 423 424 address->sin6_family = AF_INET6; 425 address->sin6_len = sizeof(sockaddr_in6); 426 427 if (address->sin6_port == 0) 428 address->sin6_port = from->sin6_port; 429 430 if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)) { 431 memcpy(address->sin6_addr.s6_addr, from->sin6_addr.s6_addr, 432 sizeof(in6_addr)); 433 } 434 435 return B_OK; 436 } 437 438 439 /*! Sets \a address to the empty address (0.0.0.0). 440 \return B_OK if \a address has been set 441 \return B_BAD_VALUE if \a address is NULL 442 */ 443 static status_t 444 ipv6_set_to_empty_address(sockaddr *address) 445 { 446 if (address == NULL) 447 return B_BAD_VALUE; 448 449 memset(address, 0, sizeof(sockaddr_in6)); 450 address->sa_len = sizeof(sockaddr_in6); 451 address->sa_family = AF_INET6; 452 return B_OK; 453 } 454 455 456 static status_t 457 ipv6_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast, 458 const sockaddr *_address, const sockaddr *_mask) 459 { 460 sockaddr_in6 *defaultMask = (sockaddr_in6 *)_defaultMask; 461 sockaddr_in6 *address = (sockaddr_in6 *)_address; 462 sockaddr_in6 *mask = (sockaddr_in6 *)_mask; 463 464 if (address == NULL || defaultMask == NULL) 465 return B_BAD_VALUE; 466 467 defaultMask->sin6_len = sizeof(sockaddr_in); 468 defaultMask->sin6_family = AF_INET6; 469 defaultMask->sin6_port = 0; 470 if (mask != NULL) { 471 memcpy(defaultMask->sin6_addr.s6_addr, 472 mask->sin6_addr.s6_addr, sizeof(in6_addr)); 473 } else { 474 // use /128 as the default mask 475 memset(defaultMask->sin6_addr.s6_addr, 0xff, sizeof(in6_addr)); 476 } 477 478 return B_OK; 479 } 480 481 482 /*! Computes a hash value of the given \a address. 483 \return uint32 representing the hash value 484 */ 485 static uint32 486 ipv6_hash_address(const struct sockaddr* _address, bool includePort) 487 { 488 const sockaddr_in6* address = (const sockaddr_in6*)_address; 489 if (address == NULL || address->sin6_len == 0) 490 return 0; 491 492 // TODO: also use sin6_flowinfo and sin6_scope_id? 493 uint32 port = includePort ? address->sin6_port : 0; 494 495 uint32 result = jenkins_hashword((const uint32*)&address->sin6_addr, 496 sizeof(in6_addr) / sizeof(uint32), 0); 497 return jenkins_hashword(&port, 1, result); 498 } 499 500 501 /*! Computes a hash-value of the given addresses \a ourAddress 502 and \a peerAddress. 503 \return uint32 representing the hash-value 504 */ 505 static uint32 506 ipv6_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 507 { 508 uint32 result = ipv6_hash_address(peerAddress, true); 509 return jenkins_hashword(&result, 1, ipv6_hash_address(ourAddress, true)); 510 } 511 512 513 /*! Adds the given \a address to the IP-checksum \a checksum. 514 \return B_OK if \a address has been added to the checksum 515 \return B_BAD_VALUE if either \a address or \a checksum is NULL or if 516 the given address is not initialized 517 */ 518 static status_t 519 ipv6_checksum_address(struct Checksum *checksum, const sockaddr *address) 520 { 521 if (checksum == NULL || address == NULL || address->sa_len == 0) 522 return B_BAD_VALUE; 523 524 in6_addr &a = ((sockaddr_in6 *)address)->sin6_addr; 525 for (uint32 i = 0; i < sizeof(in6_addr); i += 2) 526 (*checksum) << *(uint16*)(a.s6_addr + i); 527 528 return B_OK; 529 } 530 531 532 static void 533 ipv6_get_loopback_address(sockaddr *_address) 534 { 535 sockaddr_in6 *address = (sockaddr_in6 *)_address; 536 memset(address, 0, sizeof(sockaddr_in6)); 537 address->sin6_len = sizeof(sockaddr_in6); 538 address->sin6_family = AF_INET6; 539 memcpy(&address->sin6_addr, &in6addr_loopback, sizeof(in6_addr)); 540 } 541 542 543 net_address_module_info gIPv6AddressModule = { 544 { 545 NULL, 546 0, 547 NULL 548 }, 549 0, // flags 550 ipv6_copy_address, 551 ipv6_mask_address, 552 ipv6_equal_addresses, 553 ipv6_equal_ports, 554 ipv6_equal_addresses_and_ports, 555 ipv6_equal_masked_addresses, 556 ipv6_is_empty_address, 557 ipv6_is_same_family, 558 ipv6_first_mask_bit, 559 ipv6_check_mask, 560 ipv6_print_address, 561 ipv6_print_address_buffer, 562 ipv6_get_port, 563 ipv6_set_port, 564 ipv6_set_to, 565 ipv6_set_to_empty_address, 566 ipv6_set_to_defaults, 567 ipv6_update_to, 568 ipv6_hash_address, 569 ipv6_hash_address_pair, 570 ipv6_checksum_address, 571 ipv6_get_loopback_address 572 }; 573