Home | History | Annotate | Line # | Download | only in sdpd
      1 /*	$NetBSD: compat.c,v 1.2 2010/03/07 10:58:40 plunky Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Iain Hibbert.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: compat.c,v 1.2 2010/03/07 10:58:40 plunky Exp $");
     34 
     35 #include <arpa/inet.h>
     36 
     37 #include <netbt/rfcomm.h>
     38 
     39 #include <bluetooth.h>
     40 #include <errno.h>
     41 #include <sdp.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 
     46 #include "sdpd.h"
     47 
     48 /*
     49  * This file provides for compatibility with the old ABI. Clients send
     50  * a data structure and we generate a record based from that using the
     51  * server output buffer as temporary storage. The sdp_put functions will
     52  * not write invalid data or overflow the buffer which is big enough to
     53  * contain all these records, no need to worry about that.
     54  */
     55 
     56 static bool
     57 dun_profile(sdp_data_t *buf, void *arg, ssize_t len)
     58 {
     59 	sdp_dun_profile_t	*data = arg;
     60 	uint8_t			*first = buf->next;
     61 
     62 	if (len != sizeof(*data)
     63 	    || data->server_channel < RFCOMM_CHANNEL_MIN
     64 	    || data->server_channel > RFCOMM_CHANNEL_MAX)
     65 		return false;
     66 
     67 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
     68 	sdp_put_uint32(buf, 0x00000000);
     69 
     70 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
     71 	sdp_put_seq(buf, 3);
     72 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_DIALUP_NETWORKING);
     73 
     74 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
     75 	sdp_put_seq(buf, 12);
     76 	sdp_put_seq(buf, 3);
     77 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
     78 	sdp_put_seq(buf, 5);
     79 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
     80 	sdp_put_uint8(buf, data->server_channel);
     81 
     82 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
     83 	sdp_put_seq(buf, 3);
     84 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
     85 
     86 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
     87 	sdp_put_seq(buf, 9);
     88 	sdp_put_uint16(buf, 0x656e);	/* "en" */
     89 	sdp_put_uint16(buf, 106);	/* UTF-8 */
     90 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
     91 
     92 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
     93 	sdp_put_seq(buf, 8);
     94 	sdp_put_seq(buf, 6);
     95 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_DIALUP_NETWORKING);
     96 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
     97 
     98 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
     99 	sdp_put_str(buf, "Dialup Networking", -1);
    100 
    101 	sdp_put_uint16(buf, SDP_ATTR_AUDIO_FEEDBACK_SUPPORT);
    102 	sdp_put_bool(buf, data->audio_feedback_support);
    103 
    104 	buf->end = buf->next;
    105 	buf->next = first;
    106 	return true;
    107 }
    108 
    109 static bool
    110 ftrn_profile(sdp_data_t *buf, void *arg, ssize_t len)
    111 {
    112 	sdp_ftrn_profile_t	*data = arg;
    113 	uint8_t			*first = buf->next;
    114 
    115 	if (len != sizeof(*data)
    116 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    117 	    || data->server_channel > RFCOMM_CHANNEL_MAX)
    118 		return false;
    119 
    120 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    121 	sdp_put_uint32(buf, 0x00000000);
    122 
    123 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    124 	sdp_put_seq(buf, 3);
    125 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER);
    126 
    127 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    128 	sdp_put_seq(buf, 17);
    129 	sdp_put_seq(buf, 3);
    130 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    131 	sdp_put_seq(buf, 5);
    132 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    133 	sdp_put_uint8(buf, data->server_channel);
    134 	sdp_put_seq(buf, 3);
    135 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
    136 
    137 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    138 	sdp_put_seq(buf, 3);
    139 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    140 
    141 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    142 	sdp_put_seq(buf, 9);
    143 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    144 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    145 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    146 
    147 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    148 	sdp_put_seq(buf, 8);
    149 	sdp_put_seq(buf, 6);
    150 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER);
    151 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    152 
    153 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    154 	sdp_put_str(buf, "OBEX File Transfer", -1);
    155 
    156 	buf->end = buf->next;
    157 	buf->next = first;
    158 	return true;
    159 }
    160 
    161 static bool
    162 hset_profile(sdp_data_t *buf, void *arg, ssize_t len)
    163 {
    164 	sdp_hset_profile_t	*data = arg;
    165 	uint8_t			*first = buf->next;
    166 
    167 	if (len != sizeof(*data)
    168 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    169 	    || data->server_channel > RFCOMM_CHANNEL_MAX)
    170 		return false;
    171 
    172 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    173 	sdp_put_uint32(buf, 0x00000000);
    174 
    175 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    176 	sdp_put_seq(buf, 6);
    177 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY);
    178 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_GENERIC_AUDIO);
    179 
    180 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    181 	sdp_put_seq(buf, 12);
    182 	sdp_put_seq(buf, 3);
    183 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    184 	sdp_put_seq(buf, 5);
    185 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    186 	sdp_put_uint8(buf, data->server_channel);
    187 
    188 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    189 	sdp_put_seq(buf, 3);
    190 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    191 
    192 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    193 	sdp_put_seq(buf, 9);
    194 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    195 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    196 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    197 
    198 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    199 	sdp_put_seq(buf, 8);
    200 	sdp_put_seq(buf, 6);
    201 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_HEADSET);
    202 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    203 
    204 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    205 	sdp_put_str(buf, "Voice Gateway", -1);
    206 
    207 	buf->end = buf->next;
    208 	buf->next = first;
    209 	return true;
    210 }
    211 
    212 static bool
    213 hf_profile(sdp_data_t *buf, void *arg, ssize_t len)
    214 {
    215 	sdp_hf_profile_t	*data = arg;
    216 	uint8_t			*first = buf->next;
    217 
    218 	if (len != sizeof(*data)
    219 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    220 	    || data->server_channel > RFCOMM_CHANNEL_MAX
    221 	    || (data->supported_features & ~0x001f))
    222 		return false;
    223 
    224 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    225 	sdp_put_uint32(buf, 0x00000000);
    226 
    227 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    228 	sdp_put_seq(buf, 6);
    229 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_HANDSFREE);
    230 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_GENERIC_AUDIO);
    231 
    232 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    233 	sdp_put_seq(buf, 12);
    234 	sdp_put_seq(buf, 3);
    235 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    236 	sdp_put_seq(buf, 5);
    237 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    238 	sdp_put_uint8(buf, data->server_channel);
    239 
    240 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    241 	sdp_put_seq(buf, 3);
    242 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    243 
    244 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    245 	sdp_put_seq(buf, 9);
    246 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    247 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    248 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    249 
    250 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    251 	sdp_put_seq(buf, 8);
    252 	sdp_put_seq(buf, 6);
    253 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_HANDSFREE);
    254 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    255 
    256 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    257 	sdp_put_str(buf, "Hands-Free unit", -1);
    258 
    259 	sdp_put_uint16(buf, SDP_ATTR_SUPPORTED_FEATURES);
    260 	sdp_put_uint16(buf, data->supported_features);
    261 
    262 	buf->end = buf->next;
    263 	buf->next = first;
    264 	return true;
    265 }
    266 
    267 static bool
    268 irmc_profile(sdp_data_t *buf, void *arg, ssize_t len)
    269 {
    270 	sdp_irmc_profile_t	*data = arg;
    271 	uint8_t			*first = buf->next;
    272 	int			i;
    273 
    274 	if (len != sizeof(*data)
    275 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    276 	    || data->server_channel > RFCOMM_CHANNEL_MAX
    277 	    || data->supported_formats_size == 0
    278 	    || data->supported_formats_size > sizeof(data->supported_formats))
    279 		return false;
    280 
    281 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    282 	sdp_put_uint32(buf, 0x00000000);
    283 
    284 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    285 	sdp_put_seq(buf, 3);
    286 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_IR_MC_SYNC);
    287 
    288 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    289 	sdp_put_seq(buf, 17);
    290 	sdp_put_seq(buf, 3);
    291 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    292 	sdp_put_seq(buf, 5);
    293 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    294 	sdp_put_uint8(buf, data->server_channel);
    295 	sdp_put_seq(buf, 3);
    296 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
    297 
    298 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    299 	sdp_put_seq(buf, 3);
    300 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    301 
    302 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    303 	sdp_put_seq(buf, 9);
    304 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    305 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    306 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    307 
    308 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    309 	sdp_put_seq(buf, 8);
    310 	sdp_put_seq(buf, 6);
    311 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_IR_MC_SYNC);
    312 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    313 
    314 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    315 	sdp_put_str(buf, "IrMC Syncrhonization", -1);
    316 
    317 	sdp_put_uint16(buf, SDP_ATTR_SUPPORTED_DATA_STORES_LIST);
    318 	sdp_put_seq(buf, data->supported_formats_size * 2);
    319 	for (i = 0; i < data->supported_formats_size; i++)
    320 		sdp_put_uint8(buf, data->supported_formats[i]);
    321 
    322 	buf->end = buf->next;
    323 	buf->next = first;
    324 	return true;
    325 }
    326 
    327 static bool
    328 irmc_cmd_profile(sdp_data_t *buf, void *arg, ssize_t len)
    329 {
    330 	sdp_irmc_command_profile_t	*data = arg;
    331 	uint8_t				*first = buf->next;
    332 
    333 	if (len != sizeof(*data)
    334 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    335 	    || data->server_channel > RFCOMM_CHANNEL_MAX)
    336 		return false;
    337 
    338 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    339 	sdp_put_uint32(buf, 0x00000000);
    340 
    341 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    342 	sdp_put_seq(buf, 3);
    343 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND);
    344 
    345 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    346 	sdp_put_seq(buf, 17);
    347 	sdp_put_seq(buf, 3);
    348 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    349 	sdp_put_seq(buf, 5);
    350 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    351 	sdp_put_uint8(buf, data->server_channel);
    352 	sdp_put_seq(buf, 3);
    353 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
    354 
    355 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    356 	sdp_put_seq(buf, 3);
    357 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    358 
    359 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    360 	sdp_put_seq(buf, 9);
    361 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    362 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    363 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    364 
    365 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    366 	sdp_put_seq(buf, 8);
    367 	sdp_put_seq(buf, 6);
    368 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND);
    369 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    370 
    371 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    372 	sdp_put_str(buf, "Sync Command Service", -1);
    373 
    374 	buf->end = buf->next;
    375 	buf->next = first;
    376 	return true;
    377 }
    378 
    379 static bool
    380 lan_profile(sdp_data_t *buf, void *arg, ssize_t len)
    381 {
    382 	sdp_lan_profile_t	*data = arg;
    383 	uint8_t			*first = buf->next;
    384 	struct in_addr		in;
    385 	char			str[32];
    386 
    387 	if (len != sizeof(*data)
    388 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    389 	    || data->server_channel > RFCOMM_CHANNEL_MAX
    390 	    || data->ip_subnet_radius > 32)
    391 		return false;
    392 
    393 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    394 	sdp_put_uint32(buf, 0x00000000);
    395 
    396 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    397 	sdp_put_seq(buf, 3);
    398 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP);
    399 
    400 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    401 	sdp_put_seq(buf, 12);
    402 	sdp_put_seq(buf, 3);
    403 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    404 	sdp_put_seq(buf, 5);
    405 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    406 	sdp_put_uint8(buf, data->server_channel);
    407 
    408 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    409 	sdp_put_seq(buf, 3);
    410 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    411 
    412 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    413 	sdp_put_seq(buf, 9);
    414 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    415 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    416 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    417 
    418 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_AVAILABILITY);
    419 	sdp_put_uint8(buf, data->load_factor);
    420 
    421 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    422 	sdp_put_seq(buf, 8);
    423 	sdp_put_seq(buf, 6);
    424 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP);
    425 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    426 
    427 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    428 	sdp_put_str(buf, "LAN Access using PPP", -1);
    429 
    430 	in.s_addr= data->ip_subnet;
    431 	sprintf(str, "%s/%d", inet_ntoa(in), data->ip_subnet_radius);
    432 	sdp_put_uint16(buf, SDP_ATTR_IP_SUBNET);
    433 	sdp_put_str(buf, str, -1);
    434 
    435 	buf->end = buf->next;
    436 	buf->next = first;
    437 	return true;
    438 }
    439 
    440 static bool
    441 opush_profile(sdp_data_t *buf, void *arg, ssize_t len)
    442 {
    443 	sdp_opush_profile_t	*data = arg;
    444 	uint8_t			*first = buf->next;
    445 	int			i;
    446 
    447 	if (len != sizeof(*data)
    448 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    449 	    || data->server_channel > RFCOMM_CHANNEL_MAX
    450 	    || data->supported_formats_size == 0
    451 	    || data->supported_formats_size > sizeof(data->supported_formats))
    452 		return false;
    453 
    454 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    455 	sdp_put_uint32(buf, 0x00000000);
    456 
    457 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    458 	sdp_put_seq(buf, 3);
    459 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH);
    460 
    461 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    462 	sdp_put_seq(buf, 17);
    463 	sdp_put_seq(buf, 3);
    464 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    465 	sdp_put_seq(buf, 5);
    466 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    467 	sdp_put_uint8(buf, data->server_channel);
    468 	sdp_put_seq(buf, 3);
    469 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
    470 
    471 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    472 	sdp_put_seq(buf, 3);
    473 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    474 
    475 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    476 	sdp_put_seq(buf, 9);
    477 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    478 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    479 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    480 
    481 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    482 	sdp_put_seq(buf, 8);
    483 	sdp_put_seq(buf, 6);
    484 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH);
    485 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    486 
    487 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    488 	sdp_put_str(buf, "OBEX Object Push", -1);
    489 
    490 	sdp_put_uint16(buf, SDP_ATTR_SUPPORTED_FORMATS_LIST);
    491 	sdp_put_seq(buf, data->supported_formats_size * 2);
    492 	for (i = 0; i < data->supported_formats_size; i++)
    493 		sdp_put_uint8(buf, data->supported_formats[i]);
    494 
    495 	buf->end = buf->next;
    496 	buf->next = first;
    497 	return true;
    498 }
    499 
    500 static bool
    501 sp_profile(sdp_data_t *buf, void *arg, ssize_t len)
    502 {
    503 	sdp_sp_profile_t	*data = arg;
    504 	uint8_t			*first = buf->next;
    505 
    506 	if (len != sizeof(*data)
    507 	    || data->server_channel < RFCOMM_CHANNEL_MIN
    508 	    || data->server_channel > RFCOMM_CHANNEL_MAX)
    509 		return false;
    510 
    511 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    512 	sdp_put_uint32(buf, 0x00000000);
    513 
    514 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    515 	sdp_put_seq(buf, 3);
    516 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_SERIAL_PORT);
    517 
    518 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    519 	sdp_put_seq(buf, 12);
    520 	sdp_put_seq(buf, 3);
    521 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    522 	sdp_put_seq(buf, 5);
    523 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
    524 	sdp_put_uint8(buf, data->server_channel);
    525 
    526 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    527 	sdp_put_seq(buf, 3);
    528 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    529 
    530 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    531 	sdp_put_seq(buf, 9);
    532 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    533 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    534 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    535 
    536 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    537 	sdp_put_seq(buf, 8);
    538 	sdp_put_seq(buf, 6);
    539 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_SERIAL_PORT);
    540 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    541 
    542 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    543 	sdp_put_str(buf, "Serial Port", -1);
    544 
    545 	buf->end = buf->next;
    546 	buf->next = first;
    547 	return true;
    548 }
    549 
    550 /* list of protocols used by PAN profiles.  */
    551 static const uint16_t proto[] = {
    552 	0x0800,	/* IPv4 */
    553 	0x0806,	/* ARP  */
    554 #ifdef INET6
    555 	0x86dd,	/* IPv6 */
    556 #endif
    557 };
    558 
    559 static bool
    560 nap_profile(sdp_data_t *buf, void *arg, ssize_t len)
    561 {
    562 	sdp_nap_profile_t	*data = arg;
    563 	uint8_t			*first = buf->next;
    564 	size_t			i;
    565 
    566 	if (len != sizeof(*data)
    567 	    || L2CAP_PSM_INVALID(data->psm)
    568 	    || data->security_description > 0x0002)
    569 		return false;
    570 
    571 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    572 	sdp_put_uint32(buf, 0x00000000);
    573 
    574 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    575 	sdp_put_seq(buf, 3);
    576 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_NAP);
    577 
    578 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    579 	sdp_put_seq(buf, 18 + 3 * __arraycount(proto));
    580 	sdp_put_seq(buf, 6);
    581 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    582 	sdp_put_uint16(buf, data->psm);
    583 	sdp_put_seq(buf, 8 + 3 * __arraycount(proto));
    584 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_BNEP);
    585 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    586 	sdp_put_seq(buf, 3 * __arraycount(proto));
    587 	for (i = 0; i < __arraycount(proto); i++)
    588 		sdp_put_uint16(buf, proto[i]);
    589 
    590 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    591 	sdp_put_seq(buf, 3);
    592 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    593 
    594 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    595 	sdp_put_seq(buf, 9);
    596 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    597 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    598 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    599 
    600 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_AVAILABILITY);
    601 	sdp_put_uint8(buf, data->load_factor);
    602 
    603 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    604 	sdp_put_seq(buf, 8);
    605 	sdp_put_seq(buf, 6);
    606 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_NAP);
    607 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    608 
    609 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    610 	sdp_put_str(buf, "Network Access Point", -1);
    611 
    612 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET);
    613 	sdp_put_str(buf, "Personal Ad-hoc Network Service", -1);
    614 
    615 	sdp_put_uint16(buf, SDP_ATTR_SECURITY_DESCRIPTION);
    616 	sdp_put_uint16(buf, data->security_description);
    617 
    618 	sdp_put_uint16(buf, SDP_ATTR_NET_ACCESS_TYPE);
    619 	sdp_put_uint16(buf, data->net_access_type);
    620 
    621 	sdp_put_uint16(buf, SDP_ATTR_MAX_NET_ACCESS_RATE);
    622 	sdp_put_uint32(buf, data->max_net_access_rate);
    623 
    624 	buf->end = buf->next;
    625 	buf->next = first;
    626 	return true;
    627 }
    628 
    629 static bool
    630 gn_profile(sdp_data_t *buf, void *arg, ssize_t len)
    631 {
    632 	sdp_gn_profile_t	*data = arg;
    633 	uint8_t			*first = buf->next;
    634 	size_t			i;
    635 
    636 	if (len != sizeof(*data)
    637 	    || L2CAP_PSM_INVALID(data->psm)
    638 	    || data->security_description > 0x0002)
    639 		return false;
    640 
    641 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    642 	sdp_put_uint32(buf, 0x00000000);
    643 
    644 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    645 	sdp_put_seq(buf, 3);
    646 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_GN);
    647 
    648 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    649 	sdp_put_seq(buf, 18 + 3 * __arraycount(proto));
    650 	sdp_put_seq(buf, 6);
    651 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    652 	sdp_put_uint16(buf, data->psm);
    653 	sdp_put_seq(buf, 8 + 3 * __arraycount(proto));
    654 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_BNEP);
    655 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    656 	sdp_put_seq(buf, 3 * __arraycount(proto));
    657 	for (i = 0; i < __arraycount(proto); i++)
    658 		sdp_put_uint16(buf, proto[i]);
    659 
    660 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    661 	sdp_put_seq(buf, 3);
    662 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    663 
    664 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    665 	sdp_put_seq(buf, 9);
    666 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    667 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    668 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    669 
    670 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_AVAILABILITY);
    671 	sdp_put_uint8(buf, data->load_factor);
    672 
    673 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    674 	sdp_put_seq(buf, 8);
    675 	sdp_put_seq(buf, 6);
    676 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_GN);
    677 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    678 
    679 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    680 	sdp_put_str(buf, "Group Ad-hoc Network", -1);
    681 
    682 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET);
    683 	sdp_put_str(buf, "Personal Group Ad-hoc Network Service", -1);
    684 
    685 	sdp_put_uint16(buf, SDP_ATTR_SECURITY_DESCRIPTION);
    686 	sdp_put_uint16(buf, data->security_description);
    687 
    688 	buf->end = buf->next;
    689 	buf->next = first;
    690 	return true;
    691 }
    692 
    693 static bool
    694 panu_profile(sdp_data_t *buf, void *arg, ssize_t len)
    695 {
    696 	sdp_panu_profile_t	*data = arg;
    697 	uint8_t			*first = buf->next;
    698 	size_t			i;
    699 
    700 	if (len != sizeof(*data)
    701 	    || L2CAP_PSM_INVALID(data->psm)
    702 	    || data->security_description > 0x0002)
    703 		return false;
    704 
    705 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
    706 	sdp_put_uint32(buf, 0x00000000);
    707 
    708 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
    709 	sdp_put_seq(buf, 3);
    710 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PANU);
    711 
    712 	sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
    713 	sdp_put_seq(buf, 18 + 3 * __arraycount(proto));
    714 	sdp_put_seq(buf, 6);
    715 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
    716 	sdp_put_uint16(buf, data->psm);
    717 	sdp_put_seq(buf, 8 + 3 * __arraycount(proto));
    718 	sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_BNEP);
    719 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    720 	sdp_put_seq(buf, 3 * __arraycount(proto));
    721 	for (i = 0; i < __arraycount(proto); i++)
    722 		sdp_put_uint16(buf, proto[i]);
    723 
    724 	sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
    725 	sdp_put_seq(buf, 3);
    726 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    727 
    728 	sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
    729 	sdp_put_seq(buf, 9);
    730 	sdp_put_uint16(buf, 0x656e);	/* "en" */
    731 	sdp_put_uint16(buf, 106);	/* UTF-8 */
    732 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
    733 
    734 	sdp_put_uint16(buf, SDP_ATTR_SERVICE_AVAILABILITY);
    735 	sdp_put_uint8(buf, data->load_factor);
    736 
    737 	sdp_put_uint16(buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
    738 	sdp_put_seq(buf, 8);
    739 	sdp_put_seq(buf, 6);
    740 	sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PANU);
    741 	sdp_put_uint16(buf, 0x0100);	/* v1.0 */
    742 
    743 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET);
    744 	sdp_put_str(buf, "Personal Ad-hoc User Service", -1);
    745 
    746 	sdp_put_uint16(buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET);
    747 	sdp_put_str(buf, "Personal Ad-hoc User Service", -1);
    748 
    749 	sdp_put_uint16(buf, SDP_ATTR_SECURITY_DESCRIPTION);
    750 	sdp_put_uint16(buf, data->security_description);
    751 
    752 	buf->end = buf->next;
    753 	buf->next = first;
    754 	return true;
    755 }
    756 
    757 static const struct {
    758 	uint16_t	class;
    759 	bool		(*create)(sdp_data_t *, void *, ssize_t);
    760 } known[] = {
    761 	{ SDP_SERVICE_CLASS_DIALUP_NETWORKING,		dun_profile	    },
    762 	{ SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER,		ftrn_profile	    },
    763 	{ SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY,	hset_profile	    },
    764 	{ SDP_SERVICE_CLASS_HANDSFREE,			hf_profile	    },
    765 	{ SDP_SERVICE_CLASS_IR_MC_SYNC,			irmc_profile	    },
    766 	{ SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND,		irmc_cmd_profile    },
    767 	{ SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP,	lan_profile	    },
    768 	{ SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH,		opush_profile	    },
    769 	{ SDP_SERVICE_CLASS_SERIAL_PORT,		sp_profile	    },
    770 	{ SDP_SERVICE_CLASS_NAP,			nap_profile	    },
    771 	{ SDP_SERVICE_CLASS_GN,				gn_profile	    },
    772 	{ SDP_SERVICE_CLASS_PANU,			panu_profile	    },
    773 };
    774 
    775 uint16_t
    776 compat_register_request(server_t *srv, int fd)
    777 {
    778 	sdp_data_t d, r;
    779 	bdaddr_t bdaddr;
    780 	uint16_t class;
    781 	int i;
    782 
    783 	log_debug("compat RegisterRequest by client on fd#%d", fd);
    784 
    785 	if (!srv->fdidx[fd].control
    786 	    || !srv->fdidx[fd].priv)
    787 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    788 
    789 	srv->fdidx[fd].offset = 0;
    790 	db_unselect(srv, fd);
    791 	d.next = srv->ibuf;
    792 	d.end = srv->ibuf + srv->pdu.len;
    793 
    794 	if (d.next + sizeof(uint16_t) + sizeof(bdaddr_t) > d.end)
    795 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    796 
    797 	class = be16dec(d.next);
    798 	d.next += sizeof(uint16_t);
    799 
    800 	memcpy(&bdaddr, d.next, sizeof(bdaddr_t));
    801 	d.next += sizeof(bdaddr_t);
    802 
    803 	for (i = 0;; i++) {
    804 		if (i == __arraycount(known))
    805 			return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    806 
    807 		if (known[i].class == class)
    808 			break;
    809 	}
    810 
    811 	r.next = srv->obuf;
    812 	r.end = srv->obuf + srv->omtu;
    813 	if (!(known[i].create(&r, d.next, d.end - d.next)))
    814 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    815 
    816 	if (!db_create(srv, fd, &bdaddr, srv->handle, &r))
    817 		return SDP_ERROR_CODE_INSUFFICIENT_RESOURCES;
    818 
    819 	/* successful return */
    820 	be16enc(srv->obuf, 0x0000);
    821 	be32enc(srv->obuf + sizeof(uint16_t), srv->handle++);
    822 	srv->pdu.pid = SDP_PDU_ERROR_RESPONSE;
    823 	srv->pdu.len = sizeof(uint16_t) + sizeof(uint32_t);
    824 	return 0;
    825 }
    826 
    827 uint16_t
    828 compat_change_request(server_t *srv, int fd)
    829 {
    830 	record_t *rec;
    831 	sdp_data_t d, r;
    832 	int i;
    833 
    834 	log_debug("compat ChangeRequest by client on fd#%d", fd);
    835 
    836 	if (!srv->fdidx[fd].control
    837 	    || !srv->fdidx[fd].priv)
    838 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    839 
    840 	srv->fdidx[fd].offset = 0;
    841 	db_unselect(srv, fd);
    842 	d.next = srv->ibuf;
    843 	d.end = srv->ibuf + srv->pdu.len;
    844 
    845 	if (d.next + sizeof(uint32_t) > d.end)
    846 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    847 
    848 	db_select_handle(srv, fd, be32dec(d.next));
    849 	d.next += sizeof(uint32_t);
    850 
    851 	rec = NULL;
    852 	db_next(srv, fd, &rec);
    853 	if (rec == NULL || rec->fd != fd)
    854 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    855 
    856 	/*
    857 	 * This is rather simplistic but it works. We don't keep a
    858 	 * record of the ServiceClass but we do know the format of
    859 	 * of the stored record and where it should be. If we dont
    860 	 * find it there, just give up.
    861 	 */
    862 	r = rec->data;
    863 	r.next += 3;		/* uint16 ServiceRecordHandle	*/
    864 	r.next += 5;		/* uint32 %handle%		*/
    865 	r.next += 3;		/* uint16 ServiceClassIDList	*/
    866 	r.next += 2;		/* seq8				*/
    867 	for (i = 0;; i++) {
    868 		if (i == __arraycount(known))
    869 			return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    870 
    871 		if (sdp_match_uuid16(&r, known[i].class))
    872 			break;
    873 	}
    874 
    875 	r.next = srv->obuf;
    876 	r.end = srv->obuf + srv->omtu;
    877 	if (!(known[i].create(&r, d.next, d.end - d.next)))
    878 		return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
    879 
    880 	if (!db_create(srv, fd, &rec->bdaddr, rec->handle, &r))
    881 		return SDP_ERROR_CODE_INSUFFICIENT_RESOURCES;
    882 
    883 	db_unselect(srv, fd);
    884 
    885 	/* successful return */
    886 	be16enc(srv->obuf, 0x0000);
    887 	srv->pdu.pid = SDP_PDU_ERROR_RESPONSE;
    888 	srv->pdu.len = sizeof(uint16_t);
    889 	return 0;
    890 }
    891