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