xref: /freebsd/usr.sbin/bluetooth/sdpd/profile.c (revision 315ee00f)
1 /*
2  * profile.c
3  */
4 
5 /*-
6  * SPDX-License-Identifier: BSD-2-Clause
7  *
8  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: profile.c,v 1.6 2004/01/13 19:31:54 max Exp $
33  */
34 
35 #include <sys/queue.h>
36 #define L2CAP_SOCKET_CHECKED
37 #include <bluetooth.h>
38 #include <sdp.h>
39 #include <string.h>
40 #include "profile.h"
41 #include "provider.h"
42 
43 /*
44  * Lookup profile descriptor
45  */
46 
47 profile_p
48 profile_get_descriptor(uint16_t uuid)
49 {
50   	extern	profile_t	audio_sink_profile_descriptor;
51 	extern	profile_t	audio_source_profile_descriptor;
52 	extern	profile_t	dun_profile_descriptor;
53 	extern	profile_t	ftrn_profile_descriptor;
54 	extern	profile_t	irmc_profile_descriptor;
55 	extern	profile_t	irmc_command_profile_descriptor;
56 	extern	profile_t	lan_profile_descriptor;
57 	extern	profile_t	opush_profile_descriptor;
58 	extern	profile_t	sp_profile_descriptor;
59 	extern	profile_t	nap_profile_descriptor;
60 	extern	profile_t	gn_profile_descriptor;
61 	extern	profile_t	panu_profile_descriptor;
62 
63 	static const profile_p	profiles[] = {
64 		&audio_sink_profile_descriptor,
65 		&audio_source_profile_descriptor,
66 		&dun_profile_descriptor,
67 		&ftrn_profile_descriptor,
68 		&irmc_profile_descriptor,
69 		&irmc_command_profile_descriptor,
70 		&lan_profile_descriptor,
71 		&opush_profile_descriptor,
72 		&sp_profile_descriptor,
73 		&nap_profile_descriptor,
74 		&gn_profile_descriptor,
75 		&panu_profile_descriptor
76 	};
77 
78 	int32_t			i;
79 
80 	for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++)
81 		if (profiles[i]->uuid == uuid)
82 			return (profiles[i]);
83 
84 	return (NULL);
85 }
86 
87 /*
88  * Look attribute in the profile descripror
89  */
90 
91 profile_attr_create_p
92 profile_get_attr(const profile_p profile, uint16_t attr)
93 {
94 	attr_p	ad = (attr_p) profile->attrs;
95 
96 	for (; ad->create != NULL; ad ++)
97 		if (ad->attr == attr)
98 			return (ad->create);
99 
100 	return (NULL);
101 }
102 
103 /*
104  * uint32 value32 - 5 bytes
105  */
106 
107 int32_t
108 common_profile_create_service_record_handle(
109 	uint8_t *buf, uint8_t const * const eob,
110 	uint8_t const *data, uint32_t datalen)
111 {
112 	if (buf + 5 > eob)
113 		return (-1);
114 
115 	SDP_PUT8(SDP_DATA_UINT32, buf);
116 	SDP_PUT32(((provider_p) data)->handle, buf);
117 
118 	return (5);
119 }
120 
121 /*
122  * seq8 len8			- 2 bytes
123  *	uuid16 value16		- 3 bytes
124  *	[ uuid16 value ]
125  */
126 
127 int32_t
128 common_profile_create_service_class_id_list(
129 		uint8_t *buf, uint8_t const * const eob,
130 		uint8_t const *data, uint32_t datalen)
131 {
132 	int32_t	len = 3 * (datalen >>= 1);
133 
134 	if (len <= 0 || len > 0xff || buf + 2 + len > eob)
135 		return (-1);
136 
137 	SDP_PUT8(SDP_DATA_SEQ8, buf);
138 	SDP_PUT8(len, buf);
139 
140 	for (; datalen > 0; datalen --) {
141 		SDP_PUT8(SDP_DATA_UUID16, buf);
142 		SDP_PUT16(*((uint16_t const *)data), buf);
143 		data += sizeof(uint16_t);
144 	}
145 
146 	return (2 + len);
147 }
148 
149 /*
150  * seq8 len8			- 2 bytes
151  *	seq 8 len8		- 2 bytes
152  *		uuid16 value16	- 3 bytes
153  *		uint16 value16	- 3 bytes
154  *	[ seq 8 len8
155  *		uuid16 value16
156  *		uint16 value16 ]
157  */
158 
159 int32_t
160 common_profile_create_bluetooth_profile_descriptor_list(
161 		uint8_t *buf, uint8_t const * const eob,
162 		uint8_t const *data, uint32_t datalen)
163 {
164 	int32_t	len = 8 * (datalen >>= 2);
165 
166 	if (len <= 0 || len > 0xff || buf + 2 + len > eob)
167 		return (-1);
168 
169 	SDP_PUT8(SDP_DATA_SEQ8, buf);
170 	SDP_PUT8(len, buf);
171 
172 	for (; datalen > 0; datalen --) {
173 		SDP_PUT8(SDP_DATA_SEQ8, buf);
174 		SDP_PUT8(6, buf);
175 		SDP_PUT8(SDP_DATA_UUID16, buf);
176 		SDP_PUT16(*((uint16_t const *)data), buf);
177 		data += sizeof(uint16_t);
178 		SDP_PUT8(SDP_DATA_UINT16, buf);
179 		SDP_PUT16(*((uint16_t const *)data), buf);
180 		data += sizeof(uint16_t);
181 	}
182 
183 	return (2 + len);
184 }
185 
186 /*
187  * seq8 len8		- 2 bytes
188  *	uint16 value16	- 3 bytes
189  *	uint16 value16	- 3 bytes
190  *	uint16 value16	- 3 bytes
191  */
192 
193 int32_t
194 common_profile_create_language_base_attribute_id_list(
195 		uint8_t *buf, uint8_t const * const eob,
196 		uint8_t const *data, uint32_t datalen)
197 {
198 	if (buf + 11 > eob)
199 		return (-1);
200 
201 	SDP_PUT8(SDP_DATA_SEQ8, buf);
202 	SDP_PUT8(9, buf);
203 
204 	/*
205 	 * Language code per ISO 639:1988. Use "en".
206 	 */
207 
208 	SDP_PUT8(SDP_DATA_UINT16, buf);
209 	SDP_PUT16(((0x65 << 8) | 0x6e), buf);
210 
211 	/*
212 	 * Encoding. Recommended is UTF-8. ISO639 UTF-8 MIBenum is 106
213 	 * (http://www.iana.org/assignments/character-sets)
214 	 */
215 
216 	SDP_PUT8(SDP_DATA_UINT16, buf);
217 	SDP_PUT16(106, buf);
218 
219 	/*
220 	 * Offset (Primary Language Base is 0x100)
221 	 */
222 
223 	SDP_PUT8(SDP_DATA_UINT16, buf);
224 	SDP_PUT16(SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID, buf);
225 
226 	return (11);
227 }
228 
229 /*
230  * Common provider name is "FreeBSD"
231  */
232 
233 int32_t
234 common_profile_create_service_provider_name(
235 		uint8_t *buf, uint8_t const * const eob,
236 		uint8_t const *data, uint32_t datalen)
237 {
238 	char	provider_name[] = "FreeBSD";
239 
240 	return (common_profile_create_string8(buf, eob,
241 			(uint8_t const *) provider_name,
242 			strlen(provider_name)));
243 }
244 
245 /*
246  * str8 len8 string
247  */
248 
249 int32_t
250 common_profile_create_string8(
251 		uint8_t *buf, uint8_t const * const eob,
252 		uint8_t const *data, uint32_t datalen)
253 {
254 	if (datalen == 0 || datalen > 0xff || buf + 2 + datalen > eob)
255 		return (-1);
256 
257 	SDP_PUT8(SDP_DATA_STR8, buf);
258 	SDP_PUT8(datalen, buf);
259 	memcpy(buf, data, datalen);
260 
261 	return (2 + datalen);
262 }
263 
264 /*
265  * Service Availability
266  */
267 
268 int32_t
269 common_profile_create_service_availability(
270 		uint8_t *buf, uint8_t const * const eob,
271 		uint8_t const *data, uint32_t datalen)
272 {
273 	if (datalen != 1 || buf + 2 > eob)
274 		return (-1);
275 
276 	SDP_PUT8(SDP_DATA_UINT8, buf);
277 	SDP_PUT8(data[0], buf);
278 
279 	return (2);
280 }
281 
282 /*
283  * seq8 len8			- 2 bytes
284  *	seq8 len8		- 2 bytes
285  *		uuid16 value16	- 3 bytes
286  *	seq8 len8		- 2 bytes
287  *		uuid16 value16	- 3 bytes
288  *		uint8 value8	- 2 bytes
289  */
290 
291 int32_t
292 rfcomm_profile_create_protocol_descriptor_list(
293 		uint8_t *buf, uint8_t const * const eob,
294 		uint8_t const *data, uint32_t datalen)
295 {
296 	if (datalen != 1 || buf + 14 > eob)
297 		return (-1);
298 
299 	SDP_PUT8(SDP_DATA_SEQ8, buf);
300 	SDP_PUT8(12, buf);
301 
302 	SDP_PUT8(SDP_DATA_SEQ8, buf);
303 	SDP_PUT8(3, buf);
304 	SDP_PUT8(SDP_DATA_UUID16, buf);
305 	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
306 
307 	SDP_PUT8(SDP_DATA_SEQ8, buf);
308 	SDP_PUT8(5, buf);
309 	SDP_PUT8(SDP_DATA_UUID16, buf);
310 	SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
311 	SDP_PUT8(SDP_DATA_UINT8, buf);
312 	SDP_PUT8(*data, buf);
313 
314 	return (14);
315 }
316 
317 /*
318  * seq8 len8			- 2 bytes
319  *	seq8 len8		- 2 bytes
320  *		uuid16 value16	- 3 bytes
321  *	seq8 len8		- 2 bytes
322  *		uuid16 value16	- 3 bytes
323  *		uint8 value8	- 2 bytes
324  *	seq8 len8		- 2 bytes
325  *		uuid16 value16	- 3 bytes
326  */
327 
328 int32_t
329 obex_profile_create_protocol_descriptor_list(
330 		uint8_t *buf, uint8_t const * const eob,
331 		uint8_t const *data, uint32_t datalen)
332 {
333 	if (datalen != 1 || buf + 19 > eob)
334 		return (-1);
335 
336 	SDP_PUT8(SDP_DATA_SEQ8, buf);
337 	SDP_PUT8(17, buf);
338 
339 	SDP_PUT8(SDP_DATA_SEQ8, buf);
340 	SDP_PUT8(3, buf);
341 	SDP_PUT8(SDP_DATA_UUID16, buf);
342 	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
343 
344 	SDP_PUT8(SDP_DATA_SEQ8, buf);
345 	SDP_PUT8(5, buf);
346 	SDP_PUT8(SDP_DATA_UUID16, buf);
347 	SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
348 	SDP_PUT8(SDP_DATA_UINT8, buf);
349 	SDP_PUT8(*data, buf);
350 
351 	SDP_PUT8(SDP_DATA_SEQ8, buf);
352 	SDP_PUT8(3, buf);
353 	SDP_PUT8(SDP_DATA_UUID16, buf);
354 	SDP_PUT16(SDP_UUID_PROTOCOL_OBEX, buf);
355 
356 	return (19);
357 }
358 
359 /*
360  * seq8 len8
361  *	uint8 value8	- bytes
362  *	[ uint8 value 8 ]
363  */
364 
365 int32_t
366 obex_profile_create_supported_formats_list(
367 		uint8_t *buf, uint8_t const * const eob,
368 		uint8_t const *data, uint32_t datalen)
369 {
370 	int32_t	len = 2 * datalen;
371 
372 	if (len <= 0 || len > 0xff || buf + 2 + len > eob)
373 		return (-1);
374 
375 	SDP_PUT8(SDP_DATA_SEQ8, buf);
376 	SDP_PUT8(len, buf);
377 
378 	for (; datalen > 0; datalen --) {
379 		SDP_PUT8(SDP_DATA_UINT8, buf);
380 		SDP_PUT8(*data++, buf);
381 	}
382 
383 	return (2 + len);
384 }
385 
386 /*
387  * do not check anything
388  */
389 
390 int32_t
391 common_profile_always_valid(uint8_t const *data, uint32_t datalen)
392 {
393 	return (1);
394 }
395 
396 /*
397  * verify server channel number (the first byte in the data)
398  */
399 
400 int32_t
401 common_profile_server_channel_valid(uint8_t const *data, uint32_t datalen)
402 {
403 	if (data[0] < 1 || data[0] > 30)
404 		return (0);
405 
406 	return (1);
407 }
408 
409 /*
410  * verify server channel number and supported_formats_size
411  * sdp_opush_profile and sdp_irmc_profile
412  */
413 
414 int32_t
415 obex_profile_data_valid(uint8_t const *data, uint32_t datalen)
416 {
417 	sdp_opush_profile_p	opush = (sdp_opush_profile_p) data;
418 
419 	if (opush->server_channel < 1 ||
420 	    opush->server_channel > 30 ||
421 	    opush->supported_formats_size == 0 ||
422 	    opush->supported_formats_size > sizeof(opush->supported_formats))
423 		return (0);
424 
425 	return (1);
426 }
427 
428 /*
429  * BNEP protocol descriptor
430  */
431 
432 int32_t
433 bnep_profile_create_protocol_descriptor_list(
434 		uint8_t *buf, uint8_t const * const eob,
435 		uint8_t const *data, uint32_t datalen)
436 {
437 	/* supported protocol types */
438 	uint16_t	 ptype[] = {
439 		0x0800,	/* IPv4 */
440 		0x0806,	/* ARP */
441 #ifdef INET6
442 		0x86dd,	/* IPv6 */
443 #endif
444 	};
445 
446 	uint16_t	 i, psm, version = 0x0100,
447 			 nptypes = sizeof(ptype)/sizeof(ptype[0]),
448 			 nptypes_size = nptypes * 3;
449 
450 	if (datalen != 2 || 18 + nptypes_size > 255 ||
451 	    buf + 20 + nptypes_size > eob)
452 		return (-1);
453 
454 	memcpy(&psm, data, sizeof(psm));
455 
456 	SDP_PUT8(SDP_DATA_SEQ8, buf);
457 	SDP_PUT8(18 + nptypes_size, buf);
458 
459 	SDP_PUT8(SDP_DATA_SEQ8, buf);
460 	SDP_PUT8(6, buf);
461 	SDP_PUT8(SDP_DATA_UUID16, buf);
462 	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
463 	SDP_PUT8(SDP_DATA_UINT16, buf);
464 	SDP_PUT16(psm, buf);
465 
466 	SDP_PUT8(SDP_DATA_SEQ8, buf);
467 	SDP_PUT8(8 + nptypes_size, buf);
468 	SDP_PUT8(SDP_DATA_UUID16, buf);
469 	SDP_PUT16(SDP_UUID_PROTOCOL_BNEP, buf);
470 	SDP_PUT8(SDP_DATA_UINT16, buf);
471 	SDP_PUT16(version, buf);
472 	SDP_PUT8(SDP_DATA_SEQ8, buf);
473 	SDP_PUT8(nptypes_size, buf);
474 	for (i = 0; i < nptypes; i ++) {
475 		SDP_PUT8(SDP_DATA_UINT16, buf);
476 		SDP_PUT16(ptype[i], buf);
477 	}
478 
479 	return (20 + nptypes_size);
480 }
481 
482 /*
483  * BNEP security description
484  */
485 
486 int32_t
487 bnep_profile_create_security_description(
488 		uint8_t *buf, uint8_t const * const eob,
489 		uint8_t const *data, uint32_t datalen)
490 {
491 	uint16_t	security_descr;
492 
493 	if (datalen != 2 || buf + 3 > eob)
494 		return (-1);
495 
496 	memcpy(&security_descr, data, sizeof(security_descr));
497 
498 	SDP_PUT8(SDP_DATA_UINT16, buf);
499 	SDP_PUT16(security_descr, buf);
500 
501         return (3);
502 }
503 
504