1 /* 2 * Copyright 2006-2015, 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) 122 return false; 123 124 return IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr); 125 } 126 127 128 /*! Checks if the given \a address is an Ipv6 address. 129 \return false if \a address is NULL, or with family different from AF_INET 130 true if it has AF_INET address family 131 */ 132 static bool 133 ipv6_is_same_family(const sockaddr *address) 134 { 135 if (address == NULL) 136 return false; 137 138 return address->sa_family == AF_INET6; 139 } 140 141 142 /*! Compares the IP-addresses of the two given address structures \a a and \a b. 143 \return true if IP-addresses of \a a and \a b are equal, false if not 144 */ 145 static bool 146 ipv6_equal_addresses(const sockaddr *a, const sockaddr *b) 147 { 148 if (a == NULL && b == NULL) 149 return true; 150 if (a != NULL && b == NULL) 151 return ipv6_is_empty_address(a, false); 152 if (a == NULL && b != NULL) 153 return ipv6_is_empty_address(b, false); 154 155 const sockaddr_in6 *i6a = (const sockaddr_in6 *)a; 156 const sockaddr_in6 *i6b = (const sockaddr_in6 *)b; 157 return !memcmp(&i6a->sin6_addr, &i6b->sin6_addr, sizeof(in6_addr)); 158 } 159 160 161 /*! Compares the ports of the two given address structures \a a and \a b. 162 \return true if ports of \a a and \a b are equal, false if not 163 */ 164 static bool 165 ipv6_equal_ports(const sockaddr *a, const sockaddr *b) 166 { 167 uint16 portA = a ? ((sockaddr_in6 *)a)->sin6_port : 0; 168 uint16 portB = b ? ((sockaddr_in6 *)b)->sin6_port : 0; 169 return portA == portB; 170 } 171 172 173 /*! Compares the IP-addresses and ports of the two given address structures 174 \a a and \a b. 175 \return true if IP-addresses and ports of \a a and \a b are equal, false if 176 not 177 */ 178 static bool 179 ipv6_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b) 180 { 181 if (a == NULL && b == NULL) 182 return true; 183 if (a != NULL && b == NULL) 184 return ipv6_is_empty_address(a, true); 185 if (a == NULL && b != NULL) 186 return ipv6_is_empty_address(b, true); 187 188 const sockaddr_in6 *i6a = (const sockaddr_in6 *)a; 189 const sockaddr_in6 *i6b = (const sockaddr_in6 *)b; 190 return i6a->sin6_port == i6b->sin6_port 191 && !memcmp(&i6a->sin6_addr, &i6b->sin6_addr, sizeof(in6_addr)); 192 } 193 194 195 /*! Applies the given \a mask two \a a and \a b and then checks whether 196 the masked addresses match. 197 \return true if \a a matches \a b after masking both, false if not 198 */ 199 static bool 200 ipv6_equal_masked_addresses(const sockaddr *a, const sockaddr *b, 201 const sockaddr *mask) 202 { 203 if (a == NULL && b == NULL) 204 return true; 205 206 const in6_addr *i6a; 207 if (a == NULL) 208 i6a = &in6addr_any; 209 else 210 i6a = &((const sockaddr_in6*)a)->sin6_addr; 211 212 const in6_addr *i6b; 213 if (b == NULL) 214 i6b = &in6addr_any; 215 else 216 i6b = &((const sockaddr_in6*)b)->sin6_addr; 217 218 if (!mask) 219 return !memcmp(i6a, i6b, sizeof(in6_addr)); 220 221 const uint8 *pmask = ((const sockaddr_in6 *)mask)->sin6_addr.s6_addr; 222 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 223 if (pmask[i] != 0xff) { 224 return (i6a->s6_addr[i] & pmask[i]) 225 == (i6b->s6_addr[i] & pmask[i]); 226 } 227 228 if (i6a->s6_addr[i] != i6b->s6_addr[i]) 229 return false; 230 } 231 232 return true; 233 } 234 235 236 /*! Routing utility function: determines the least significant bit that is set 237 in the given \a mask. 238 \return the number of the first bit that is set (0-32, where 32 means 239 that there's no bit set in the mask). 240 */ 241 static int32 242 ipv6_first_mask_bit(const sockaddr *_mask) 243 { 244 if (_mask == NULL) 245 return 0; 246 247 const uint8 *pmask = ((const sockaddr_in6 *)_mask)->sin6_addr.s6_addr; 248 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 249 if (pmask[i] == 0xff) 250 continue; 251 252 for (uint8 bit = 0; bit < 8; bit++) { 253 if ((pmask[i] & (1 << (7 - bit))) == 0) 254 return i * 8 + bit; 255 } 256 } 257 258 return 128; 259 } 260 261 262 /*! Routing utility function: checks the given \a mask for correctness (which 263 means that (starting with LSB) consists zero or more unset bits, followed 264 by bits that are all set). 265 \return true if \a mask is ok, false if not 266 */ 267 static bool 268 ipv6_check_mask(const sockaddr *_mask) 269 { 270 if (_mask == NULL) 271 return true; 272 273 bool zero = false; 274 const uint8 *pmask = ((const sockaddr_in6 *)_mask)->sin6_addr.s6_addr; 275 for (uint8 i = 0; i < sizeof(in6_addr); ++i) { 276 if (pmask[i] == 0xff) { 277 if (zero) 278 return false; 279 } else if (pmask[i] == 0) { 280 zero = true; 281 } else { 282 for (int8 bit = 7; bit >= 0; bit--) { 283 if (pmask[i] & (1 << bit)) { 284 if (zero) 285 return false; 286 } else { 287 zero = true; 288 } 289 } 290 } 291 } 292 293 return true; 294 } 295 296 297 /*! Creates a buffer for the given \a address and prints the address into 298 it (hexadecimal representation in network byte order or '<none>'). 299 If \a printPort is set, the port is printed, too. 300 \return B_OK if the address could be printed, \a buffer will point to 301 the resulting string 302 \return B_BAD_VALUE if no buffer has been given 303 \return B_NO_MEMORY if the buffer could not be allocated, 304 or does not have enogh space 305 */ 306 static status_t 307 ipv6_print_address_buffer(const sockaddr *_address, char *buffer, 308 size_t bufferSize, bool printPort) 309 { 310 const sockaddr_in6 *address = (const sockaddr_in6 *)_address; 311 312 if (buffer == NULL) 313 return B_BAD_VALUE; 314 315 if (address == NULL) { 316 if (bufferSize < sizeof("<none>")) 317 return B_NO_MEMORY; 318 strcpy(buffer, "<none>"); 319 } else { 320 if (printPort && bufferSize > 0) { 321 *buffer = '['; 322 buffer++; 323 bufferSize--; 324 } 325 326 if (!ip6_sprintf(&address->sin6_addr, buffer, bufferSize)) 327 return B_NO_MEMORY; 328 329 if (printPort) { 330 char port[7]; 331 snprintf(port, sizeof(port), "]:%d", ntohs(address->sin6_port)); 332 if (bufferSize - strlen(buffer) < strlen(port) + 1) 333 return B_NO_MEMORY; 334 strcat(buffer, port); 335 } 336 } 337 338 return B_OK; 339 } 340 341 342 static status_t 343 ipv6_print_address(const sockaddr *_address, char **_buffer, bool printPort) 344 { 345 if (_buffer == NULL) 346 return B_BAD_VALUE; 347 348 char tmp[64]; 349 ipv6_print_address_buffer(_address, tmp, sizeof(tmp), printPort); 350 351 *_buffer = strdup(tmp); 352 if (*_buffer == NULL) 353 return B_NO_MEMORY; 354 355 return B_OK; 356 } 357 358 359 /*! Determines the port of the given \a address. 360 \return uint16 representing the port-nr 361 */ 362 static uint16 363 ipv6_get_port(const sockaddr *address) 364 { 365 if (address == NULL || address->sa_len == 0) 366 return 0; 367 368 return ((sockaddr_in6 *)address)->sin6_port; 369 } 370 371 372 /*! Sets the port of the given \a address to \a port. 373 \return B_OK if the port has been set 374 \return B_BAD_VALUE if \a address is NULL or has not been initialized 375 */ 376 static status_t 377 ipv6_set_port(sockaddr *address, uint16 port) 378 { 379 if (address == NULL || address->sa_len == 0) 380 return B_BAD_VALUE; 381 382 ((sockaddr_in6 *)address)->sin6_port = port; 383 return B_OK; 384 } 385 386 387 /*! Sets \a address to \a from. 388 \return B_OK if \a from has been copied into \a address 389 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 390 address given in from has not been initialized 391 \return B_MISMATCHED_VALUES if from is not of family AF_INET6 392 */ 393 static status_t 394 ipv6_set_to(sockaddr *address, const sockaddr *from) 395 { 396 if (address == NULL || from == NULL || from->sa_len == 0) 397 return B_BAD_VALUE; 398 399 if (from->sa_family != AF_INET6) 400 return B_MISMATCHED_VALUES; 401 402 memcpy(address, from, sizeof(sockaddr_in6)); 403 address->sa_len = sizeof(sockaddr_in6); 404 return B_OK; 405 } 406 407 408 /*! Updates missing parts in \a address with the values in \a from. 409 \return B_OK if \a address has been updated from \a from 410 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 411 address given in from has not been initialized 412 \return B_MISMATCHED_VALUES if from is not of family AF_INET6 413 */ 414 static status_t 415 ipv6_update_to(sockaddr *_address, const sockaddr *_from) 416 { 417 sockaddr_in6 *address = (sockaddr_in6 *)_address; 418 const sockaddr_in6 *from = (const sockaddr_in6 *)_from; 419 420 if (address == NULL || from == NULL || from->sin6_len == 0) 421 return B_BAD_VALUE; 422 423 if (from->sin6_family != AF_INET6) 424 return B_BAD_VALUE; 425 426 address->sin6_family = AF_INET6; 427 address->sin6_len = sizeof(sockaddr_in6); 428 429 if (address->sin6_port == 0) 430 address->sin6_port = from->sin6_port; 431 432 if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)) { 433 memcpy(address->sin6_addr.s6_addr, from->sin6_addr.s6_addr, 434 sizeof(in6_addr)); 435 } 436 437 return B_OK; 438 } 439 440 441 /*! Sets \a address to the empty address (0.0.0.0). 442 \return B_OK if \a address has been set 443 \return B_BAD_VALUE if \a address is NULL 444 */ 445 static status_t 446 ipv6_set_to_empty_address(sockaddr *address) 447 { 448 if (address == NULL) 449 return B_BAD_VALUE; 450 451 memset(address, 0, sizeof(sockaddr_in6)); 452 address->sa_len = sizeof(sockaddr_in6); 453 address->sa_family = AF_INET6; 454 return B_OK; 455 } 456 457 458 static status_t 459 ipv6_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast, 460 const sockaddr *_address, const sockaddr *_mask) 461 { 462 sockaddr_in6 *defaultMask = (sockaddr_in6 *)_defaultMask; 463 sockaddr_in6 *address = (sockaddr_in6 *)_address; 464 sockaddr_in6 *mask = (sockaddr_in6 *)_mask; 465 466 if (address == NULL || defaultMask == NULL) 467 return B_BAD_VALUE; 468 469 defaultMask->sin6_len = sizeof(sockaddr_in); 470 defaultMask->sin6_family = AF_INET6; 471 defaultMask->sin6_port = 0; 472 if (mask != NULL) { 473 memcpy(defaultMask->sin6_addr.s6_addr, 474 mask->sin6_addr.s6_addr, sizeof(in6_addr)); 475 } else { 476 // use /128 as the default mask 477 memset(defaultMask->sin6_addr.s6_addr, 0xff, sizeof(in6_addr)); 478 } 479 480 return B_OK; 481 } 482 483 484 /*! Computes a hash value of the given \a address. 485 \return uint32 representing the hash value 486 */ 487 static uint32 488 ipv6_hash_address(const struct sockaddr* _address, bool includePort) 489 { 490 const sockaddr_in6* address = (const sockaddr_in6*)_address; 491 if (address == NULL || address->sin6_len == 0) 492 return 0; 493 494 // TODO: also use sin6_flowinfo and sin6_scope_id? 495 uint32 port = includePort ? address->sin6_port : 0; 496 497 uint32 result = jenkins_hashword((const uint32*)&address->sin6_addr, 498 sizeof(in6_addr) / sizeof(uint32), 0); 499 return jenkins_hashword(&port, 1, result); 500 } 501 502 503 /*! Computes a hash-value of the given addresses \a ourAddress 504 and \a peerAddress. 505 \return uint32 representing the hash-value 506 */ 507 static uint32 508 ipv6_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 509 { 510 uint32 result = ipv6_hash_address(peerAddress, true); 511 return jenkins_hashword(&result, 1, ipv6_hash_address(ourAddress, true)); 512 } 513 514 515 /*! Adds the given \a address to the IP-checksum \a checksum. 516 \return B_OK if \a address has been added to the checksum 517 \return B_BAD_VALUE if either \a address or \a checksum is NULL or if 518 the given address is not initialized 519 */ 520 static status_t 521 ipv6_checksum_address(Checksum *checksum, const sockaddr *address) 522 { 523 if (checksum == NULL || address == NULL || address->sa_len == 0) 524 return B_BAD_VALUE; 525 526 in6_addr &a = ((sockaddr_in6 *)address)->sin6_addr; 527 for (uint32 i = 0; i < sizeof(in6_addr); i += 2) 528 (*checksum) << *(uint16*)(a.s6_addr + i); 529 530 return B_OK; 531 } 532 533 534 static void 535 ipv6_get_loopback_address(sockaddr *_address) 536 { 537 sockaddr_in6 *address = (sockaddr_in6 *)_address; 538 memset(address, 0, sizeof(sockaddr_in6)); 539 address->sin6_len = sizeof(sockaddr_in6); 540 address->sin6_family = AF_INET6; 541 memcpy(&address->sin6_addr, &in6addr_loopback, sizeof(in6_addr)); 542 } 543 544 545 net_address_module_info gIPv6AddressModule = { 546 { 547 NULL, 548 0, 549 NULL 550 }, 551 0, // flags 552 ipv6_copy_address, 553 ipv6_mask_address, 554 ipv6_equal_addresses, 555 ipv6_equal_ports, 556 ipv6_equal_addresses_and_ports, 557 ipv6_equal_masked_addresses, 558 ipv6_is_empty_address, 559 ipv6_is_same_family, 560 ipv6_first_mask_bit, 561 ipv6_check_mask, 562 ipv6_print_address, 563 ipv6_print_address_buffer, 564 ipv6_get_port, 565 ipv6_set_port, 566 ipv6_set_to, 567 ipv6_set_to_empty_address, 568 ipv6_set_to_defaults, 569 ipv6_update_to, 570 ipv6_hash_address, 571 ipv6_hash_address_pair, 572 ipv6_checksum_address, 573 ipv6_get_loopback_address 574 }; 575