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