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