xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/l2cap_address.cpp (revision 9f3bdf3d039430b5172c424def20ce5d9f7367d4)
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 
25 static status_t
26 l2cap_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 
54 static bool
55 l2cap_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 
67 static bool
68 l2cap_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 
77 static bool
78 l2cap_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 
92 static bool
93 l2cap_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 
101 static bool
102 l2cap_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 
117 static bool
118 l2cap_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 
126 static int32
127 l2cap_first_mask_bit(const sockaddr *_mask)
128 {
129 	return 0;
130 }
131 
132 
133 static bool
134 l2cap_check_mask(const sockaddr *_mask)
135 {
136 	return false;
137 }
138 
139 
140 static status_t
141 l2cap_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 
168 static status_t
169 l2cap_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 
185 static uint16
186 l2cap_get_port(const sockaddr *address)
187 {
188 	if (address == NULL)
189 		return 0;
190 
191 	return ((sockaddr_l2cap *)address)->l2cap_psm;
192 }
193 
194 
195 static status_t
196 l2cap_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 
206 static status_t
207 l2cap_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 
220 static status_t
221 l2cap_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 
229 static status_t
230 l2cap_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 
254 static status_t
255 l2cap_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 
267 static status_t
268 l2cap_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 
284 static uint32
285 l2cap_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 
301 static uint32
302 l2cap_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 
309 static status_t
310 l2cap_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 
322 net_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