1 /* 2 * Copyright 2006, 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(const sockaddr *address, char **_buffer, bool printPort) 255 { 256 if (_buffer == NULL) 257 return B_BAD_VALUE; 258 259 int bufLen = printPort ? 15 : 9; 260 char *buffer = (char *)malloc(bufLen); 261 if (buffer == NULL) 262 return B_NO_MEMORY; 263 264 if (address == NULL) 265 strcpy(buffer, "<none>"); 266 else if (printPort) { 267 sprintf(buffer, "%08lx:%u", ntohl(((sockaddr_in *)address)->sin_addr.s_addr), 268 ntohs(((sockaddr_in *)address)->sin_port)); 269 } else 270 sprintf(buffer, "%08lx", ntohl(((sockaddr_in *)address)->sin_addr.s_addr)); 271 *_buffer = buffer; 272 return B_OK; 273 } 274 275 276 /*! 277 Determines the port of the given \a address. 278 \return uint16 representing the port-nr 279 */ 280 static uint16 281 ipv4_get_port(const sockaddr *address) 282 { 283 if (address == NULL) 284 return 0; 285 286 return ((sockaddr_in *)address)->sin_port; 287 } 288 289 290 /*! 291 Sets the port of the given \a address to \a port. 292 \return B_OK if the port has been set 293 \return B_BAD_VALUE if \a address is NULL 294 */ 295 static status_t 296 ipv4_set_port(sockaddr *address, uint16 port) 297 { 298 if (address == NULL) 299 return B_BAD_VALUE; 300 301 ((sockaddr_in *)address)->sin_port = port; 302 return B_OK; 303 } 304 305 306 /*! 307 Sets \a address to \a from. 308 \return B_OK if \a from has been copied into \a address 309 \return B_BAD_VALUE if either \a address or \a from is NULL 310 \return B_MISMATCHED_VALUES if from is not of family AF_INET 311 */ 312 static status_t 313 ipv4_set_to(sockaddr *address, const sockaddr *from) 314 { 315 if (address == NULL || from == NULL) 316 return B_BAD_VALUE; 317 318 if (from->sa_family != AF_INET) 319 return B_MISMATCHED_VALUES; 320 321 memcpy(address, from, sizeof(sockaddr_in)); 322 address->sa_len = sizeof(sockaddr_in); 323 return B_OK; 324 } 325 326 327 /*! 328 Sets \a address to the empty address (0.0.0.0). 329 \return B_OK if \a address has been set 330 \return B_BAD_VALUE if \a address is NULL 331 */ 332 static status_t 333 ipv4_set_to_empty_address(sockaddr *address) 334 { 335 if (address == NULL) 336 return B_BAD_VALUE; 337 338 memset(address, 0, sizeof(sockaddr_in)); 339 address->sa_len = sizeof(sockaddr_in); 340 address->sa_family = AF_INET; 341 return B_OK; 342 } 343 344 345 /*! 346 Computes a hash-value of the given addresses \a ourAddress 347 and \a peerAddress. 348 \return uint32 representing the hash-value 349 */ 350 static uint32 351 ipv4_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 352 { 353 int32 hash = (((sockaddr_in *)ourAddress)->sin_port 354 | ((sockaddr_in *)peerAddress)->sin_port << 16) 355 ^ ((sockaddr_in *)ourAddress)->sin_addr.s_addr 356 ^ ((sockaddr_in *)peerAddress)->sin_addr.s_addr; 357 return hash; 358 } 359 360 361 /*! 362 Adds the given \a address to the IP-checksum \a checksum. 363 \return B_OK if \a address has been added to the checksum 364 \return B_BAD_VALUE if either \a address or \a checksum is NULL 365 */ 366 static status_t 367 ipv4_checksum_address(struct Checksum *checksum, const sockaddr *address) 368 { 369 if (checksum == NULL || address == NULL) 370 return B_BAD_VALUE; 371 372 (*checksum) << (uint32)((sockaddr_in *)address)->sin_addr.s_addr; 373 return B_OK; 374 } 375 376 377 net_address_module_info gIPv4AddressModule = { 378 { 379 NULL, 380 0, 381 NULL 382 }, 383 ipv4_copy_address, 384 ipv4_mask_address, 385 ipv4_equal_addresses, 386 ipv4_equal_ports, 387 ipv4_equal_addresses_and_ports, 388 ipv4_equal_masked_addresses, 389 ipv4_is_empty_address, 390 ipv4_first_mask_bit, 391 ipv4_check_mask, 392 ipv4_print_address, 393 ipv4_get_port, 394 ipv4_set_port, 395 ipv4_set_to, 396 ipv4_set_to_empty_address, 397 ipv4_hash_address_pair, 398 ipv4_checksum_address, 399 NULL // ipv4_matches_broadcast_address, 400 }; 401