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
ipv4_copy_address(const sockaddr * from,sockaddr ** to,bool replaceWithZeros=false,const sockaddr * mask=NULL)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
ipv4_mask_address(const sockaddr * address,const sockaddr * mask,sockaddr * result)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
ipv4_is_empty_address(const sockaddr * address,bool checkPort)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
ipv4_is_same_family(const sockaddr * address)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
ipv4_equal_addresses(const sockaddr * a,const sockaddr * b)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
ipv4_equal_ports(const sockaddr * a,const sockaddr * b)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
ipv4_equal_addresses_and_ports(const sockaddr * a,const sockaddr * b)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
ipv4_equal_masked_addresses(const sockaddr * a,const sockaddr * b,const sockaddr * mask)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
ipv4_first_mask_bit(const sockaddr * _mask)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
ipv4_check_mask(const sockaddr * _mask)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
ipv4_print_address_buffer(const sockaddr * _address,char * buffer,size_t bufferSize,bool printPort)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
ipv4_print_address(const sockaddr * _address,char ** _buffer,bool printPort)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
ipv4_get_port(const sockaddr * address)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
ipv4_set_port(sockaddr * address,uint16 port)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
ipv4_set_to(sockaddr * address,const sockaddr * from)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
ipv4_update_to(sockaddr * _address,const sockaddr * _from)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
ipv4_set_to_empty_address(sockaddr * address)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
ipv4_set_to_defaults(sockaddr * _defaultMask,sockaddr * _defaultBroadcast,const sockaddr * _address,const sockaddr * _mask)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
ipv4_hash_address(const struct sockaddr * _address,bool includePort)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
ipv4_hash_address_pair(const sockaddr * ourAddress,const sockaddr * peerAddress)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
ipv4_checksum_address(Checksum * checksum,const sockaddr * address)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
ipv4_get_loopback_address(sockaddr * _address)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