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*/
36static status_t
37ipv4_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*/
77static status_t
78ipv4_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*/
100static bool
101ipv4_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*/
116static bool
117ipv4_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*/
129static bool
130ipv4_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*/
147static bool
148ipv4_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*/
161static bool
162ipv4_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*/
181static bool
182ipv4_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*/
213static int32
214ipv4_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*/
238static bool
239ipv4_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*/
269static status_t
270ipv4_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
297static status_t
298ipv4_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*/
317static uint16
318ipv4_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*/
331static status_t
332ipv4_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*/
348static status_t
349ipv4_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*/
369static status_t
370ipv4_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*/
398static status_t
399ipv4_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
411static status_t
412ipv4_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*/
461static uint32
462ipv4_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*/
479static uint32
480ipv4_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*/
501static status_t
502ipv4_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
512static void
513ipv4_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
523net_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