1/*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
7 */
8
9
10#include <net_datalink.h>
11
12#include <ByteOrder.h>
13#include <KernelExport.h>
14
15#include <NetUtilities.h>
16
17#include <memory.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#include <bluetooth/bdaddrUtils.h>
22#include <bluetooth/L2CAP/btL2CAP.h>
23
24
25#define L2CAP_CHECKSUM(address) \
26	(address.b[0] + address.b[1] + address.b[2] + address.b[3] \
27		+ address.b[4] + address.b[5])
28
29
30/*!	Routing utility function: copies address \a from into a new address
31	that is put into \a to.
32	If \a replaceWithZeros is set \a from will be replaced by an empty
33	address.
34	If a \a mask is given it is applied to \a from (such that \a to is the
35	result of \a from & \a mask).
36	\return B_OK if the address could be copied
37	\return B_NO_MEMORY if the new address could not be allocated
38	\return B_MISMATCHED_VALUES if \a address does not match family AF_BLUETOOTH
39*/
40static status_t
41l2cap_copy_address(const sockaddr *from, sockaddr **to,
42	bool replaceWithZeros = false, const sockaddr *mask = NULL)
43{
44	if (replaceWithZeros) {
45		*to = (sockaddr *)malloc(sizeof(sockaddr_in));
46		if (*to == NULL)
47			return B_NO_MEMORY;
48
49		memset(*to, 0, sizeof(sockaddr_l2cap));
50		(*to)->sa_family = AF_BLUETOOTH;
51		(*to)->sa_len = sizeof(sockaddr_l2cap);
52	} else {
53		if (from == NULL)
54			return B_OK;
55		if (from->sa_family != AF_BLUETOOTH)
56			return B_MISMATCHED_VALUES;
57
58		*to = (sockaddr *)malloc(sizeof(sockaddr_in));
59		if (*to == NULL)
60			return B_NO_MEMORY;
61
62		memcpy(*to, from, sizeof(sockaddr_l2cap));
63
64	}
65	return B_OK;
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*/
74static status_t
75l2cap_mask_address(const sockaddr *address, const sockaddr *mask,
76	sockaddr *result)
77{
78	if (address == NULL || result == NULL)
79		return B_BAD_VALUE;
80
81	return B_OK;
82}
83
84
85/*!	Checks if the given \a address is the empty address. By default, the port
86	is checked, too, but you can avoid that by passing \a checkPort = false.
87	\return true if \a address is NULL, uninitialized or the empty address,
88		false if not
89*/
90static bool
91l2cap_is_empty_address(const sockaddr *address, bool checkPort)
92{
93	if (address == NULL || address->sa_len == 0
94		|| address->sa_family == AF_UNSPEC)
95		return true;
96
97	return ((bdaddrUtils::Compare(
98		((const sockaddr_l2cap *)address)->l2cap_bdaddr, BDADDR_NULL)==0)
99		&& (!checkPort || ((sockaddr_l2cap *)address)->l2cap_psm == 0));
100}
101
102
103/*!	Checks if the given \a address is L2CAP address.
104	\return false if \a address is NULL, or with family different from
105		AF_BLUETOOTH true if it has AF_BLUETOOTH address family
106*/
107static bool
108l2cap_is_same_family(const sockaddr *address)
109{
110	if (address == NULL)
111		return false;
112
113	return address->sa_family == AF_BLUETOOTH;
114}
115
116
117/*!	Compares the IP-addresses of the two given address structures \a a and \a b.
118	\return true if IP-addresses of \a a and \a b are equal, false if not
119*/
120static bool
121l2cap_equal_addresses(const sockaddr *a, const sockaddr *b)
122{
123	if (a == NULL && b == NULL)
124		return true;
125	if (a != NULL && b == NULL)
126		return l2cap_is_empty_address(a, false);
127	if (a == NULL && b != NULL)
128		return l2cap_is_empty_address(b, false);
129
130	return bdaddrUtils::Compare(((const sockaddr_l2cap*)a)->l2cap_bdaddr,
131		((sockaddr_l2cap*)b)->l2cap_bdaddr);
132}
133
134
135/*!	Compares the ports of the two given address structures \a a and \a b.
136	\return true if ports of \a a and \a b are equal, false if not
137*/
138static bool
139l2cap_equal_ports(const sockaddr *a, const sockaddr *b)
140{
141	uint16 portA = a ? ((sockaddr_l2cap *)a)->l2cap_psm : 0;
142	uint16 portB = b ? ((sockaddr_l2cap *)b)->l2cap_psm : 0;
143	return portA == portB;
144}
145
146
147/*!	Compares the IP-addresses and ports of the two given address structures
148	\a a and \a b.
149	\return true if IP-addresses and ports of \a a and \a b are equal, false if
150		not.
151*/
152static bool
153l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
154{
155	if (a == NULL && b == NULL)
156		return true;
157	if (a != NULL && b == NULL)
158		return l2cap_is_empty_address(a, true);
159	if (a == NULL && b != NULL)
160		return l2cap_is_empty_address(b, true);
161
162	return (bdaddrUtils::Compare(((const sockaddr_l2cap *)a)->l2cap_bdaddr,
163		((const sockaddr_l2cap *)b)->l2cap_bdaddr))
164		&& ((sockaddr_l2cap *)a)->l2cap_psm == ((sockaddr_l2cap *)b)->l2cap_psm;
165}
166
167
168/*!	Applies the given \a mask two \a a and \a b and then checks whether
169	the masked addresses match.
170	\return true if \a a matches \a b after masking both, false if not
171*/
172static bool
173l2cap_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
174	const sockaddr *mask)
175{
176	if (a == NULL && b == NULL)
177		return true;
178
179    return false;
180}
181
182
183/*!	Routing utility function: determines the least significant bit that is set
184	in the given \a mask.
185	\return the number of the first bit that is set (0-32, where 32 means
186		that there's no bit set in the mask).
187*/
188static int32
189l2cap_first_mask_bit(const sockaddr *_mask)
190{
191	if (_mask == NULL)
192		return 0;
193
194	return 0;
195}
196
197
198/*!	Routing utility function: checks the given \a mask for correctness (which
199	means that (starting with LSB) consists zero or more unset bits, followed
200	by bits that are all set).
201	\return true if \a mask is ok, false if not
202*/
203static bool
204l2cap_check_mask(const sockaddr *_mask)
205{
206
207	return true;
208}
209
210
211/*!	Creates a buffer for the given \a address and prints the address into
212	it (hexadecimal representation in host byte order or '<none>').
213	If \a printPort is set, the port is printed, too.
214	\return B_OK if the address could be printed, \a buffer will point to
215		the resulting string
216	\return B_BAD_VALUE if no buffer has been given
217	\return B_NO_MEMORY if the buffer could not be allocated
218*/
219static status_t
220l2cap_print_address_buffer(const sockaddr *_address, char *buffer,
221	size_t bufferSize, bool printPort)
222{
223	const sockaddr_l2cap *address = (const sockaddr_l2cap *)_address;
224
225	if (buffer == NULL)
226		return B_BAD_VALUE;
227
228	if (address == NULL)
229		strlcpy(buffer, "<none>", bufferSize);
230	else {
231		bdaddr_t addr = address->l2cap_bdaddr;
232		if (printPort) {
233			snprintf(buffer, bufferSize,
234				"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X|%u", addr.b[0],
235				addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5],
236				address->l2cap_psm);
237		}
238		else {
239			snprintf(buffer, bufferSize,
240				"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",addr.b[0],
241				addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5]);
242		}
243	}
244
245	return B_OK;
246}
247
248
249static status_t
250l2cap_print_address(const sockaddr *_address, char **_buffer, bool printPort)
251{
252	if (_buffer == NULL)
253		return B_BAD_VALUE;
254
255	char tmp[32];
256	l2cap_print_address_buffer(_address, tmp, sizeof(tmp), printPort);
257
258	*_buffer = strdup(tmp);
259	if (*_buffer == NULL)
260		return B_NO_MEMORY;
261
262	return B_OK;
263}
264
265
266/*!	Determines the port of the given \a address.
267	\return uint16 representing the port-nr
268*/
269static uint16
270l2cap_get_port(const sockaddr *address)
271{
272	if (address == NULL)
273		return 0;
274
275	return ((sockaddr_l2cap *)address)->l2cap_psm;
276}
277
278
279/*!	Sets the port of the given \a address to \a port.
280	\return B_OK if the port has been set
281	\return B_BAD_VALUE if \a address is NULL
282*/
283static status_t
284l2cap_set_port(sockaddr *address, uint16 port)
285{
286	if (address == NULL)
287		return B_BAD_VALUE;
288
289	((sockaddr_l2cap *)address)->l2cap_psm = port;
290	return B_OK;
291}
292
293
294/*!	Sets \a address to \a from.
295	\return B_OK if \a from has been copied into \a address
296	\return B_BAD_VALUE if either \a address or \a from is NULL
297	\return B_MISMATCHED_VALUES if from is not of family AF_BLUETOOTH
298*/
299static status_t
300l2cap_set_to(sockaddr *address, const sockaddr *from)
301{
302	if (address == NULL || from == NULL)
303		return B_BAD_VALUE;
304
305	if (from->sa_family != AF_BLUETOOTH)
306		return B_MISMATCHED_VALUES;
307
308	memcpy(address, from, sizeof(sockaddr_l2cap));
309	address->sa_len = sizeof(sockaddr_l2cap);
310	return B_OK;
311}
312
313
314static status_t
315l2cap_update_to(sockaddr *_address, const sockaddr *_from)
316{
317	sockaddr_l2cap *address = (sockaddr_l2cap *)_address;
318	const sockaddr_l2cap *from = (const sockaddr_l2cap *)_from;
319
320	if (address == NULL || from == NULL)
321		return B_BAD_VALUE;
322
323	if (from->l2cap_family != AF_BLUETOOTH)
324		return B_BAD_VALUE;
325
326	address->l2cap_family = AF_BLUETOOTH;
327	address->l2cap_len = sizeof(sockaddr_l2cap);
328
329	if (address->l2cap_psm == 0)
330		address->l2cap_psm = from->l2cap_psm;
331
332	if (bdaddrUtils::Compare(address->l2cap_bdaddr, BDADDR_BROADCAST))
333		address->l2cap_bdaddr = from->l2cap_bdaddr;
334
335	return B_OK;
336}
337
338
339/*!	Sets \a address to the empty address.
340	\return B_OK if \a address has been set
341	\return B_BAD_VALUE if \a address is NULL
342*/
343static status_t
344l2cap_set_to_empty_address(sockaddr *address)
345{
346	if (address == NULL)
347		return B_BAD_VALUE;
348
349	memset(address, 0, sizeof(sockaddr_l2cap));
350	address->sa_len = sizeof(sockaddr_l2cap);
351	address->sa_family = AF_BLUETOOTH;
352	return B_OK;
353}
354
355
356static status_t
357l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
358	const sockaddr *_address, const sockaddr *_mask)
359{
360	// TODO: not implemented
361	return B_ERROR;
362}
363
364
365/*!	Computes a hash value of the given \a address.
366	\return uint32 representing the hash value
367*/
368static uint32
369l2cap_hash_address(const struct sockaddr* _address, bool includePort)
370{
371	const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
372	if (address == NULL || address->l2cap_len == 0)
373		return 0;
374
375	return address->l2cap_psm ^ L2CAP_CHECKSUM(address->l2cap_bdaddr);
376}
377
378
379/*!	Computes a hash-value of the given addresses \a ourAddress
380	and \a peerAddress.
381	\return uint32 representing the hash-value
382*/
383static uint32
384l2cap_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
385{
386	const sockaddr_l2cap *our = (const sockaddr_l2cap *)ourAddress;
387	const sockaddr_l2cap *peer = (const sockaddr_l2cap *)peerAddress;
388
389	return ((our ? our->l2cap_psm : 0) | ((peer ? peer->l2cap_psm : 0) << 16))
390		^ (our ? L2CAP_CHECKSUM(our->l2cap_bdaddr) : 0)
391		^ (peer ? L2CAP_CHECKSUM(peer->l2cap_bdaddr) : 0);
392}
393
394
395/*!	Adds the given \a address to the IP-checksum \a checksum.
396	\return B_OK if \a address has been added to the checksum
397	\return B_BAD_VALUE if either \a address or \a checksum is NULL
398*/
399static status_t
400l2cap_checksum_address(struct Checksum *checksum, const sockaddr *address)
401{
402	if (checksum == NULL || address == NULL)
403		return B_BAD_VALUE;
404
405	for (uint i = 0; i < sizeof(bdaddr_t); i++)
406		(*checksum) << ((sockaddr_l2cap*)address)->l2cap_bdaddr.b[i];
407
408	return B_OK;
409}
410
411
412net_address_module_info gL2cap4AddressModule = {
413	{
414		NULL,
415		0,
416		NULL
417	},
418	NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
419	l2cap_copy_address,
420	l2cap_mask_address,
421	l2cap_equal_addresses,
422	l2cap_equal_ports,
423	l2cap_equal_addresses_and_ports,
424	l2cap_equal_masked_addresses,
425	l2cap_is_empty_address,
426	l2cap_is_same_family,
427	l2cap_first_mask_bit,
428	l2cap_check_mask,
429	l2cap_print_address,
430	l2cap_print_address_buffer,
431	l2cap_get_port,
432	l2cap_set_port,
433	l2cap_set_to,
434	l2cap_set_to_empty_address,
435	l2cap_set_to_defaults,
436	l2cap_update_to,
437	l2cap_hash_address,
438	l2cap_hash_address_pair,
439	l2cap_checksum_address,
440	NULL	// get_loopback_address
441};
442