1/*
2 * Copyright 2006-2024, 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
25static status_t
26l2cap_copy_address(const sockaddr *from, sockaddr **to,
27	bool replaceWithZeros = false, const sockaddr *mask = NULL)
28{
29	if (replaceWithZeros) {
30		*to = (sockaddr *)malloc(sizeof(sockaddr_in));
31		if (*to == NULL)
32			return B_NO_MEMORY;
33
34		memset(*to, 0, sizeof(sockaddr_l2cap));
35		(*to)->sa_family = AF_BLUETOOTH;
36		(*to)->sa_len = sizeof(sockaddr_l2cap);
37	} else {
38		if (from == NULL)
39			return B_OK;
40		if (from->sa_family != AF_BLUETOOTH)
41			return B_MISMATCHED_VALUES;
42
43		*to = (sockaddr *)malloc(sizeof(sockaddr_in));
44		if (*to == NULL)
45			return B_NO_MEMORY;
46
47		memcpy(*to, from, sizeof(sockaddr_l2cap));
48
49	}
50	return B_OK;
51}
52
53
54static bool
55l2cap_is_empty_address(const sockaddr *address, bool checkPort)
56{
57	if (address == NULL || address->sa_len == 0
58		|| address->sa_family == AF_UNSPEC)
59		return true;
60
61	return ((bdaddrUtils::Compare(
62		((const sockaddr_l2cap *)address)->l2cap_bdaddr, BDADDR_NULL))
63		&& (!checkPort || ((sockaddr_l2cap *)address)->l2cap_psm == 0));
64}
65
66
67static bool
68l2cap_is_same_family(const sockaddr *address)
69{
70	if (address == NULL)
71		return false;
72
73	return address->sa_family == AF_BLUETOOTH;
74}
75
76
77static bool
78l2cap_equal_addresses(const sockaddr *a, const sockaddr *b)
79{
80	if (a == NULL && b == NULL)
81		return true;
82	if (a != NULL && b == NULL)
83		return l2cap_is_empty_address(a, false);
84	if (a == NULL && b != NULL)
85		return l2cap_is_empty_address(b, false);
86
87	return bdaddrUtils::Compare(((const sockaddr_l2cap*)a)->l2cap_bdaddr,
88		((sockaddr_l2cap*)b)->l2cap_bdaddr);
89}
90
91
92static bool
93l2cap_equal_ports(const sockaddr *a, const sockaddr *b)
94{
95	uint16 portA = a ? ((sockaddr_l2cap *)a)->l2cap_psm : 0;
96	uint16 portB = b ? ((sockaddr_l2cap *)b)->l2cap_psm : 0;
97	return portA == portB;
98}
99
100
101static bool
102l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
103{
104	if (a == NULL && b == NULL)
105		return true;
106	if (a != NULL && b == NULL)
107		return l2cap_is_empty_address(a, true);
108	if (a == NULL && b != NULL)
109		return l2cap_is_empty_address(b, true);
110
111	return (bdaddrUtils::Compare(((const sockaddr_l2cap *)a)->l2cap_bdaddr,
112		((const sockaddr_l2cap *)b)->l2cap_bdaddr))
113		&& ((sockaddr_l2cap *)a)->l2cap_psm == ((sockaddr_l2cap *)b)->l2cap_psm;
114}
115
116
117static bool
118l2cap_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
119	const sockaddr *mask)
120{
121	// no masks
122	return l2cap_equal_addresses(a, b);
123}
124
125
126static int32
127l2cap_first_mask_bit(const sockaddr *_mask)
128{
129	return 0;
130}
131
132
133static bool
134l2cap_check_mask(const sockaddr *_mask)
135{
136	return false;
137}
138
139
140static status_t
141l2cap_print_address_buffer(const sockaddr *_address, char *buffer,
142	size_t bufferSize, bool printPort)
143{
144	if (buffer == NULL)
145		return B_BAD_VALUE;
146
147	const sockaddr_l2cap *address = (const sockaddr_l2cap *)_address;
148	if (address == NULL) {
149		strlcpy(buffer, "<none>", bufferSize);
150	} else {
151		bdaddr_t addr = address->l2cap_bdaddr;
152		if (printPort) {
153			snprintf(buffer, bufferSize,
154				"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X|%u", addr.b[0],
155				addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5],
156				address->l2cap_psm);
157		} else {
158			snprintf(buffer, bufferSize,
159				"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",addr.b[0],
160				addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5]);
161		}
162	}
163
164	return B_OK;
165}
166
167
168static status_t
169l2cap_print_address(const sockaddr *_address, char **_buffer, bool printPort)
170{
171	if (_buffer == NULL)
172		return B_BAD_VALUE;
173
174	char tmp[32];
175	l2cap_print_address_buffer(_address, tmp, sizeof(tmp), printPort);
176
177	*_buffer = strdup(tmp);
178	if (*_buffer == NULL)
179		return B_NO_MEMORY;
180
181	return B_OK;
182}
183
184
185static uint16
186l2cap_get_port(const sockaddr *address)
187{
188	if (address == NULL)
189		return 0;
190
191	return ((sockaddr_l2cap *)address)->l2cap_psm;
192}
193
194
195static status_t
196l2cap_set_port(sockaddr *address, uint16 port)
197{
198	if (address == NULL)
199		return B_BAD_VALUE;
200
201	((sockaddr_l2cap *)address)->l2cap_psm = port;
202	return B_OK;
203}
204
205
206static status_t
207l2cap_set_to(sockaddr *address, const sockaddr *from)
208{
209	if (address == NULL || from == NULL)
210		return B_BAD_VALUE;
211
212	if (from->sa_family != AF_BLUETOOTH)
213		return B_MISMATCHED_VALUES;
214
215	memcpy(address, from, sizeof(sockaddr_l2cap));
216	return B_OK;
217}
218
219
220static status_t
221l2cap_mask_address(const sockaddr *address, const sockaddr *mask,
222	sockaddr *result)
223{
224	// no masks
225	return l2cap_set_to(result, address);
226}
227
228
229static status_t
230l2cap_update_to(sockaddr *_address, const sockaddr *_from)
231{
232	sockaddr_l2cap *address = (sockaddr_l2cap *)_address;
233	const sockaddr_l2cap *from = (const sockaddr_l2cap *)_from;
234
235	if (address == NULL || from == NULL)
236		return B_BAD_VALUE;
237
238	if (from->l2cap_family != AF_BLUETOOTH)
239		return B_BAD_VALUE;
240
241	address->l2cap_family = AF_BLUETOOTH;
242	address->l2cap_len = sizeof(sockaddr_l2cap);
243
244	if (bdaddrUtils::Compare(address->l2cap_bdaddr, BDADDR_NULL))
245		address->l2cap_bdaddr = from->l2cap_bdaddr;
246
247	if (address->l2cap_psm == 0)
248		address->l2cap_psm = from->l2cap_psm;
249
250	return B_OK;
251}
252
253
254static status_t
255l2cap_set_to_empty_address(sockaddr *address)
256{
257	if (address == NULL)
258		return B_BAD_VALUE;
259
260	memset(address, 0, sizeof(sockaddr_l2cap));
261	address->sa_len = sizeof(sockaddr_l2cap);
262	address->sa_family = AF_BLUETOOTH;
263	return B_OK;
264}
265
266
267static status_t
268l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
269	const sockaddr *_address, const sockaddr *_mask)
270{
271	if (_address == NULL)
272		return B_BAD_VALUE;
273
274	status_t error = B_OK;
275	if (_defaultMask != NULL)
276		error = l2cap_set_to_empty_address(_defaultMask);
277	if (error == B_OK && _defaultBroadcast != NULL)
278		error = l2cap_set_to_empty_address(_defaultBroadcast);
279
280	return error;
281}
282
283
284static uint32
285l2cap_hash_address(const struct sockaddr* _address, bool includePort)
286{
287	const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
288	if (address == NULL || address->l2cap_len == 0)
289		return 0;
290
291	uint32 hash = 0;
292	for (size_t i = 0; i < sizeof(address->l2cap_bdaddr.b); i++)
293		hash += address->l2cap_bdaddr.b[i] << (i * 2);
294
295	if (includePort)
296		hash += address->l2cap_psm;
297	return hash;
298}
299
300
301static uint32
302l2cap_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
303{
304	return l2cap_hash_address(ourAddress, true) * 17
305		+ l2cap_hash_address(peerAddress, true);
306}
307
308
309static status_t
310l2cap_checksum_address(struct Checksum *checksum, const sockaddr *address)
311{
312	if (checksum == NULL || address == NULL)
313		return B_BAD_VALUE;
314
315	for (uint i = 0; i < sizeof(bdaddr_t); i++)
316		(*checksum) << ((sockaddr_l2cap*)address)->l2cap_bdaddr.b[i];
317
318	return B_OK;
319}
320
321
322net_address_module_info gL2capAddressModule = {
323	{
324		NULL,
325		0,
326		NULL
327	},
328	NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
329	l2cap_copy_address,
330	l2cap_mask_address,
331	l2cap_equal_addresses,
332	l2cap_equal_ports,
333	l2cap_equal_addresses_and_ports,
334	l2cap_equal_masked_addresses,
335	l2cap_is_empty_address,
336	l2cap_is_same_family,
337	l2cap_first_mask_bit,
338	l2cap_check_mask,
339	l2cap_print_address,
340	l2cap_print_address_buffer,
341	l2cap_get_port,
342	l2cap_set_port,
343	l2cap_set_to,
344	l2cap_set_to_empty_address,
345	l2cap_set_to_defaults,
346	l2cap_update_to,
347	l2cap_hash_address,
348	l2cap_hash_address_pair,
349	l2cap_checksum_address,
350	NULL	// get_loopback_address
351};
352