1*1de7b4b8SPedro F. Giffuni /*- 207be7a6cSMaksim Yevmenkin * sd.c 307be7a6cSMaksim Yevmenkin * 4*1de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5*1de7b4b8SPedro F. Giffuni * 607be7a6cSMaksim Yevmenkin * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 707be7a6cSMaksim Yevmenkin * All rights reserved. 807be7a6cSMaksim Yevmenkin * 907be7a6cSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without 1007be7a6cSMaksim Yevmenkin * modification, are permitted provided that the following conditions 1107be7a6cSMaksim Yevmenkin * are met: 1207be7a6cSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright 1307be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer. 1407be7a6cSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright 1507be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the 1607be7a6cSMaksim Yevmenkin * documentation and/or other materials provided with the distribution. 1707be7a6cSMaksim Yevmenkin * 1807be7a6cSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1907be7a6cSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2007be7a6cSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2107be7a6cSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2207be7a6cSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2307be7a6cSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2407be7a6cSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2507be7a6cSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2607be7a6cSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2707be7a6cSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2807be7a6cSMaksim Yevmenkin * SUCH DAMAGE. 2907be7a6cSMaksim Yevmenkin * 3007be7a6cSMaksim Yevmenkin * $Id: sd.c,v 1.4 2004/01/13 01:54:39 max Exp $ 3107be7a6cSMaksim Yevmenkin * $FreeBSD$ 3207be7a6cSMaksim Yevmenkin */ 3307be7a6cSMaksim Yevmenkin 3407be7a6cSMaksim Yevmenkin #include <sys/queue.h> 358d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED 3607be7a6cSMaksim Yevmenkin #include <bluetooth.h> 3707be7a6cSMaksim Yevmenkin #include <sdp.h> 3807be7a6cSMaksim Yevmenkin #include <string.h> 3907be7a6cSMaksim Yevmenkin #include "profile.h" 4007be7a6cSMaksim Yevmenkin #include "provider.h" 4107be7a6cSMaksim Yevmenkin 4207be7a6cSMaksim Yevmenkin static int32_t 4307be7a6cSMaksim Yevmenkin sd_profile_create_service_class_id_list( 4407be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 4507be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 4607be7a6cSMaksim Yevmenkin { 4707be7a6cSMaksim Yevmenkin static uint16_t service_classes[] = { 4807be7a6cSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER 4907be7a6cSMaksim Yevmenkin }; 5007be7a6cSMaksim Yevmenkin 5107be7a6cSMaksim Yevmenkin return (common_profile_create_service_class_id_list( 5207be7a6cSMaksim Yevmenkin buf, eob, 5307be7a6cSMaksim Yevmenkin (uint8_t const *) service_classes, 5407be7a6cSMaksim Yevmenkin sizeof(service_classes))); 5507be7a6cSMaksim Yevmenkin } 5607be7a6cSMaksim Yevmenkin 5707be7a6cSMaksim Yevmenkin static int32_t 58c169089aSMaksim Yevmenkin sd_profile_create_bluetooth_profile_descriptor_list( 59c169089aSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 60c169089aSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 61c169089aSMaksim Yevmenkin { 62c169089aSMaksim Yevmenkin static uint16_t profile_descriptor_list[] = { 63c169089aSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, 64c169089aSMaksim Yevmenkin 0x0100 65c169089aSMaksim Yevmenkin }; 66c169089aSMaksim Yevmenkin 67c169089aSMaksim Yevmenkin return (common_profile_create_bluetooth_profile_descriptor_list( 68c169089aSMaksim Yevmenkin buf, eob, 69c169089aSMaksim Yevmenkin (uint8_t const *) profile_descriptor_list, 70c169089aSMaksim Yevmenkin sizeof(profile_descriptor_list))); 71c169089aSMaksim Yevmenkin } 72c169089aSMaksim Yevmenkin 73c169089aSMaksim Yevmenkin static int32_t 7407be7a6cSMaksim Yevmenkin sd_profile_create_service_id( 7507be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 7607be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 7707be7a6cSMaksim Yevmenkin { 7807be7a6cSMaksim Yevmenkin if (buf + 3 > eob) 7907be7a6cSMaksim Yevmenkin return (-1); 8007be7a6cSMaksim Yevmenkin 8107be7a6cSMaksim Yevmenkin /* 8207be7a6cSMaksim Yevmenkin * The ServiceID is a UUID that universally and uniquely identifies 8307be7a6cSMaksim Yevmenkin * the service instance described by the service record. This service 8407be7a6cSMaksim Yevmenkin * attribute is particularly useful if the same service is described 8507be7a6cSMaksim Yevmenkin * by service records in more than one SDP server 8607be7a6cSMaksim Yevmenkin */ 8707be7a6cSMaksim Yevmenkin 8807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 8907be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); /* XXX ??? */ 9007be7a6cSMaksim Yevmenkin 9107be7a6cSMaksim Yevmenkin return (3); 9207be7a6cSMaksim Yevmenkin } 9307be7a6cSMaksim Yevmenkin 9407be7a6cSMaksim Yevmenkin static int32_t 9507be7a6cSMaksim Yevmenkin sd_profile_create_service_name( 9607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 9707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 9807be7a6cSMaksim Yevmenkin { 9907be7a6cSMaksim Yevmenkin static char service_name[] = "Bluetooth service discovery"; 10007be7a6cSMaksim Yevmenkin 10107be7a6cSMaksim Yevmenkin return (common_profile_create_string8( 10207be7a6cSMaksim Yevmenkin buf, eob, 10307be7a6cSMaksim Yevmenkin (uint8_t const *) service_name, strlen(service_name))); 10407be7a6cSMaksim Yevmenkin } 10507be7a6cSMaksim Yevmenkin 10607be7a6cSMaksim Yevmenkin static int32_t 10707be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list( 10807be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 10907be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 11007be7a6cSMaksim Yevmenkin { 111c169089aSMaksim Yevmenkin if (buf + 12 > eob) 11207be7a6cSMaksim Yevmenkin return (-1); 11307be7a6cSMaksim Yevmenkin 11407be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 115c169089aSMaksim Yevmenkin SDP_PUT8(10, buf); 11607be7a6cSMaksim Yevmenkin 11707be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 118c169089aSMaksim Yevmenkin SDP_PUT8(3, buf); 11907be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 12007be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 12107be7a6cSMaksim Yevmenkin 122c169089aSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 123c169089aSMaksim Yevmenkin SDP_PUT8(3, buf); 124c169089aSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 125c169089aSMaksim Yevmenkin SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); 12607be7a6cSMaksim Yevmenkin 127c169089aSMaksim Yevmenkin return (12); 12807be7a6cSMaksim Yevmenkin } 12907be7a6cSMaksim Yevmenkin 13007be7a6cSMaksim Yevmenkin static int32_t 13107be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list( 13207be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 13307be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 13407be7a6cSMaksim Yevmenkin { 13507be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 13607be7a6cSMaksim Yevmenkin return (-1); 13707be7a6cSMaksim Yevmenkin 13807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 13907be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 14007be7a6cSMaksim Yevmenkin 14107be7a6cSMaksim Yevmenkin /* 14207be7a6cSMaksim Yevmenkin * The top-level browse group ID, called PublicBrowseRoot and 14307be7a6cSMaksim Yevmenkin * representing the root of the browsing hierarchy, has the value 14407be7a6cSMaksim Yevmenkin * 00001002-0000-1000-8000-00805F9B34FB (UUID16: 0x1002) from the 14507be7a6cSMaksim Yevmenkin * Bluetooth Assigned Numbers document 14607be7a6cSMaksim Yevmenkin */ 14707be7a6cSMaksim Yevmenkin 14807be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UUID16, buf); 14907be7a6cSMaksim Yevmenkin SDP_PUT16(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, buf); 15007be7a6cSMaksim Yevmenkin 15107be7a6cSMaksim Yevmenkin return (5); 15207be7a6cSMaksim Yevmenkin } 15307be7a6cSMaksim Yevmenkin 15407be7a6cSMaksim Yevmenkin static int32_t 15507be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list( 15607be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 15707be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 15807be7a6cSMaksim Yevmenkin { 15907be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 16007be7a6cSMaksim Yevmenkin return (-1); 16107be7a6cSMaksim Yevmenkin 16207be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ8, buf); 16307be7a6cSMaksim Yevmenkin SDP_PUT8(3, buf); 16407be7a6cSMaksim Yevmenkin 16507be7a6cSMaksim Yevmenkin /* 16607be7a6cSMaksim Yevmenkin * The VersionNumberList is a data element sequence in which each 16707be7a6cSMaksim Yevmenkin * element of the sequence is a version number supported by the SDP 16807be7a6cSMaksim Yevmenkin * server. A version number is a 16-bit unsigned integer consisting 16907be7a6cSMaksim Yevmenkin * of two fields. The higher-order 8 bits contain the major version 17007be7a6cSMaksim Yevmenkin * number field and the low-order 8 bits contain the minor version 17107be7a6cSMaksim Yevmenkin * number field. The initial version of SDP has a major version of 17207be7a6cSMaksim Yevmenkin * 1 and a minor version of 0 17307be7a6cSMaksim Yevmenkin */ 17407be7a6cSMaksim Yevmenkin 17507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT16, buf); 17607be7a6cSMaksim Yevmenkin SDP_PUT16(0x0100, buf); 17707be7a6cSMaksim Yevmenkin 17807be7a6cSMaksim Yevmenkin return (5); 17907be7a6cSMaksim Yevmenkin } 18007be7a6cSMaksim Yevmenkin 18107be7a6cSMaksim Yevmenkin static int32_t 18207be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state( 18307be7a6cSMaksim Yevmenkin uint8_t *buf, uint8_t const * const eob, 18407be7a6cSMaksim Yevmenkin uint8_t const *data, uint32_t datalen) 18507be7a6cSMaksim Yevmenkin { 18607be7a6cSMaksim Yevmenkin uint32_t change_state = provider_get_change_state(); 18707be7a6cSMaksim Yevmenkin 18807be7a6cSMaksim Yevmenkin if (buf + 5 > eob) 18907be7a6cSMaksim Yevmenkin return (-1); 19007be7a6cSMaksim Yevmenkin 19107be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_UINT32, buf); 19207be7a6cSMaksim Yevmenkin SDP_PUT32(change_state, buf); 19307be7a6cSMaksim Yevmenkin 19407be7a6cSMaksim Yevmenkin return (5); 19507be7a6cSMaksim Yevmenkin } 19607be7a6cSMaksim Yevmenkin 19707be7a6cSMaksim Yevmenkin static attr_t sd_profile_attrs[] = { 19807be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_RECORD_HANDLE, 19907be7a6cSMaksim Yevmenkin common_profile_create_service_record_handle }, 20007be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_CLASS_ID_LIST, 20107be7a6cSMaksim Yevmenkin sd_profile_create_service_class_id_list }, 202c169089aSMaksim Yevmenkin { SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 203c169089aSMaksim Yevmenkin sd_profile_create_bluetooth_profile_descriptor_list }, 20407be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_ID, 20507be7a6cSMaksim Yevmenkin sd_profile_create_service_id }, 20607be7a6cSMaksim Yevmenkin { SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, 20707be7a6cSMaksim Yevmenkin common_profile_create_language_base_attribute_id_list }, 20807be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 20907be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 21007be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET, 21107be7a6cSMaksim Yevmenkin sd_profile_create_service_name }, 21207be7a6cSMaksim Yevmenkin { SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_PROVIDER_NAME_OFFSET, 21307be7a6cSMaksim Yevmenkin common_profile_create_service_provider_name }, 21407be7a6cSMaksim Yevmenkin { SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 21507be7a6cSMaksim Yevmenkin sd_profile_create_protocol_descriptor_list }, 21607be7a6cSMaksim Yevmenkin { SDP_ATTR_BROWSE_GROUP_LIST, 21707be7a6cSMaksim Yevmenkin sd_profile_create_browse_group_list }, 21807be7a6cSMaksim Yevmenkin { SDP_ATTR_VERSION_NUMBER_LIST, 21907be7a6cSMaksim Yevmenkin sd_profile_create_version_number_list }, 22007be7a6cSMaksim Yevmenkin { SDP_ATTR_SERVICE_DATABASE_STATE, 22107be7a6cSMaksim Yevmenkin sd_profile_create_service_database_state }, 22207be7a6cSMaksim Yevmenkin { 0, NULL } /* end entry */ 22307be7a6cSMaksim Yevmenkin }; 22407be7a6cSMaksim Yevmenkin 22507be7a6cSMaksim Yevmenkin profile_t sd_profile_descriptor = { 22607be7a6cSMaksim Yevmenkin SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, 22707be7a6cSMaksim Yevmenkin 0, 22807be7a6cSMaksim Yevmenkin (profile_data_valid_p) NULL, 22907be7a6cSMaksim Yevmenkin (attr_t const * const) &sd_profile_attrs 23007be7a6cSMaksim Yevmenkin }; 23107be7a6cSMaksim Yevmenkin 232