107be7a6cSMaksim Yevmenkin /*
207be7a6cSMaksim Yevmenkin * profile.c
3f2505d70SMaksim Yevmenkin */
4f2505d70SMaksim Yevmenkin
5f2505d70SMaksim Yevmenkin /*-
64d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
71de7b4b8SPedro F. Giffuni *
807be7a6cSMaksim Yevmenkin * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
907be7a6cSMaksim Yevmenkin * All rights reserved.
1007be7a6cSMaksim Yevmenkin *
1107be7a6cSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without
1207be7a6cSMaksim Yevmenkin * modification, are permitted provided that the following conditions
1307be7a6cSMaksim Yevmenkin * are met:
1407be7a6cSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright
1507be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer.
1607be7a6cSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright
1707be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the
1807be7a6cSMaksim Yevmenkin * documentation and/or other materials provided with the distribution.
1907be7a6cSMaksim Yevmenkin *
2007be7a6cSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2107be7a6cSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2207be7a6cSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2307be7a6cSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2407be7a6cSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2507be7a6cSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2607be7a6cSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2707be7a6cSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2807be7a6cSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2907be7a6cSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3007be7a6cSMaksim Yevmenkin * SUCH DAMAGE.
3107be7a6cSMaksim Yevmenkin *
3207be7a6cSMaksim Yevmenkin * $Id: profile.c,v 1.6 2004/01/13 19:31:54 max Exp $
3307be7a6cSMaksim Yevmenkin */
3407be7a6cSMaksim Yevmenkin
35*fdbf7cabSElyes Haouas #include <sys/param.h>
3607be7a6cSMaksim Yevmenkin #include <sys/queue.h>
378d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
3807be7a6cSMaksim Yevmenkin #include <bluetooth.h>
3907be7a6cSMaksim Yevmenkin #include <sdp.h>
4007be7a6cSMaksim Yevmenkin #include <string.h>
4107be7a6cSMaksim Yevmenkin #include "profile.h"
4207be7a6cSMaksim Yevmenkin #include "provider.h"
4307be7a6cSMaksim Yevmenkin
4407be7a6cSMaksim Yevmenkin /*
4507be7a6cSMaksim Yevmenkin * Lookup profile descriptor
4607be7a6cSMaksim Yevmenkin */
4707be7a6cSMaksim Yevmenkin
4807be7a6cSMaksim Yevmenkin profile_p
profile_get_descriptor(uint16_t uuid)4907be7a6cSMaksim Yevmenkin profile_get_descriptor(uint16_t uuid)
5007be7a6cSMaksim Yevmenkin {
5121be80aeSHans Petter Selasky extern profile_t audio_sink_profile_descriptor;
5221be80aeSHans Petter Selasky extern profile_t audio_source_profile_descriptor;
5307be7a6cSMaksim Yevmenkin extern profile_t dun_profile_descriptor;
5407be7a6cSMaksim Yevmenkin extern profile_t ftrn_profile_descriptor;
5507be7a6cSMaksim Yevmenkin extern profile_t irmc_profile_descriptor;
5607be7a6cSMaksim Yevmenkin extern profile_t irmc_command_profile_descriptor;
5707be7a6cSMaksim Yevmenkin extern profile_t lan_profile_descriptor;
5807be7a6cSMaksim Yevmenkin extern profile_t opush_profile_descriptor;
5907be7a6cSMaksim Yevmenkin extern profile_t sp_profile_descriptor;
60f2505d70SMaksim Yevmenkin extern profile_t nap_profile_descriptor;
61f2505d70SMaksim Yevmenkin extern profile_t gn_profile_descriptor;
62f2505d70SMaksim Yevmenkin extern profile_t panu_profile_descriptor;
6307be7a6cSMaksim Yevmenkin
6407be7a6cSMaksim Yevmenkin static const profile_p profiles[] = {
6521be80aeSHans Petter Selasky &audio_sink_profile_descriptor,
6621be80aeSHans Petter Selasky &audio_source_profile_descriptor,
6707be7a6cSMaksim Yevmenkin &dun_profile_descriptor,
6807be7a6cSMaksim Yevmenkin &ftrn_profile_descriptor,
6907be7a6cSMaksim Yevmenkin &irmc_profile_descriptor,
7007be7a6cSMaksim Yevmenkin &irmc_command_profile_descriptor,
7107be7a6cSMaksim Yevmenkin &lan_profile_descriptor,
7207be7a6cSMaksim Yevmenkin &opush_profile_descriptor,
73f2505d70SMaksim Yevmenkin &sp_profile_descriptor,
74f2505d70SMaksim Yevmenkin &nap_profile_descriptor,
75f2505d70SMaksim Yevmenkin &gn_profile_descriptor,
76f2505d70SMaksim Yevmenkin &panu_profile_descriptor
7707be7a6cSMaksim Yevmenkin };
7807be7a6cSMaksim Yevmenkin
7907be7a6cSMaksim Yevmenkin int32_t i;
8007be7a6cSMaksim Yevmenkin
81*fdbf7cabSElyes Haouas for (i = 0; i < nitems(profiles); i++)
8207be7a6cSMaksim Yevmenkin if (profiles[i]->uuid == uuid)
8307be7a6cSMaksim Yevmenkin return (profiles[i]);
8407be7a6cSMaksim Yevmenkin
8507be7a6cSMaksim Yevmenkin return (NULL);
8607be7a6cSMaksim Yevmenkin }
8707be7a6cSMaksim Yevmenkin
8807be7a6cSMaksim Yevmenkin /*
8907be7a6cSMaksim Yevmenkin * Look attribute in the profile descripror
9007be7a6cSMaksim Yevmenkin */
9107be7a6cSMaksim Yevmenkin
9207be7a6cSMaksim Yevmenkin profile_attr_create_p
profile_get_attr(const profile_p profile,uint16_t attr)9307be7a6cSMaksim Yevmenkin profile_get_attr(const profile_p profile, uint16_t attr)
9407be7a6cSMaksim Yevmenkin {
9507be7a6cSMaksim Yevmenkin attr_p ad = (attr_p) profile->attrs;
9607be7a6cSMaksim Yevmenkin
9707be7a6cSMaksim Yevmenkin for (; ad->create != NULL; ad ++)
9807be7a6cSMaksim Yevmenkin if (ad->attr == attr)
9907be7a6cSMaksim Yevmenkin return (ad->create);
10007be7a6cSMaksim Yevmenkin
10107be7a6cSMaksim Yevmenkin return (NULL);
10207be7a6cSMaksim Yevmenkin }
10307be7a6cSMaksim Yevmenkin
10407be7a6cSMaksim Yevmenkin /*
10507be7a6cSMaksim Yevmenkin * uint32 value32 - 5 bytes
10607be7a6cSMaksim Yevmenkin */
10707be7a6cSMaksim Yevmenkin
10807be7a6cSMaksim Yevmenkin int32_t
common_profile_create_service_record_handle(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)10907be7a6cSMaksim Yevmenkin common_profile_create_service_record_handle(
11007be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
11107be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
11207be7a6cSMaksim Yevmenkin {
11307be7a6cSMaksim Yevmenkin if (buf + 5 > eob)
11407be7a6cSMaksim Yevmenkin return (-1);
11507be7a6cSMaksim Yevmenkin
11607be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT32, buf);
11707be7a6cSMaksim Yevmenkin SDP_PUT32(((provider_p) data)->handle, buf);
11807be7a6cSMaksim Yevmenkin
11907be7a6cSMaksim Yevmenkin return (5);
12007be7a6cSMaksim Yevmenkin }
12107be7a6cSMaksim Yevmenkin
12207be7a6cSMaksim Yevmenkin /*
12307be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
12407be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
12507be7a6cSMaksim Yevmenkin * [ uuid16 value ]
12607be7a6cSMaksim Yevmenkin */
12707be7a6cSMaksim Yevmenkin
12807be7a6cSMaksim Yevmenkin int32_t
common_profile_create_service_class_id_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)12907be7a6cSMaksim Yevmenkin common_profile_create_service_class_id_list(
13007be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
13107be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
13207be7a6cSMaksim Yevmenkin {
13307be7a6cSMaksim Yevmenkin int32_t len = 3 * (datalen >>= 1);
13407be7a6cSMaksim Yevmenkin
13507be7a6cSMaksim Yevmenkin if (len <= 0 || len > 0xff || buf + 2 + len > eob)
13607be7a6cSMaksim Yevmenkin return (-1);
13707be7a6cSMaksim Yevmenkin
13807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
13907be7a6cSMaksim Yevmenkin SDP_PUT8(len, buf);
14007be7a6cSMaksim Yevmenkin
14107be7a6cSMaksim Yevmenkin for (; datalen > 0; datalen --) {
14207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
1431bb0b6deSAlexander Kabaev SDP_PUT16(*((uint16_t const *)data), buf);
1441bb0b6deSAlexander Kabaev data += sizeof(uint16_t);
14507be7a6cSMaksim Yevmenkin }
14607be7a6cSMaksim Yevmenkin
14707be7a6cSMaksim Yevmenkin return (2 + len);
14807be7a6cSMaksim Yevmenkin }
14907be7a6cSMaksim Yevmenkin
15007be7a6cSMaksim Yevmenkin /*
15107be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
15207be7a6cSMaksim Yevmenkin * seq 8 len8 - 2 bytes
15307be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
15407be7a6cSMaksim Yevmenkin * uint16 value16 - 3 bytes
15507be7a6cSMaksim Yevmenkin * [ seq 8 len8
15607be7a6cSMaksim Yevmenkin * uuid16 value16
15707be7a6cSMaksim Yevmenkin * uint16 value16 ]
15807be7a6cSMaksim Yevmenkin */
15907be7a6cSMaksim Yevmenkin
16007be7a6cSMaksim Yevmenkin int32_t
common_profile_create_bluetooth_profile_descriptor_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)16107be7a6cSMaksim Yevmenkin common_profile_create_bluetooth_profile_descriptor_list(
16207be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
16307be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
16407be7a6cSMaksim Yevmenkin {
16507be7a6cSMaksim Yevmenkin int32_t len = 8 * (datalen >>= 2);
16607be7a6cSMaksim Yevmenkin
16707be7a6cSMaksim Yevmenkin if (len <= 0 || len > 0xff || buf + 2 + len > eob)
16807be7a6cSMaksim Yevmenkin return (-1);
16907be7a6cSMaksim Yevmenkin
17007be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
17107be7a6cSMaksim Yevmenkin SDP_PUT8(len, buf);
17207be7a6cSMaksim Yevmenkin
17307be7a6cSMaksim Yevmenkin for (; datalen > 0; datalen --) {
17407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
17507be7a6cSMaksim Yevmenkin SDP_PUT8(6, buf);
17607be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
1771bb0b6deSAlexander Kabaev SDP_PUT16(*((uint16_t const *)data), buf);
1781bb0b6deSAlexander Kabaev data += sizeof(uint16_t);
17907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
1801bb0b6deSAlexander Kabaev SDP_PUT16(*((uint16_t const *)data), buf);
1811bb0b6deSAlexander Kabaev data += sizeof(uint16_t);
18207be7a6cSMaksim Yevmenkin }
18307be7a6cSMaksim Yevmenkin
18407be7a6cSMaksim Yevmenkin return (2 + len);
18507be7a6cSMaksim Yevmenkin }
18607be7a6cSMaksim Yevmenkin
18707be7a6cSMaksim Yevmenkin /*
18807be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
18907be7a6cSMaksim Yevmenkin * uint16 value16 - 3 bytes
19007be7a6cSMaksim Yevmenkin * uint16 value16 - 3 bytes
19107be7a6cSMaksim Yevmenkin * uint16 value16 - 3 bytes
19207be7a6cSMaksim Yevmenkin */
19307be7a6cSMaksim Yevmenkin
19407be7a6cSMaksim Yevmenkin int32_t
common_profile_create_language_base_attribute_id_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)19507be7a6cSMaksim Yevmenkin common_profile_create_language_base_attribute_id_list(
19607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
19707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
19807be7a6cSMaksim Yevmenkin {
19907be7a6cSMaksim Yevmenkin if (buf + 11 > eob)
20007be7a6cSMaksim Yevmenkin return (-1);
20107be7a6cSMaksim Yevmenkin
20207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
20307be7a6cSMaksim Yevmenkin SDP_PUT8(9, buf);
20407be7a6cSMaksim Yevmenkin
20507be7a6cSMaksim Yevmenkin /*
20607be7a6cSMaksim Yevmenkin * Language code per ISO 639:1988. Use "en".
20707be7a6cSMaksim Yevmenkin */
20807be7a6cSMaksim Yevmenkin
20907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
21007be7a6cSMaksim Yevmenkin SDP_PUT16(((0x65 << 8) | 0x6e), buf);
21107be7a6cSMaksim Yevmenkin
21207be7a6cSMaksim Yevmenkin /*
21307be7a6cSMaksim Yevmenkin * Encoding. Recommended is UTF-8. ISO639 UTF-8 MIBenum is 106
21407be7a6cSMaksim Yevmenkin * (http://www.iana.org/assignments/character-sets)
21507be7a6cSMaksim Yevmenkin */
21607be7a6cSMaksim Yevmenkin
21707be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
21807be7a6cSMaksim Yevmenkin SDP_PUT16(106, buf);
21907be7a6cSMaksim Yevmenkin
22007be7a6cSMaksim Yevmenkin /*
22107be7a6cSMaksim Yevmenkin * Offset (Primary Language Base is 0x100)
22207be7a6cSMaksim Yevmenkin */
22307be7a6cSMaksim Yevmenkin
22407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
22507be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID, buf);
22607be7a6cSMaksim Yevmenkin
22707be7a6cSMaksim Yevmenkin return (11);
22807be7a6cSMaksim Yevmenkin }
22907be7a6cSMaksim Yevmenkin
23007be7a6cSMaksim Yevmenkin /*
23107be7a6cSMaksim Yevmenkin * Common provider name is "FreeBSD"
23207be7a6cSMaksim Yevmenkin */
23307be7a6cSMaksim Yevmenkin
23407be7a6cSMaksim Yevmenkin int32_t
common_profile_create_service_provider_name(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)23507be7a6cSMaksim Yevmenkin common_profile_create_service_provider_name(
23607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
23707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
23807be7a6cSMaksim Yevmenkin {
23907be7a6cSMaksim Yevmenkin char provider_name[] = "FreeBSD";
24007be7a6cSMaksim Yevmenkin
24107be7a6cSMaksim Yevmenkin return (common_profile_create_string8(buf, eob,
24207be7a6cSMaksim Yevmenkin (uint8_t const *) provider_name,
24307be7a6cSMaksim Yevmenkin strlen(provider_name)));
24407be7a6cSMaksim Yevmenkin }
24507be7a6cSMaksim Yevmenkin
24607be7a6cSMaksim Yevmenkin /*
24707be7a6cSMaksim Yevmenkin * str8 len8 string
24807be7a6cSMaksim Yevmenkin */
24907be7a6cSMaksim Yevmenkin
25007be7a6cSMaksim Yevmenkin int32_t
common_profile_create_string8(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)25107be7a6cSMaksim Yevmenkin common_profile_create_string8(
25207be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
25307be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
25407be7a6cSMaksim Yevmenkin {
25507be7a6cSMaksim Yevmenkin if (datalen == 0 || datalen > 0xff || buf + 2 + datalen > eob)
25607be7a6cSMaksim Yevmenkin return (-1);
25707be7a6cSMaksim Yevmenkin
25807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_STR8, buf);
25907be7a6cSMaksim Yevmenkin SDP_PUT8(datalen, buf);
26007be7a6cSMaksim Yevmenkin memcpy(buf, data, datalen);
26107be7a6cSMaksim Yevmenkin
26207be7a6cSMaksim Yevmenkin return (2 + datalen);
26307be7a6cSMaksim Yevmenkin }
26407be7a6cSMaksim Yevmenkin
26507be7a6cSMaksim Yevmenkin /*
26613040bc9SMaksim Yevmenkin * Service Availability
26713040bc9SMaksim Yevmenkin */
26813040bc9SMaksim Yevmenkin
26913040bc9SMaksim Yevmenkin int32_t
common_profile_create_service_availability(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)27013040bc9SMaksim Yevmenkin common_profile_create_service_availability(
27113040bc9SMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
27213040bc9SMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
27313040bc9SMaksim Yevmenkin {
27413040bc9SMaksim Yevmenkin if (datalen != 1 || buf + 2 > eob)
27513040bc9SMaksim Yevmenkin return (-1);
27613040bc9SMaksim Yevmenkin
27713040bc9SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT8, buf);
27813040bc9SMaksim Yevmenkin SDP_PUT8(data[0], buf);
27913040bc9SMaksim Yevmenkin
28013040bc9SMaksim Yevmenkin return (2);
28113040bc9SMaksim Yevmenkin }
28213040bc9SMaksim Yevmenkin
28313040bc9SMaksim Yevmenkin /*
28407be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
28507be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
28607be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
28707be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
28807be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
28907be7a6cSMaksim Yevmenkin * uint8 value8 - 2 bytes
29007be7a6cSMaksim Yevmenkin */
29107be7a6cSMaksim Yevmenkin
29207be7a6cSMaksim Yevmenkin int32_t
rfcomm_profile_create_protocol_descriptor_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)29307be7a6cSMaksim Yevmenkin rfcomm_profile_create_protocol_descriptor_list(
29407be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
29507be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
29607be7a6cSMaksim Yevmenkin {
29707be7a6cSMaksim Yevmenkin if (datalen != 1 || buf + 14 > eob)
29807be7a6cSMaksim Yevmenkin return (-1);
29907be7a6cSMaksim Yevmenkin
30007be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
30107be7a6cSMaksim Yevmenkin SDP_PUT8(12, buf);
30207be7a6cSMaksim Yevmenkin
30307be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
30407be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf);
30507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
30607be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
30707be7a6cSMaksim Yevmenkin
30807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
30907be7a6cSMaksim Yevmenkin SDP_PUT8(5, buf);
31007be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
31107be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
31207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT8, buf);
31307be7a6cSMaksim Yevmenkin SDP_PUT8(*data, buf);
31407be7a6cSMaksim Yevmenkin
31507be7a6cSMaksim Yevmenkin return (14);
31607be7a6cSMaksim Yevmenkin }
31707be7a6cSMaksim Yevmenkin
31807be7a6cSMaksim Yevmenkin /*
31907be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
32007be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
32107be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
32207be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
32307be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
32407be7a6cSMaksim Yevmenkin * uint8 value8 - 2 bytes
32507be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
32607be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes
32707be7a6cSMaksim Yevmenkin */
32807be7a6cSMaksim Yevmenkin
32907be7a6cSMaksim Yevmenkin int32_t
obex_profile_create_protocol_descriptor_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)33007be7a6cSMaksim Yevmenkin obex_profile_create_protocol_descriptor_list(
33107be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
33207be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
33307be7a6cSMaksim Yevmenkin {
33407be7a6cSMaksim Yevmenkin if (datalen != 1 || buf + 19 > eob)
33507be7a6cSMaksim Yevmenkin return (-1);
33607be7a6cSMaksim Yevmenkin
33707be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
33807be7a6cSMaksim Yevmenkin SDP_PUT8(17, buf);
33907be7a6cSMaksim Yevmenkin
34007be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
34107be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf);
34207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
34307be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
34407be7a6cSMaksim Yevmenkin
34507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
34607be7a6cSMaksim Yevmenkin SDP_PUT8(5, buf);
34707be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
34807be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf);
34907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT8, buf);
35007be7a6cSMaksim Yevmenkin SDP_PUT8(*data, buf);
35107be7a6cSMaksim Yevmenkin
35207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
35307be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf);
35407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
35507be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_OBEX, buf);
35607be7a6cSMaksim Yevmenkin
35707be7a6cSMaksim Yevmenkin return (19);
35807be7a6cSMaksim Yevmenkin }
35907be7a6cSMaksim Yevmenkin
36007be7a6cSMaksim Yevmenkin /*
36107be7a6cSMaksim Yevmenkin * seq8 len8
36207be7a6cSMaksim Yevmenkin * uint8 value8 - bytes
36307be7a6cSMaksim Yevmenkin * [ uint8 value 8 ]
36407be7a6cSMaksim Yevmenkin */
36507be7a6cSMaksim Yevmenkin
36607be7a6cSMaksim Yevmenkin int32_t
obex_profile_create_supported_formats_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)36707be7a6cSMaksim Yevmenkin obex_profile_create_supported_formats_list(
36807be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
36907be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
37007be7a6cSMaksim Yevmenkin {
37107be7a6cSMaksim Yevmenkin int32_t len = 2 * datalen;
37207be7a6cSMaksim Yevmenkin
37307be7a6cSMaksim Yevmenkin if (len <= 0 || len > 0xff || buf + 2 + len > eob)
37407be7a6cSMaksim Yevmenkin return (-1);
37507be7a6cSMaksim Yevmenkin
37607be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
37707be7a6cSMaksim Yevmenkin SDP_PUT8(len, buf);
37807be7a6cSMaksim Yevmenkin
37907be7a6cSMaksim Yevmenkin for (; datalen > 0; datalen --) {
38007be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT8, buf);
38107be7a6cSMaksim Yevmenkin SDP_PUT8(*data++, buf);
38207be7a6cSMaksim Yevmenkin }
38307be7a6cSMaksim Yevmenkin
38407be7a6cSMaksim Yevmenkin return (2 + len);
38507be7a6cSMaksim Yevmenkin }
38607be7a6cSMaksim Yevmenkin
38707be7a6cSMaksim Yevmenkin /*
388f2505d70SMaksim Yevmenkin * do not check anything
389f2505d70SMaksim Yevmenkin */
390f2505d70SMaksim Yevmenkin
391f2505d70SMaksim Yevmenkin int32_t
common_profile_always_valid(uint8_t const * data,uint32_t datalen)392f2505d70SMaksim Yevmenkin common_profile_always_valid(uint8_t const *data, uint32_t datalen)
393f2505d70SMaksim Yevmenkin {
394f2505d70SMaksim Yevmenkin return (1);
395f2505d70SMaksim Yevmenkin }
396f2505d70SMaksim Yevmenkin
397f2505d70SMaksim Yevmenkin /*
39807be7a6cSMaksim Yevmenkin * verify server channel number (the first byte in the data)
39907be7a6cSMaksim Yevmenkin */
40007be7a6cSMaksim Yevmenkin
40107be7a6cSMaksim Yevmenkin int32_t
common_profile_server_channel_valid(uint8_t const * data,uint32_t datalen)40207be7a6cSMaksim Yevmenkin common_profile_server_channel_valid(uint8_t const *data, uint32_t datalen)
40307be7a6cSMaksim Yevmenkin {
40407be7a6cSMaksim Yevmenkin if (data[0] < 1 || data[0] > 30)
40507be7a6cSMaksim Yevmenkin return (0);
40607be7a6cSMaksim Yevmenkin
40707be7a6cSMaksim Yevmenkin return (1);
40807be7a6cSMaksim Yevmenkin }
40907be7a6cSMaksim Yevmenkin
41007be7a6cSMaksim Yevmenkin /*
41107be7a6cSMaksim Yevmenkin * verify server channel number and supported_formats_size
41207be7a6cSMaksim Yevmenkin * sdp_opush_profile and sdp_irmc_profile
41307be7a6cSMaksim Yevmenkin */
41407be7a6cSMaksim Yevmenkin
41507be7a6cSMaksim Yevmenkin int32_t
obex_profile_data_valid(uint8_t const * data,uint32_t datalen)41607be7a6cSMaksim Yevmenkin obex_profile_data_valid(uint8_t const *data, uint32_t datalen)
41707be7a6cSMaksim Yevmenkin {
41807be7a6cSMaksim Yevmenkin sdp_opush_profile_p opush = (sdp_opush_profile_p) data;
41907be7a6cSMaksim Yevmenkin
42007be7a6cSMaksim Yevmenkin if (opush->server_channel < 1 ||
42107be7a6cSMaksim Yevmenkin opush->server_channel > 30 ||
42207be7a6cSMaksim Yevmenkin opush->supported_formats_size == 0 ||
42307be7a6cSMaksim Yevmenkin opush->supported_formats_size > sizeof(opush->supported_formats))
42407be7a6cSMaksim Yevmenkin return (0);
42507be7a6cSMaksim Yevmenkin
42607be7a6cSMaksim Yevmenkin return (1);
42707be7a6cSMaksim Yevmenkin }
42807be7a6cSMaksim Yevmenkin
429f2505d70SMaksim Yevmenkin /*
430f2505d70SMaksim Yevmenkin * BNEP protocol descriptor
431f2505d70SMaksim Yevmenkin */
432f2505d70SMaksim Yevmenkin
433f2505d70SMaksim Yevmenkin int32_t
bnep_profile_create_protocol_descriptor_list(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)434f2505d70SMaksim Yevmenkin bnep_profile_create_protocol_descriptor_list(
435f2505d70SMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
436f2505d70SMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
437f2505d70SMaksim Yevmenkin {
438f2505d70SMaksim Yevmenkin /* supported protocol types */
439f2505d70SMaksim Yevmenkin uint16_t ptype[] = {
440f2505d70SMaksim Yevmenkin 0x0800, /* IPv4 */
441f2505d70SMaksim Yevmenkin 0x0806, /* ARP */
442f2505d70SMaksim Yevmenkin #ifdef INET6
443f2505d70SMaksim Yevmenkin 0x86dd, /* IPv6 */
444f2505d70SMaksim Yevmenkin #endif
445f2505d70SMaksim Yevmenkin };
446f2505d70SMaksim Yevmenkin
44713040bc9SMaksim Yevmenkin uint16_t i, psm, version = 0x0100,
448*fdbf7cabSElyes Haouas nptypes = nitems(ptype),
449f2505d70SMaksim Yevmenkin nptypes_size = nptypes * 3;
450f2505d70SMaksim Yevmenkin
45113040bc9SMaksim Yevmenkin if (datalen != 2 || 18 + nptypes_size > 255 ||
45213040bc9SMaksim Yevmenkin buf + 20 + nptypes_size > eob)
453f2505d70SMaksim Yevmenkin return (-1);
454f2505d70SMaksim Yevmenkin
45513040bc9SMaksim Yevmenkin memcpy(&psm, data, sizeof(psm));
45613040bc9SMaksim Yevmenkin
457f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
458f2505d70SMaksim Yevmenkin SDP_PUT8(18 + nptypes_size, buf);
459f2505d70SMaksim Yevmenkin
460f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
461f2505d70SMaksim Yevmenkin SDP_PUT8(6, buf);
462f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
463f2505d70SMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
464f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
465f2505d70SMaksim Yevmenkin SDP_PUT16(psm, buf);
466f2505d70SMaksim Yevmenkin
467f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
468f2505d70SMaksim Yevmenkin SDP_PUT8(8 + nptypes_size, buf);
469f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf);
470f2505d70SMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_BNEP, buf);
471f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
472f2505d70SMaksim Yevmenkin SDP_PUT16(version, buf);
473f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf);
474f2505d70SMaksim Yevmenkin SDP_PUT8(nptypes_size, buf);
475f2505d70SMaksim Yevmenkin for (i = 0; i < nptypes; i ++) {
476f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
477f2505d70SMaksim Yevmenkin SDP_PUT16(ptype[i], buf);
478f2505d70SMaksim Yevmenkin }
479f2505d70SMaksim Yevmenkin
480f2505d70SMaksim Yevmenkin return (20 + nptypes_size);
481f2505d70SMaksim Yevmenkin }
482f2505d70SMaksim Yevmenkin
483f2505d70SMaksim Yevmenkin /*
484f2505d70SMaksim Yevmenkin * BNEP security description
485f2505d70SMaksim Yevmenkin */
486f2505d70SMaksim Yevmenkin
487f2505d70SMaksim Yevmenkin int32_t
bnep_profile_create_security_description(uint8_t * buf,uint8_t const * const eob,uint8_t const * data,uint32_t datalen)488f2505d70SMaksim Yevmenkin bnep_profile_create_security_description(
489f2505d70SMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob,
490f2505d70SMaksim Yevmenkin uint8_t const *data, uint32_t datalen)
491f2505d70SMaksim Yevmenkin {
492f2505d70SMaksim Yevmenkin uint16_t security_descr;
493f2505d70SMaksim Yevmenkin
494f2505d70SMaksim Yevmenkin if (datalen != 2 || buf + 3 > eob)
495f2505d70SMaksim Yevmenkin return (-1);
496f2505d70SMaksim Yevmenkin
497f2505d70SMaksim Yevmenkin memcpy(&security_descr, data, sizeof(security_descr));
498f2505d70SMaksim Yevmenkin
499f2505d70SMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf);
500f2505d70SMaksim Yevmenkin SDP_PUT16(security_descr, buf);
501f2505d70SMaksim Yevmenkin
502f2505d70SMaksim Yevmenkin return (3);
503f2505d70SMaksim Yevmenkin }
504f2505d70SMaksim Yevmenkin
505