1 /* 2 * Copyright 2006-2009, 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 return true; 105 106 return ((sockaddr_in *)address)->sin_addr.s_addr == 0 107 && (!checkPort || ((sockaddr_in *)address)->sin_port == 0); 108 } 109 110 111 /*! Compares the IP-addresses of the two given address structures \a a and \a b. 112 \return true if IP-addresses of \a a and \a b are equal, false if not 113 */ 114 static bool 115 ipv4_equal_addresses(const sockaddr *a, const sockaddr *b) 116 { 117 if (a == NULL && b == NULL) 118 return true; 119 if (a != NULL && b == NULL) 120 return ipv4_is_empty_address(a, false); 121 if (a == NULL && b != NULL) 122 return ipv4_is_empty_address(b, false); 123 124 return ((sockaddr_in *)a)->sin_addr.s_addr 125 == ((sockaddr_in *)b)->sin_addr.s_addr; 126 } 127 128 129 /*! Compares the ports of the two given address structures \a a and \a b. 130 \return true if ports of \a a and \a b are equal, false if not 131 */ 132 static bool 133 ipv4_equal_ports(const sockaddr *a, const sockaddr *b) 134 { 135 uint16 portA = a ? ((sockaddr_in *)a)->sin_port : 0; 136 uint16 portB = b ? ((sockaddr_in *)b)->sin_port : 0; 137 return portA == portB; 138 } 139 140 141 /*! Compares the IP-addresses and ports of the two given address structures 142 \a a and \a b. 143 \return true if IP-addresses and ports of \a a and \a b are equal, false if 144 not 145 */ 146 static bool 147 ipv4_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b) 148 { 149 if (a == NULL && b == NULL) 150 return true; 151 if (a != NULL && b == NULL) 152 return ipv4_is_empty_address(a, true); 153 if (a == NULL && b != NULL) 154 return ipv4_is_empty_address(b, true); 155 156 return ((sockaddr_in *)a)->sin_addr.s_addr 157 == ((sockaddr_in *)b)->sin_addr.s_addr 158 && ((sockaddr_in *)a)->sin_port == ((sockaddr_in *)b)->sin_port; 159 } 160 161 162 /*! Applies the given \a mask two \a a and \a b and then checks whether 163 the masked addresses match. 164 \return true if \a a matches \a b after masking both, false if not 165 */ 166 static bool 167 ipv4_equal_masked_addresses(const sockaddr *a, const sockaddr *b, 168 const sockaddr *mask) 169 { 170 if (a == NULL && b == NULL) 171 return true; 172 173 sockaddr emptyAddr; 174 if (a == NULL || b == NULL) { 175 memset(&emptyAddr, 0, sizeof(sockaddr_in)); 176 if (a == NULL) 177 a = &emptyAddr; 178 else if (b == NULL) 179 b = &emptyAddr; 180 } 181 182 uint32 aValue = ((sockaddr_in *)a)->sin_addr.s_addr; 183 uint32 bValue = ((sockaddr_in *)b)->sin_addr.s_addr; 184 185 if (!mask) 186 return aValue == bValue; 187 188 uint32 maskValue = ((sockaddr_in *)mask)->sin_addr.s_addr; 189 return (aValue & maskValue) == (bValue & maskValue); 190 } 191 192 193 /*! Routing utility function: determines the least significant bit that is set 194 in the given \a mask. 195 \return the number of the first bit that is set (0-32, where 32 means 196 that there's no bit set in the mask). 197 */ 198 static int32 199 ipv4_first_mask_bit(const sockaddr *_mask) 200 { 201 if (_mask == NULL) 202 return 0; 203 204 uint32 mask = ntohl(((const sockaddr_in *)_mask)->sin_addr.s_addr); 205 206 // TODO: this can be optimized, there are also some nice assembler mnemonics 207 // for this 208 int8 bit = 0; 209 for (uint32 bitMask = 1; bit < 32; bitMask <<= 1, bit++) { 210 if (mask & bitMask) 211 return bit; 212 } 213 214 return 32; 215 } 216 217 218 /*! Routing utility function: checks the given \a mask for correctness (which 219 means that (starting with LSB) consists zero or more unset bits, followed 220 by bits that are all set). 221 \return true if \a mask is ok, false if not 222 */ 223 static bool 224 ipv4_check_mask(const sockaddr *_mask) 225 { 226 if (_mask == NULL) 227 return true; 228 229 uint32 mask = ntohl(((const sockaddr_in *)_mask)->sin_addr.s_addr); 230 231 // A mask (from LSB) starts with zeros, after the first one, only ones 232 // are allowed: 233 bool zero = true; 234 int8 bit = 0; 235 for (uint32 bitMask = 1; bit < 32; bitMask <<= 1, bit++) { 236 if (mask & bitMask) { 237 if (zero) 238 zero = false; 239 } else if (!zero) 240 return false; 241 } 242 return true; 243 } 244 245 246 /*! Creates a buffer for the given \a address and prints the address into 247 it (hexadecimal representation in host byte order or '<none>'). 248 If \a printPort is set, the port is printed, too. 249 \return B_OK if the address could be printed, \a buffer will point to 250 the resulting string 251 \return B_BAD_VALUE if no buffer has been given 252 \return B_NO_MEMORY if the buffer could not be allocated 253 */ 254 static status_t 255 ipv4_print_address_buffer(const sockaddr *_address, char *buffer, 256 size_t bufferSize, bool printPort) 257 { 258 const sockaddr_in *address = (const sockaddr_in *)_address; 259 260 if (buffer == NULL) 261 return B_BAD_VALUE; 262 263 if (address == NULL) 264 strlcpy(buffer, "<none>", bufferSize); 265 else { 266 unsigned int addr = ntohl(address->sin_addr.s_addr); 267 268 if (printPort) { 269 snprintf(buffer, bufferSize, "%u.%u.%u.%u:%u", 270 (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, 271 addr & 0xff, ntohs(address->sin_port)); 272 } else { 273 snprintf(buffer, bufferSize, "%u.%u.%u.%u", (addr >> 24) & 0xff, 274 (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); 275 } 276 } 277 278 return B_OK; 279 } 280 281 282 static status_t 283 ipv4_print_address(const sockaddr *_address, char **_buffer, bool printPort) 284 { 285 if (_buffer == NULL) 286 return B_BAD_VALUE; 287 288 char tmp[64]; 289 ipv4_print_address_buffer(_address, tmp, sizeof(tmp), printPort); 290 291 *_buffer = strdup(tmp); 292 if (*_buffer == NULL) 293 return B_NO_MEMORY; 294 295 return B_OK; 296 } 297 298 299 /*! Determines the port of the given \a address. 300 \return uint16 representing the port-nr 301 */ 302 static uint16 303 ipv4_get_port(const sockaddr *address) 304 { 305 if (address == NULL || address->sa_len == 0) 306 return 0; 307 308 return ((sockaddr_in *)address)->sin_port; 309 } 310 311 312 /*! Sets the port of the given \a address to \a port. 313 \return B_OK if the port has been set 314 \return B_BAD_VALUE if \a address is NULL or has not been initialized 315 */ 316 static status_t 317 ipv4_set_port(sockaddr *address, uint16 port) 318 { 319 if (address == NULL || address->sa_len == 0) 320 return B_BAD_VALUE; 321 322 ((sockaddr_in *)address)->sin_port = port; 323 return B_OK; 324 } 325 326 327 /*! Sets \a address to \a from. 328 \return B_OK if \a from has been copied into \a address 329 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 330 address given in from has not been initialized 331 \return B_MISMATCHED_VALUES if from is not of family AF_INET 332 */ 333 static status_t 334 ipv4_set_to(sockaddr *address, const sockaddr *from) 335 { 336 if (address == NULL || from == NULL || from->sa_len == 0) 337 return B_BAD_VALUE; 338 339 if (from->sa_family != AF_INET) 340 return B_MISMATCHED_VALUES; 341 342 memcpy(address, from, sizeof(sockaddr_in)); 343 address->sa_len = sizeof(sockaddr_in); 344 return B_OK; 345 } 346 347 348 /*! Updates missing parts in \a address with the values in \a from. 349 \return B_OK if \a address has been updated from \a from 350 \return B_BAD_VALUE if either \a address or \a from is NULL or if the 351 address given in from has not been initialized 352 \return B_MISMATCHED_VALUES if from is not of family AF_INET 353 */ 354 static status_t 355 ipv4_update_to(sockaddr *_address, const sockaddr *_from) 356 { 357 sockaddr_in *address = (sockaddr_in *)_address; 358 const sockaddr_in *from = (const sockaddr_in *)_from; 359 360 if (address == NULL || from == NULL || from->sin_len == 0) 361 return B_BAD_VALUE; 362 363 if (from->sin_family != AF_INET) 364 return B_BAD_VALUE; 365 366 address->sin_family = AF_INET; 367 address->sin_len = sizeof(sockaddr_in); 368 369 if (address->sin_port == 0) 370 address->sin_port = from->sin_port; 371 372 if (address->sin_addr.s_addr == INADDR_ANY) 373 address->sin_addr.s_addr = from->sin_addr.s_addr; 374 375 return B_OK; 376 } 377 378 379 /*! Sets \a address to the empty address (0.0.0.0). 380 \return B_OK if \a address has been set 381 \return B_BAD_VALUE if \a address is NULL 382 */ 383 static status_t 384 ipv4_set_to_empty_address(sockaddr *address) 385 { 386 if (address == NULL) 387 return B_BAD_VALUE; 388 389 memset(address, 0, sizeof(sockaddr_in)); 390 address->sa_len = sizeof(sockaddr_in); 391 address->sa_family = AF_INET; 392 return B_OK; 393 } 394 395 396 static status_t 397 ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast, 398 sockaddr *_address, sockaddr *_mask) 399 { 400 sockaddr_in *defaultMask = (sockaddr_in *)_defaultMask; 401 sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast; 402 sockaddr_in *address = (sockaddr_in *)_address; 403 sockaddr_in *mask = (sockaddr_in *)_mask; 404 405 if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL)) 406 return B_BAD_VALUE; 407 408 in_addr_t net; 409 if (mask == NULL) { 410 // choose default netmask depending on the class of the address 411 net = ntohl(address->sin_addr.s_addr); 412 if (IN_CLASSA(net) || (net >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 413 // class A, or loopback 414 net = htonl(IN_CLASSA_NET); 415 } else if (IN_CLASSB(net)) { 416 // class B 417 net = htonl(IN_CLASSB_NET); 418 } else { 419 // class C and rest 420 net = htonl(IN_CLASSC_NET); 421 } 422 } else 423 net = mask->sin_addr.s_addr; 424 425 if (defaultMask != NULL) { 426 defaultMask->sin_len = sizeof(sockaddr_in); 427 defaultMask->sin_family = AF_INET; 428 defaultMask->sin_port = 0; 429 defaultMask->sin_addr.s_addr = net; 430 } 431 432 if (defaultBroadcast != NULL) { 433 defaultBroadcast->sin_len = sizeof(sockaddr_in); 434 defaultBroadcast->sin_family = AF_INET; 435 defaultBroadcast->sin_port = 0; 436 defaultBroadcast->sin_addr.s_addr = (address->sin_addr.s_addr & net) 437 | ~net; 438 } 439 440 return B_OK; 441 } 442 443 444 /*! Computes a hash-value of the given addresses \a ourAddress 445 and \a peerAddress. 446 \return uint32 representing the hash-value 447 */ 448 static uint32 449 ipv4_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 450 { 451 const sockaddr_in *our = (const sockaddr_in *)ourAddress; 452 const sockaddr_in *peer = (const sockaddr_in *)peerAddress; 453 454 bool haveOur = our && our->sin_len != 0; 455 bool havePeer = peer && peer->sin_len != 0; 456 457 return 458 ((haveOur ? our->sin_port : 0) 459 | ((havePeer ? peer->sin_port : 0) << 16)) 460 ^ (haveOur ? our->sin_addr.s_addr : 0) 461 ^ (havePeer ? peer->sin_addr.s_addr : 0); 462 } 463 464 465 /*! Adds the given \a address to the IP-checksum \a checksum. 466 \return B_OK if \a address has been added to the checksum 467 \return B_BAD_VALUE if either \a address or \a checksum is NULL or if 468 the given address is not initialized 469 */ 470 static status_t 471 ipv4_checksum_address(struct Checksum *checksum, const sockaddr *address) 472 { 473 if (checksum == NULL || address == NULL || address->sa_len == 0) 474 return B_BAD_VALUE; 475 476 (*checksum) << (uint32)((sockaddr_in *)address)->sin_addr.s_addr; 477 return B_OK; 478 } 479 480 481 net_address_module_info gIPv4AddressModule = { 482 { 483 NULL, 484 0, 485 NULL 486 }, 487 ipv4_copy_address, 488 ipv4_mask_address, 489 ipv4_equal_addresses, 490 ipv4_equal_ports, 491 ipv4_equal_addresses_and_ports, 492 ipv4_equal_masked_addresses, 493 ipv4_is_empty_address, 494 ipv4_first_mask_bit, 495 ipv4_check_mask, 496 ipv4_print_address, 497 ipv4_print_address_buffer, 498 ipv4_get_port, 499 ipv4_set_port, 500 ipv4_set_to, 501 ipv4_set_to_empty_address, 502 ipv4_set_to_defaults, 503 ipv4_update_to, 504 ipv4_hash_address_pair, 505 ipv4_checksum_address, 506 NULL // ipv4_matches_broadcast_address, 507 }; 508