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