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