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 */ 9 10 11 #include <net_datalink.h> 12 13 #include <ByteOrder.h> 14 #include <KernelExport.h> 15 16 #include <NetUtilities.h> 17 18 #include <memory.h> 19 #include <netinet/in.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 24 /*! Routing utility function: copies address \a from into a new address 25 that is put into \a to. 26 If \a replaceWithZeros is set \a from will be replaced by an empty 27 address. 28 If a \a mask is given it is applied to \a from (such that \a to is the 29 result of \a from & \a mask). 30 \return B_OK if the address could be copied 31 \return B_NO_MEMORY if the new address could not be allocated 32 \return B_BAD_VALUE if any of \a from or \a mask refers to an uninitialized 33 address 34 \return B_MISMATCHED_VALUES if \a address does not match family AF_INET 35 */ 36 static status_t 37 ipv4_copy_address(const sockaddr *from, sockaddr **to, 38 bool replaceWithZeros = false, const sockaddr *mask = NULL) 39 { 40 if (replaceWithZeros) { 41 *to = (sockaddr *)malloc(sizeof(sockaddr_in)); 42 if (*to == NULL) 43 return B_NO_MEMORY; 44 45 memset(*to, 0, sizeof(sockaddr_in)); 46 (*to)->sa_family = AF_INET; 47 (*to)->sa_len = sizeof(sockaddr_in); 48 } else { 49 if (from == NULL) 50 return B_OK; 51 if (from->sa_len == 0 || (mask != NULL && mask->sa_len == 0)) 52 return B_BAD_VALUE; 53 if (from->sa_family != AF_INET) 54 return B_MISMATCHED_VALUES; 55 56 *to = (sockaddr *)malloc(sizeof(sockaddr_in)); 57 if (*to == NULL) 58 return B_NO_MEMORY; 59 60 memcpy(*to, from, sizeof(sockaddr_in)); 61 62 if (mask != NULL) { 63 ((sockaddr_in *)*to)->sin_addr.s_addr 64 &= ((const sockaddr_in *)mask)->sin_addr.s_addr; 65 } 66 } 67 return B_OK; 68 } 69 70 71 /*! Routing utility function: applies \a mask to given \a address and puts 72 the resulting address into \a result. 73 \return B_OK if the mask has been applied 74 \return B_BAD_VALUE if \a address is NULL or if any of \a address or \a mask 75 refers to an uninitialized address 76 */ 77 static status_t 78 ipv4_mask_address(const sockaddr *address, const sockaddr *mask, 79 sockaddr *result) 80 { 81 if (address == NULL || address->sa_len == 0 || result == NULL 82 || (mask != NULL && mask->sa_len == 0)) 83 return B_BAD_VALUE; 84 85 memcpy(result, address, sizeof(sockaddr_in)); 86 if (mask != NULL) { 87 ((sockaddr_in *)result)->sin_addr.s_addr 88 &= ((sockaddr_in *)mask)->sin_addr.s_addr; 89 } 90 91 return B_OK; 92 } 93 94 95 /*! Checks if the given \a address is the empty address. By default, the port 96 is checked, too, but you can avoid that by passing \a checkPort = false. 97 \return true if \a address is NULL, uninitialized or the empty address, 98 false if not 99 */ 100 static bool 101 ipv4_is_empty_address(const sockaddr *address, bool checkPort) 102 { 103 if (address == NULL || address->sa_len == 0 104 || address->sa_family == AF_UNSPEC) 105 return true; 106 107 return ((sockaddr_in *)address)->sin_addr.s_addr == 0 108 && (!checkPort || ((sockaddr_in *)address)->sin_port == 0); 109 } 110 111 112 /*! Checks if the given \a address is an IPv4 address. 113 \return false if \a address is NULL, or with family different from AF_INET 114 true if it has AF_INET address family 115 */ 116 static bool 117 ipv4_is_same_family(const sockaddr *address) 118 { 119 if (address == NULL) 120 return false; 121 122 return address->sa_family == AF_INET; 123 } 124 125 126 /*! Compares the IP-addresses of the two given address structures \a a and \a b. 127 \return true if IP-addresses of \a a and \a b are equal, false if not 128 */ 129 static bool 130 ipv4_equal_addresses(const sockaddr *a, const sockaddr *b) 131 { 132 if (a == NULL && b == NULL) 133 return true; 134 if (a != NULL && b == NULL) 135 return ipv4_is_empty_address(a, false); 136 if (a == NULL && b != NULL) 137 return ipv4_is_empty_address(b, false); 138 139 return ((sockaddr_in *)a)->sin_addr.s_addr 140 == ((sockaddr_in *)b)->sin_addr.s_addr; 141 } 142 143 144 /*! Compares the ports of the two given address structures \a a and \a b. 145 \return true if ports of \a a and \a b are equal, false if not 146 */ 147 static bool 148 ipv4_equal_ports(const sockaddr *a, const sockaddr *b) 149 { 150 uint16 portA = a ? ((sockaddr_in *)a)->sin_port : 0; 151 uint16 portB = b ? ((sockaddr_in *)b)->sin_port : 0; 152 return portA == portB; 153 } 154 155 156 /*! Compares the IP-addresses and ports of the two given address structures 157 \a a and \a b. 158 \return true if IP-addresses and ports of \a a and \a b are equal, false if 159 not 160 */ 161 static bool 162 ipv4_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b) 163 { 164 if (a == NULL && b == NULL) 165 return true; 166 if (a != NULL && b == NULL) 167 return ipv4_is_empty_address(a, true); 168 if (a == NULL && b != NULL) 169 return ipv4_is_empty_address(b, true); 170 171 return ((sockaddr_in *)a)->sin_addr.s_addr 172 == ((sockaddr_in *)b)->sin_addr.s_addr 173 && ((sockaddr_in *)a)->sin_port == ((sockaddr_in *)b)->sin_port; 174 } 175 176 177 /*! Applies the given \a mask two \a a and \a b and then checks whether 178 the masked addresses match. 179 \return true if \a a matches \a b after masking both, false if not 180 */ 181 static bool 182 ipv4_equal_masked_addresses(const sockaddr *a, const sockaddr *b, 183 const sockaddr *mask) 184 { 185 if (a == NULL && b == NULL) 186 return true; 187 188 sockaddr emptyAddr; 189 if (a == NULL || b == NULL) { 190 memset(&emptyAddr, 0, sizeof(sockaddr_in)); 191 if (a == NULL) 192 a = &emptyAddr; 193 else if (b == NULL) 194 b = &emptyAddr; 195 } 196 197 uint32 aValue = ((sockaddr_in *)a)->sin_addr.s_addr; 198 uint32 bValue = ((sockaddr_in *)b)->sin_addr.s_addr; 199 200 if (!mask) 201 return aValue == bValue; 202 203 uint32 maskValue = ((sockaddr_in *)mask)->sin_addr.s_addr; 204 return (aValue & maskValue) == (bValue & maskValue); 205 } 206 207 208 /*! Routing utility function: determines the least significant bit that is set 209 in the given \a mask. 210 \return the number of the first bit that is set (0-32, where 32 means 211 that there's no bit set in the mask). 212 */ 213 static int32 214 ipv4_first_mask_bit(const sockaddr *_mask) 215 { 216 if (_mask == NULL) 217 return 0; 218 219 uint32 mask = ntohl(((const sockaddr_in *)_mask)->sin_addr.s_addr); 220 221 // TODO: this can be optimized, there are also some nice assembler mnemonics 222 // for this 223 int8 bit = 0; 224 for (uint32 bitMask = 1; bit < 32; bitMask <<= 1, bit++) { 225 if (mask & bitMask) 226 return bit; 227 } 228 229 return 32; 230 } 231 232 233 /*! Routing utility function: checks the given \a mask for correctness (which 234 means that (starting with LSB) consists zero or more unset bits, followed 235 by bits that are all set). 236 \return true if \a mask is ok, false if not 237 */ 238 static bool 239 ipv4_check_mask(const sockaddr *_mask) 240 { 241 if (_mask == NULL) 242 return true; 243 244 uint32 mask = ntohl(((const sockaddr_in *)_mask)->sin_addr.s_addr); 245 246 // A mask (from LSB) starts with zeros, after the first one, only ones 247 // are allowed: 248 bool zero = true; 249 int8 bit = 0; 250 for (uint32 bitMask = 1; bit < 32; bitMask <<= 1, bit++) { 251 if (mask & bitMask) { 252 if (zero) 253 zero = false; 254 } else if (!zero) 255 return false; 256 } 257 return true; 258 } 259 260 261 /*! Creates a buffer for the given \a address and prints the address into 262 it (hexadecimal representation in host byte order or '<none>'). 263 If \a printPort is set, the port is printed, too. 264 \return B_OK if the address could be printed, \a buffer will point to 265 the resulting string 266 \return B_BAD_VALUE if no buffer has been given 267 \return B_NO_MEMORY if the buffer could not be allocated 268 */ 269 static status_t 270 ipv4_print_address_buffer(const sockaddr *_address, char *buffer, 271 size_t bufferSize, bool printPort) 272 { 273 const sockaddr_in *address = (const sockaddr_in *)_address; 274 275 if (buffer == NULL) 276 return B_BAD_VALUE; 277 278 if (address == NULL) 279 strlcpy(buffer, "<none>", bufferSize); 280 else { 281 unsigned int addr = ntohl(address->sin_addr.s_addr); 282 283 if (printPort) { 284 snprintf(buffer, bufferSize, "%u.%u.%u.%u:%u", 285 (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, 286 addr & 0xff, ntohs(address->sin_port)); 287 } else { 288 snprintf(buffer, bufferSize, "%u.%u.%u.%u", (addr >> 24) & 0xff, 289 (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); 290 } 291 } 292 293 return B_OK; 294 } 295 296 297 static status_t 298 ipv4_print_address(const sockaddr *_address, char **_buffer, bool printPort) 299 { 300 if (_buffer == NULL) 301 return B_BAD_VALUE; 302 303 char tmp[64]; 304 ipv4_print_address_buffer(_address, tmp, sizeof(tmp), printPort); 305 306 *_buffer = strdup(tmp); 307 if (*_buffer == NULL) 308 return B_NO_MEMORY; 309 310 return B_OK; 311 } 312 313 314 /*! Determines the port of the given \a address. 315 \return uint16 representing the port-nr 316 */ 317 static uint16 318 ipv4_get_port(const sockaddr *address) 319 { 320 if (address == NULL || address->sa_len == 0) 321 return 0; 322 323 return ((sockaddr_in *)address)->sin_port; 324 } 325 326 327 /*! Sets the port of the given \a address to \a port. 328 \return B_OK if the port has been set 329 \return B_BAD_VALUE if \a address is NULL or has not been initialized 330 */ 331 static status_t 332 ipv4_set_port(sockaddr *address, uint16 port) 333 { 334 if (address == NULL || address->sa_len == 0) 335 return B_BAD_VALUE; 336 337 ((sockaddr_in *)address)->sin_port = port; 338 return B_OK; 339 } 340 341 342 /*! Sets \a address to \a from. 343 \return B_OK if \a from has been copied into \a address 344 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 345 address given in from has not been initialized 346 \return B_MISMATCHED_VALUES if from is not of family AF_INET 347 */ 348 static status_t 349 ipv4_set_to(sockaddr *address, const sockaddr *from) 350 { 351 if (address == NULL || from == NULL || from->sa_len == 0) 352 return B_BAD_VALUE; 353 354 if (from->sa_family != AF_INET) 355 return B_MISMATCHED_VALUES; 356 357 memcpy(address, from, sizeof(sockaddr_in)); 358 address->sa_len = sizeof(sockaddr_in); 359 return B_OK; 360 } 361 362 363 /*! Updates missing parts in \a address with the values in \a from. 364 \return B_OK if \a address has been updated from \a from 365 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 366 address given in from has not been initialized 367 \return B_MISMATCHED_VALUES if from is not of family AF_INET 368 */ 369 static status_t 370 ipv4_update_to(sockaddr *_address, const sockaddr *_from) 371 { 372 sockaddr_in *address = (sockaddr_in *)_address; 373 const sockaddr_in *from = (const sockaddr_in *)_from; 374 375 if (address == NULL || from == NULL || from->sin_len == 0) 376 return B_BAD_VALUE; 377 378 if (from->sin_family != AF_INET) 379 return B_BAD_VALUE; 380 381 address->sin_family = AF_INET; 382 address->sin_len = sizeof(sockaddr_in); 383 384 if (address->sin_port == 0) 385 address->sin_port = from->sin_port; 386 387 if (address->sin_addr.s_addr == INADDR_ANY) 388 address->sin_addr.s_addr = from->sin_addr.s_addr; 389 390 return B_OK; 391 } 392 393 394 /*! Sets \a address to the empty address (0.0.0.0). 395 \return B_OK if \a address has been set 396 \return B_BAD_VALUE if \a address is NULL 397 */ 398 static status_t 399 ipv4_set_to_empty_address(sockaddr *address) 400 { 401 if (address == NULL) 402 return B_BAD_VALUE; 403 404 memset(address, 0, sizeof(sockaddr_in)); 405 address->sa_len = sizeof(sockaddr_in); 406 address->sa_family = AF_INET; 407 return B_OK; 408 } 409 410 411 static status_t 412 ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast, 413 const sockaddr *_address, const sockaddr *_mask) 414 { 415 sockaddr_in *defaultMask = (sockaddr_in *)_defaultMask; 416 sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast; 417 const sockaddr_in *address = (const sockaddr_in *)_address; 418 const sockaddr_in *mask = (const sockaddr_in *)_mask; 419 420 if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL)) 421 return B_BAD_VALUE; 422 423 in_addr_t net; 424 if (mask == NULL) { 425 // choose default netmask depending on the class of the address 426 net = ntohl(address->sin_addr.s_addr); 427 if (IN_CLASSA(net) || (net >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 428 // class A, or loopback 429 net = htonl(IN_CLASSA_NET); 430 } else if (IN_CLASSB(net)) { 431 // class B 432 net = htonl(IN_CLASSB_NET); 433 } else { 434 // class C and rest 435 net = htonl(IN_CLASSC_NET); 436 } 437 } else 438 net = mask->sin_addr.s_addr; 439 440 if (defaultMask != NULL) { 441 defaultMask->sin_len = sizeof(sockaddr_in); 442 defaultMask->sin_family = AF_INET; 443 defaultMask->sin_port = 0; 444 defaultMask->sin_addr.s_addr = net; 445 } 446 447 if (defaultBroadcast != NULL) { 448 defaultBroadcast->sin_len = sizeof(sockaddr_in); 449 defaultBroadcast->sin_family = AF_INET; 450 defaultBroadcast->sin_port = 0; 451 defaultBroadcast->sin_addr.s_addr = address->sin_addr.s_addr | ~net; 452 } 453 454 return B_OK; 455 } 456 457 458 /*! Computes a hash value of the given \a address. 459 \return uint32 representing the hash value 460 */ 461 static uint32 462 ipv4_hash_address(const struct sockaddr* _address, bool includePort) 463 { 464 const sockaddr_in* address = (const sockaddr_in*)_address; 465 if (address == NULL || address->sin_len == 0) 466 return 0; 467 468 if (includePort) 469 return address->sin_port ^ address->sin_addr.s_addr; 470 471 return address->sin_addr.s_addr; 472 } 473 474 475 /*! Computes a hash-value of the given addresses \a ourAddress 476 and \a peerAddress. 477 \return uint32 representing the hash-value 478 */ 479 static uint32 480 ipv4_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 481 { 482 const sockaddr_in *our = (const sockaddr_in *)ourAddress; 483 const sockaddr_in *peer = (const sockaddr_in *)peerAddress; 484 485 bool haveOur = our && our->sin_len != 0; 486 bool havePeer = peer && peer->sin_len != 0; 487 488 return 489 ((haveOur ? our->sin_port : 0) 490 | ((havePeer ? peer->sin_port : 0) << 16)) 491 ^ (haveOur ? our->sin_addr.s_addr : 0) 492 ^ (havePeer ? peer->sin_addr.s_addr : 0); 493 } 494 495 496 /*! Adds the given \a address to the IP-checksum \a checksum. 497 \return B_OK if \a address has been added to the checksum 498 \return B_BAD_VALUE if either \a address or \a checksum is NULL or if 499 the given address is not initialized 500 */ 501 static status_t 502 ipv4_checksum_address(Checksum *checksum, const sockaddr *address) 503 { 504 if (checksum == NULL || address == NULL || address->sa_len == 0) 505 return B_BAD_VALUE; 506 507 (*checksum) << (uint32)((sockaddr_in *)address)->sin_addr.s_addr; 508 return B_OK; 509 } 510 511 512 static void 513 ipv4_get_loopback_address(sockaddr *_address) 514 { 515 sockaddr_in *address = (sockaddr_in *)_address; 516 memset(address, 0, sizeof(sockaddr_in)); 517 address->sin_len = sizeof(sockaddr_in); 518 address->sin_family = AF_INET; 519 address->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 520 } 521 522 523 net_address_module_info gIPv4AddressModule = { 524 { 525 NULL, 526 0, 527 NULL 528 }, 529 NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS, 530 ipv4_copy_address, 531 ipv4_mask_address, 532 ipv4_equal_addresses, 533 ipv4_equal_ports, 534 ipv4_equal_addresses_and_ports, 535 ipv4_equal_masked_addresses, 536 ipv4_is_empty_address, 537 ipv4_is_same_family, 538 ipv4_first_mask_bit, 539 ipv4_check_mask, 540 ipv4_print_address, 541 ipv4_print_address_buffer, 542 ipv4_get_port, 543 ipv4_set_port, 544 ipv4_set_to, 545 ipv4_set_to_empty_address, 546 ipv4_set_to_defaults, 547 ipv4_update_to, 548 ipv4_hash_address, 549 ipv4_hash_address_pair, 550 ipv4_checksum_address, 551 ipv4_get_loopback_address 552 }; 553