xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/l2cap_address.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
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 */
40 static status_t
41 l2cap_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 */
74 static status_t
75 l2cap_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 */
90 static bool
91 l2cap_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 */
107 static bool
108 l2cap_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 */
120 static bool
121 l2cap_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 */
138 static bool
139 l2cap_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 */
152 static bool
153 l2cap_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 */
172 static bool
173 l2cap_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 */
188 static int32
189 l2cap_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 */
203 static bool
204 l2cap_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 */
219 static status_t
220 l2cap_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 
249 static status_t
250 l2cap_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 */
269 static uint16
270 l2cap_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 */
283 static status_t
284 l2cap_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 */
299 static status_t
300 l2cap_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 
314 static status_t
315 l2cap_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 */
343 static status_t
344 l2cap_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 
356 static status_t
357 l2cap_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 */
368 static uint32
369 l2cap_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 */
383 static uint32
384 l2cap_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 */
399 static status_t
400 l2cap_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 
412 net_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