sdpd-request.c revision 5bdbbb44d612746b5c19932f9da15a3ced57ff05
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2001-2002 Nokia Corporation 6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> 7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org> 8 * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com> 9 * 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30 31#include <stdio.h> 32#include <errno.h> 33#include <stdlib.h> 34#include <string.h> 35#include <limits.h> 36#include <sys/socket.h> 37 38#include <bluetooth/bluetooth.h> 39#include <bluetooth/l2cap.h> 40#include <bluetooth/sdp.h> 41#include <bluetooth/sdp_lib.h> 42 43#include <netinet/in.h> 44 45#include "sdpd.h" 46#include "log.h" 47 48#define MIN(x, y) ((x) < (y)) ? (x): (y) 49 50typedef struct _sdp_cstate_list sdp_cstate_list_t; 51 52struct _sdp_cstate_list { 53 sdp_cstate_list_t *next; 54 uint32_t timestamp; 55 sdp_buf_t buf; 56}; 57 58static sdp_cstate_list_t *cstates; 59 60// FIXME: should probably remove it when it's found 61sdp_buf_t *sdp_get_cached_rsp(sdp_cont_state_t *cstate) 62{ 63 sdp_cstate_list_t *p; 64 65 for (p = cstates; p; p = p->next) 66 if (p->timestamp == cstate->timestamp) 67 return &p->buf; 68 return 0; 69} 70 71static uint32_t sdp_cstate_alloc_buf(sdp_buf_t *buf) 72{ 73 sdp_cstate_list_t *cstate = malloc(sizeof(sdp_cstate_list_t)); 74 uint8_t *data = malloc(buf->data_size); 75 76 memcpy(data, buf->data, buf->data_size); 77 memset((char *)cstate, 0, sizeof(sdp_cstate_list_t)); 78 cstate->buf.data = data; 79 cstate->buf.data_size = buf->data_size; 80 cstate->buf.buf_size = buf->data_size; 81 cstate->timestamp = sdp_get_time(); 82 cstate->next = cstates; 83 cstates = cstate; 84 return cstate->timestamp; 85} 86 87/* Additional values for checking datatype (not in spec) */ 88#define SDP_TYPE_UUID 0xfe 89#define SDP_TYPE_ATTRID 0xff 90 91struct attrid { 92 uint8_t dtd; 93 union { 94 uint16_t uint16; 95 uint32_t uint32; 96 }; 97}; 98 99/* 100 * Generic data element sequence extractor. Builds 101 * a list whose elements are those found in the 102 * sequence. The data type of elements found in the 103 * sequence is returned in the reference pDataType 104 */ 105static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *pDataType, uint8_t expectedType) 106{ 107 uint8_t seqType; 108 int scanned, data_size = 0; 109 short numberOfElements = 0; 110 int seqlen = 0; 111 sdp_list_t *pSeq = NULL; 112 uint8_t dataType; 113 int status = 0; 114 const uint8_t *p; 115 size_t bufsize; 116 117 scanned = sdp_extract_seqtype(buf, len, &seqType, &data_size); 118 119 SDPDBG("Seq type : %d", seqType); 120 if (!scanned || (seqType != SDP_SEQ8 && seqType != SDP_SEQ16)) { 121 error("Unknown seq type"); 122 return -1; 123 } 124 p = buf + scanned; 125 bufsize = len - scanned; 126 127 SDPDBG("Data size : %d", data_size); 128 129 for (;;) { 130 char *pElem = NULL; 131 int localSeqLength = 0; 132 133 if (bufsize < sizeof(uint8_t)) { 134 SDPDBG("->Unexpected end of buffer"); 135 goto failed; 136 } 137 138 dataType = *p; 139 140 SDPDBG("Data type: 0x%02x", dataType); 141 142 if (expectedType == SDP_TYPE_UUID) { 143 if (dataType != SDP_UUID16 && dataType != SDP_UUID32 && dataType != SDP_UUID128) { 144 SDPDBG("->Unexpected Data type (expected UUID_ANY)"); 145 goto failed; 146 } 147 } else if (expectedType == SDP_TYPE_ATTRID && 148 (dataType != SDP_UINT16 && dataType != SDP_UINT32)) { 149 SDPDBG("->Unexpected Data type (expected 0x%02x or 0x%02x)", 150 SDP_UINT16, SDP_UINT32); 151 goto failed; 152 } else if (expectedType != SDP_TYPE_ATTRID && dataType != expectedType) { 153 SDPDBG("->Unexpected Data type (expected 0x%02x)", expectedType); 154 goto failed; 155 } 156 157 switch (dataType) { 158 case SDP_UINT16: 159 p += sizeof(uint8_t); 160 seqlen += sizeof(uint8_t); 161 bufsize -= sizeof(uint8_t); 162 if (bufsize < sizeof(uint16_t)) { 163 SDPDBG("->Unexpected end of buffer"); 164 goto failed; 165 } 166 167 if (expectedType == SDP_TYPE_ATTRID) { 168 struct attrid *aid; 169 aid = malloc(sizeof(struct attrid)); 170 aid->dtd = dataType; 171 bt_put_unaligned(ntohs(bt_get_unaligned((uint16_t *)p)), (uint16_t *)&aid->uint16); 172 pElem = (char *) aid; 173 } else { 174 pElem = malloc(sizeof(uint16_t)); 175 bt_put_unaligned(ntohs(bt_get_unaligned((uint16_t *)p)), (uint16_t *)pElem); 176 } 177 p += sizeof(uint16_t); 178 seqlen += sizeof(uint16_t); 179 bufsize -= sizeof(uint16_t); 180 break; 181 case SDP_UINT32: 182 p += sizeof(uint8_t); 183 seqlen += sizeof(uint8_t); 184 bufsize -= sizeof(uint8_t); 185 if (bufsize < (int)sizeof(uint32_t)) { 186 SDPDBG("->Unexpected end of buffer"); 187 goto failed; 188 } 189 190 if (expectedType == SDP_TYPE_ATTRID) { 191 struct attrid *aid; 192 aid = malloc(sizeof(struct attrid)); 193 aid->dtd = dataType; 194 bt_put_unaligned(ntohl(bt_get_unaligned((uint32_t *)p)), (uint32_t *)&aid->uint32); 195 pElem = (char *) aid; 196 } else { 197 pElem = malloc(sizeof(uint32_t)); 198 bt_put_unaligned(ntohl(bt_get_unaligned((uint32_t *)p)), (uint32_t *)pElem); 199 } 200 p += sizeof(uint32_t); 201 seqlen += sizeof(uint32_t); 202 bufsize -= sizeof(uint32_t); 203 break; 204 case SDP_UUID16: 205 case SDP_UUID32: 206 case SDP_UUID128: 207 pElem = malloc(sizeof(uuid_t)); 208 status = sdp_uuid_extract(p, bufsize, (uuid_t *) pElem, &localSeqLength); 209 if (status < 0) { 210 free(pElem); 211 goto failed; 212 } 213 seqlen += localSeqLength; 214 p += localSeqLength; 215 bufsize -= localSeqLength; 216 break; 217 default: 218 return -1; 219 } 220 if (status == 0) { 221 pSeq = sdp_list_append(pSeq, pElem); 222 numberOfElements++; 223 SDPDBG("No of elements : %d", numberOfElements); 224 225 if (seqlen == data_size) 226 break; 227 else if (seqlen > data_size || seqlen > len) 228 goto failed; 229 } else 230 free(pElem); 231 } 232 *svcReqSeq = pSeq; 233 scanned += seqlen; 234 *pDataType = dataType; 235 return scanned; 236 237failed: 238 sdp_list_free(pSeq, free); 239 return -1; 240} 241 242static int sdp_set_cstate_pdu(sdp_buf_t *buf, sdp_cont_state_t *cstate) 243{ 244 uint8_t *pdata = buf->data + buf->data_size; 245 int length = 0; 246 247 if (cstate) { 248 SDPDBG("Non null sdp_cstate_t id : 0x%x", cstate->timestamp); 249 *(uint8_t *)pdata = sizeof(sdp_cont_state_t); 250 pdata += sizeof(uint8_t); 251 length += sizeof(uint8_t); 252 memcpy(pdata, cstate, sizeof(sdp_cont_state_t)); 253 length += sizeof(sdp_cont_state_t); 254 } else { 255 // set "null" continuation state 256 *(uint8_t *)pdata = 0; 257 pdata += sizeof(uint8_t); 258 length += sizeof(uint8_t); 259 } 260 buf->data_size += length; 261 return length; 262} 263 264static int sdp_cstate_get(uint8_t *buffer, size_t len, 265 sdp_cont_state_t **cstate) 266{ 267 uint8_t cStateSize = *buffer; 268 269 SDPDBG("Continuation State size : %d", cStateSize); 270 271 if (cStateSize == 0) { 272 *cstate = NULL; 273 return 0; 274 } 275 276 buffer++; 277 len--; 278 279 if (len < sizeof(sdp_cont_state_t)) 280 return -EINVAL; 281 282 /* 283 * Check if continuation state exists, if yes attempt 284 * to get response remainder from cache, else send error 285 */ 286 287 *cstate = malloc(sizeof(sdp_cont_state_t)); 288 if (!(*cstate)) 289 return -ENOMEM; 290 291 memcpy(*cstate, buffer, sizeof(sdp_cont_state_t)); 292 293 SDPDBG("Cstate TS : 0x%x", (*cstate)->timestamp); 294 SDPDBG("Bytes sent : %d", (*cstate)->cStateValue.maxBytesSent); 295 296 return 0; 297} 298 299/* 300 * The matching process is defined as "each and every UUID 301 * specified in the "search pattern" must be present in the 302 * "target pattern". Here "search pattern" is the set of UUIDs 303 * specified by the service discovery client and "target pattern" 304 * is the set of UUIDs present in a service record. 305 * 306 * Return 1 if each and every UUID in the search 307 * pattern exists in the target pattern, 0 if the 308 * match succeeds and -1 on error. 309 */ 310static int sdp_match_uuid(sdp_list_t *search, sdp_list_t *pattern) 311{ 312 /* 313 * The target is a sorted list, so we need not look 314 * at all elements to confirm existence of an element 315 * from the search pattern 316 */ 317 int patlen = sdp_list_len(pattern); 318 319 if (patlen < sdp_list_len(search)) 320 return -1; 321 for (; search; search = search->next) { 322 uuid_t *uuid128; 323 void *data = search->data; 324 sdp_list_t *list; 325 if (data == NULL) 326 return -1; 327 328 // create 128-bit form of the search UUID 329 uuid128 = sdp_uuid_to_uuid128((uuid_t *)data); 330 list = sdp_list_find(pattern, uuid128, sdp_uuid128_cmp); 331 bt_free(uuid128); 332 if (!list) 333 return 0; 334 } 335 return 1; 336} 337 338/* 339 * Service search request PDU. This method extracts the search pattern 340 * (a sequence of UUIDs) and calls the matching function 341 * to find matching services 342 */ 343static int service_search_req(sdp_req_t *req, sdp_buf_t *buf) 344{ 345 int status = 0, i, plen, mlen, mtu, scanned; 346 sdp_list_t *pattern = NULL; 347 uint16_t expected, actual, rsp_count = 0; 348 uint8_t dtd; 349 sdp_cont_state_t *cstate = NULL; 350 uint8_t *pCacheBuffer = NULL; 351 int handleSize = 0; 352 uint32_t cStateId = 0; 353 short *pTotalRecordCount, *pCurrentRecordCount; 354 uint8_t *pdata = req->buf + sizeof(sdp_pdu_hdr_t); 355 size_t data_left = req->len - sizeof(sdp_pdu_hdr_t); 356 357 scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID); 358 359 if (scanned == -1) { 360 status = SDP_INVALID_SYNTAX; 361 goto done; 362 } 363 pdata += scanned; 364 data_left -= scanned; 365 366 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen); 367 mlen = scanned + sizeof(uint16_t) + 1; 368 // ensure we don't read past buffer 369 if (plen < mlen || plen != mlen + *(uint8_t *)(pdata+sizeof(uint16_t))) { 370 status = SDP_INVALID_PDU_SIZE; 371 goto done; 372 } 373 374 if (data_left < sizeof(uint16_t)) { 375 status = SDP_INVALID_SYNTAX; 376 goto done; 377 } 378 379 expected = ntohs(bt_get_unaligned((uint16_t *)pdata)); 380 381 SDPDBG("Expected count: %d", expected); 382 SDPDBG("Bytes scanned : %d", scanned); 383 384 pdata += sizeof(uint16_t); 385 data_left -= sizeof(uint16_t); 386 387 /* 388 * Check if continuation state exists, if yes attempt 389 * to get rsp remainder from cache, else send error 390 */ 391 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { 392 status = SDP_INVALID_SYNTAX; 393 goto done; 394 } 395 396 mtu = req->mtu - sizeof(sdp_pdu_hdr_t) - sizeof(uint16_t) - sizeof(uint16_t) - SDP_CONT_STATE_SIZE; 397 actual = MIN(expected, mtu >> 2); 398 399 /* make space in the rsp buffer for total and current record counts */ 400 pdata = buf->data; 401 402 /* total service record count = 0 */ 403 pTotalRecordCount = (short *)pdata; 404 bt_put_unaligned(0, (uint16_t *)pdata); 405 pdata += sizeof(uint16_t); 406 buf->data_size += sizeof(uint16_t); 407 408 /* current service record count = 0 */ 409 pCurrentRecordCount = (short *)pdata; 410 bt_put_unaligned(0, (uint16_t *)pdata); 411 pdata += sizeof(uint16_t); 412 buf->data_size += sizeof(uint16_t); 413 414 if (cstate == NULL) { 415 /* for every record in the DB, do a pattern search */ 416 sdp_list_t *list = sdp_get_record_list(); 417 418 handleSize = 0; 419 for (; list && rsp_count < expected; list = list->next) { 420 sdp_record_t *rec = (sdp_record_t *) list->data; 421 422 SDPDBG("Checking svcRec : 0x%x", rec->handle); 423 424 if (sdp_match_uuid(pattern, rec->pattern) > 0 && 425 sdp_check_access(rec->handle, &req->device)) { 426 rsp_count++; 427 bt_put_unaligned(htonl(rec->handle), (uint32_t *)pdata); 428 pdata += sizeof(uint32_t); 429 handleSize += sizeof(uint32_t); 430 } 431 } 432 433 SDPDBG("Match count: %d", rsp_count); 434 435 buf->data_size += handleSize; 436 bt_put_unaligned(htons(rsp_count), (uint16_t *)pTotalRecordCount); 437 bt_put_unaligned(htons(rsp_count), (uint16_t *)pCurrentRecordCount); 438 439 if (rsp_count > actual) { 440 /* cache the rsp and generate a continuation state */ 441 cStateId = sdp_cstate_alloc_buf(buf); 442 /* 443 * subtract handleSize since we now send only 444 * a subset of handles 445 */ 446 buf->data_size -= handleSize; 447 } else { 448 /* NULL continuation state */ 449 sdp_set_cstate_pdu(buf, NULL); 450 } 451 } 452 453 /* under both the conditions below, the rsp buffer is not built yet */ 454 if (cstate || cStateId > 0) { 455 short lastIndex = 0; 456 457 if (cstate) { 458 /* 459 * Get the previous sdp_cont_state_t and obtain 460 * the cached rsp 461 */ 462 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate); 463 if (pCache) { 464 pCacheBuffer = pCache->data; 465 /* get the rsp_count from the cached buffer */ 466 rsp_count = ntohs(bt_get_unaligned((uint16_t *)pCacheBuffer)); 467 468 /* get index of the last sdp_record_t sent */ 469 lastIndex = cstate->cStateValue.lastIndexSent; 470 } else { 471 status = SDP_INVALID_CSTATE; 472 goto done; 473 } 474 } else { 475 pCacheBuffer = buf->data; 476 lastIndex = 0; 477 } 478 479 /* 480 * Set the local buffer pointer to after the 481 * current record count and increment the cached 482 * buffer pointer to beyond the counters 483 */ 484 pdata = (uint8_t *) pCurrentRecordCount + sizeof(uint16_t); 485 486 /* increment beyond the totalCount and the currentCount */ 487 pCacheBuffer += 2 * sizeof(uint16_t); 488 489 if (cstate) { 490 handleSize = 0; 491 for (i = lastIndex; (i - lastIndex) < actual && i < rsp_count; i++) { 492 bt_put_unaligned(bt_get_unaligned((uint32_t *)(pCacheBuffer + i * sizeof(uint32_t))), (uint32_t *)pdata); 493 pdata += sizeof(uint32_t); 494 handleSize += sizeof(uint32_t); 495 } 496 } else { 497 handleSize = actual << 2; 498 i = actual; 499 } 500 501 buf->data_size += handleSize; 502 bt_put_unaligned(htons(rsp_count), (uint16_t *)pTotalRecordCount); 503 bt_put_unaligned(htons(i - lastIndex), (uint16_t *)pCurrentRecordCount); 504 505 if (i == rsp_count) { 506 /* set "null" continuationState */ 507 sdp_set_cstate_pdu(buf, NULL); 508 } else { 509 /* 510 * there's more: set lastIndexSent to 511 * the new value and move on 512 */ 513 sdp_cont_state_t newState; 514 515 SDPDBG("Setting non-NULL sdp_cstate_t"); 516 517 if (cstate) 518 memcpy(&newState, cstate, sizeof(sdp_cont_state_t)); 519 else { 520 memset(&newState, 0, sizeof(sdp_cont_state_t)); 521 newState.timestamp = cStateId; 522 } 523 newState.cStateValue.lastIndexSent = i; 524 sdp_set_cstate_pdu(buf, &newState); 525 } 526 } 527 528done: 529 free(cstate); 530 if (pattern) 531 sdp_list_free(pattern, free); 532 533 return status; 534} 535 536/* 537 * Extract attribute identifiers from the request PDU. 538 * Clients could request a subset of attributes (by id) 539 * from a service record, instead of the whole set. The 540 * requested identifiers are present in the PDU form of 541 * the request 542 */ 543static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, sdp_buf_t *buf) 544{ 545 sdp_buf_t pdu; 546 547 if (!rec) 548 return SDP_INVALID_RECORD_HANDLE; 549 550 if (seq) { 551 SDPDBG("Entries in attr seq : %d", sdp_list_len(seq)); 552 } else { 553 SDPDBG("NULL attribute descriptor"); 554 } 555 556 if (seq == NULL) { 557 SDPDBG("Attribute sequence is NULL"); 558 return 0; 559 } 560 561 sdp_gen_record_pdu(rec, &pdu); 562 563 for (; seq; seq = seq->next) { 564 struct attrid *aid = seq->data; 565 566 SDPDBG("AttrDataType : %d", aid->dtd); 567 568 if (aid->dtd == SDP_UINT16) { 569 uint16_t attr = bt_get_unaligned((uint16_t *)&aid->uint16); 570 sdp_data_t *a = (sdp_data_t *)sdp_data_get(rec, attr); 571 if (a) 572 sdp_append_to_pdu(buf, a); 573 } else if (aid->dtd == SDP_UINT32) { 574 uint32_t range = bt_get_unaligned((uint32_t *)&aid->uint32); 575 uint16_t attr; 576 uint16_t low = (0xffff0000 & range) >> 16; 577 uint16_t high = 0x0000ffff & range; 578 sdp_data_t *data; 579 580 SDPDBG("attr range : 0x%x", range); 581 SDPDBG("Low id : 0x%x", low); 582 SDPDBG("High id : 0x%x", high); 583 584 if (low == 0x0000 && high == 0xffff && pdu.data_size <= buf->buf_size) { 585 /* copy it */ 586 memcpy(buf->data, pdu.data, pdu.data_size); 587 buf->data_size = pdu.data_size; 588 break; 589 } 590 /* (else) sub-range of attributes */ 591 for (attr = low; attr < high; attr++) { 592 data = sdp_data_get(rec, attr); 593 if (data) 594 sdp_append_to_pdu(buf, data); 595 } 596 data = sdp_data_get(rec, high); 597 if (data) 598 sdp_append_to_pdu(buf, data); 599 } else { 600 error("Unexpected data type : 0x%x", aid->dtd); 601 error("Expect uint16_t or uint32_t"); 602 free(pdu.data); 603 return SDP_INVALID_SYNTAX; 604 } 605 } 606 607 free(pdu.data); 608 609 return 0; 610} 611 612/* 613 * A request for the attributes of a service record. 614 * First check if the service record (specified by 615 * service record handle) exists, then call the attribute 616 * streaming function 617 */ 618static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf) 619{ 620 sdp_cont_state_t *cstate = NULL; 621 uint8_t *pResponse = NULL; 622 short cstate_size = 0; 623 sdp_list_t *seq = NULL; 624 uint8_t dtd = 0; 625 int scanned = 0; 626 unsigned int max_rsp_size; 627 int status = 0, plen, mlen; 628 uint8_t *pdata = req->buf + sizeof(sdp_pdu_hdr_t); 629 size_t data_left = req->len - sizeof(sdp_pdu_hdr_t); 630 uint32_t handle; 631 632 if (data_left < sizeof(uint32_t)) { 633 status = SDP_INVALID_SYNTAX; 634 goto done; 635 } 636 637 handle = ntohl(bt_get_unaligned((uint32_t *)pdata)); 638 639 pdata += sizeof(uint32_t); 640 data_left -= sizeof(uint32_t); 641 642 if (data_left < sizeof(uint16_t)) { 643 status = SDP_INVALID_SYNTAX; 644 goto done; 645 } 646 647 max_rsp_size = ntohs(bt_get_unaligned((uint16_t *)pdata)); 648 649 pdata += sizeof(uint16_t); 650 data_left -= sizeof(uint16_t); 651 652 if (data_left < sizeof(sdp_pdu_hdr_t)) { 653 status = SDP_INVALID_SYNTAX; 654 goto done; 655 } 656 657 /* extract the attribute list */ 658 scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID); 659 if (scanned == -1) { 660 status = SDP_INVALID_SYNTAX; 661 goto done; 662 } 663 pdata += scanned; 664 data_left -= scanned; 665 666 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen); 667 mlen = scanned + sizeof(uint32_t) + sizeof(uint16_t) + 1; 668 // ensure we don't read past buffer 669 if (plen < mlen || plen != mlen + *(uint8_t *)pdata) { 670 status = SDP_INVALID_PDU_SIZE; 671 goto done; 672 } 673 674 /* 675 * if continuation state exists, attempt 676 * to get rsp remainder from cache, else send error 677 */ 678 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { 679 status = SDP_INVALID_SYNTAX; 680 goto done; 681 } 682 683 SDPDBG("SvcRecHandle : 0x%x", handle); 684 SDPDBG("max_rsp_size : %d", max_rsp_size); 685 686 /* 687 * Check that max_rsp_size is within valid range 688 * a minimum size of 0x0007 has to be used for data field 689 */ 690 if (max_rsp_size < 0x0007) { 691 status = SDP_INVALID_SYNTAX; 692 goto done; 693 } 694 695 /* 696 * Calculate Attribute size acording to MTU 697 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t)) 698 */ 699 max_rsp_size = MIN(max_rsp_size, req->mtu - sizeof(sdp_pdu_hdr_t) - 700 sizeof(uint32_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t)); 701 702 /* pull header for AttributeList byte count */ 703 buf->data += sizeof(uint16_t); 704 buf->buf_size -= sizeof(uint16_t); 705 706 if (cstate) { 707 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate); 708 709 SDPDBG("Obtained cached rsp : %p", pCache); 710 711 if (pCache) { 712 short sent = MIN(max_rsp_size, pCache->data_size - cstate->cStateValue.maxBytesSent); 713 pResponse = pCache->data; 714 memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent); 715 buf->data_size += sent; 716 cstate->cStateValue.maxBytesSent += sent; 717 718 SDPDBG("Response size : %d sending now : %d bytes sent so far : %d", 719 pCache->data_size, sent, cstate->cStateValue.maxBytesSent); 720 if (cstate->cStateValue.maxBytesSent == pCache->data_size) 721 cstate_size = sdp_set_cstate_pdu(buf, NULL); 722 else 723 cstate_size = sdp_set_cstate_pdu(buf, cstate); 724 } else { 725 status = SDP_INVALID_CSTATE; 726 error("NULL cache buffer and non-NULL continuation state"); 727 } 728 } else { 729 sdp_record_t *rec = sdp_record_find(handle); 730 status = extract_attrs(rec, seq, buf); 731 if (buf->data_size > max_rsp_size) { 732 sdp_cont_state_t newState; 733 734 memset((char *)&newState, 0, sizeof(sdp_cont_state_t)); 735 newState.timestamp = sdp_cstate_alloc_buf(buf); 736 /* 737 * Reset the buffer size to the maximum expected and 738 * set the sdp_cont_state_t 739 */ 740 SDPDBG("Creating continuation state of size : %d", buf->data_size); 741 buf->data_size = max_rsp_size; 742 newState.cStateValue.maxBytesSent = max_rsp_size; 743 cstate_size = sdp_set_cstate_pdu(buf, &newState); 744 } else { 745 if (buf->data_size == 0) 746 sdp_append_to_buf(buf, 0, 0); 747 cstate_size = sdp_set_cstate_pdu(buf, NULL); 748 } 749 } 750 751 // push header 752 buf->data -= sizeof(uint16_t); 753 buf->buf_size += sizeof(uint16_t); 754 755done: 756 free(cstate); 757 if (seq) 758 sdp_list_free(seq, free); 759 if (status) 760 return status; 761 762 /* set attribute list byte count */ 763 bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data); 764 buf->data_size += sizeof(uint16_t); 765 return 0; 766} 767 768/* 769 * combined service search and attribute extraction 770 */ 771static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf) 772{ 773 int status = 0, plen, totscanned; 774 uint8_t *pdata, *pResponse = NULL; 775 unsigned int max; 776 int scanned, rsp_count = 0; 777 sdp_list_t *pattern = NULL, *seq = NULL, *svcList; 778 sdp_cont_state_t *cstate = NULL; 779 short cstate_size = 0; 780 uint8_t dtd = 0; 781 sdp_buf_t tmpbuf; 782 size_t data_left = req->len; 783 784 tmpbuf.data = NULL; 785 pdata = req->buf + sizeof(sdp_pdu_hdr_t); 786 data_left = req->len - sizeof(sdp_pdu_hdr_t); 787 scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID); 788 if (scanned == -1) { 789 status = SDP_INVALID_SYNTAX; 790 goto done; 791 } 792 totscanned = scanned; 793 794 SDPDBG("Bytes scanned: %d", scanned); 795 796 pdata += scanned; 797 data_left -= scanned; 798 799 if (data_left < sizeof(uint16_t)) { 800 status = SDP_INVALID_SYNTAX; 801 goto done; 802 } 803 804 max = ntohs(bt_get_unaligned((uint16_t *)pdata)); 805 806 pdata += sizeof(uint16_t); 807 data_left -= sizeof(uint16_t); 808 809 SDPDBG("Max Attr expected: %d", max); 810 811 if (data_left < sizeof(sdp_pdu_hdr_t)) { 812 status = SDP_INVALID_SYNTAX; 813 goto done; 814 } 815 816 /* extract the attribute list */ 817 scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID); 818 if (scanned == -1) { 819 status = SDP_INVALID_SYNTAX; 820 goto done; 821 } 822 823 pdata += scanned; 824 data_left -= scanned; 825 826 totscanned += scanned + sizeof(uint16_t) + 1; 827 828 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen); 829 if (plen < totscanned || plen != totscanned + *(uint8_t *)pdata) { 830 status = SDP_INVALID_PDU_SIZE; 831 goto done; 832 } 833 834 /* 835 * if continuation state exists attempt 836 * to get rsp remainder from cache, else send error 837 */ 838 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) { 839 status = SDP_INVALID_SYNTAX; 840 goto done; 841 } 842 843 svcList = sdp_get_record_list(); 844 845 tmpbuf.data = malloc(USHRT_MAX); 846 tmpbuf.data_size = 0; 847 tmpbuf.buf_size = USHRT_MAX; 848 memset(tmpbuf.data, 0, USHRT_MAX); 849 850 /* 851 * Calculate Attribute size acording to MTU 852 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t)) 853 */ 854 max = MIN(max, req->mtu - sizeof(sdp_pdu_hdr_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t)); 855 856 /* pull header for AttributeList byte count */ 857 buf->data += sizeof(uint16_t); 858 buf->buf_size -= sizeof(uint16_t); 859 860 if (cstate == NULL) { 861 /* no continuation state -> create new response */ 862 sdp_list_t *p; 863 for (p = svcList; p; p = p->next) { 864 sdp_record_t *rec = (sdp_record_t *) p->data; 865 if (sdp_match_uuid(pattern, rec->pattern) > 0 && 866 sdp_check_access(rec->handle, &req->device)) { 867 rsp_count++; 868 status = extract_attrs(rec, seq, &tmpbuf); 869 870 SDPDBG("Response count : %d", rsp_count); 871 SDPDBG("Local PDU size : %d", tmpbuf.data_size); 872 if (status) { 873 SDPDBG("Extract attr from record returns err"); 874 break; 875 } 876 if (buf->data_size + tmpbuf.data_size < buf->buf_size) { 877 // to be sure no relocations 878 sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size); 879 tmpbuf.data_size = 0; 880 memset(tmpbuf.data, 0, USHRT_MAX); 881 } else { 882 error("Relocation needed"); 883 break; 884 } 885 SDPDBG("Net PDU size : %d", buf->data_size); 886 } 887 } 888 if (buf->data_size > max) { 889 sdp_cont_state_t newState; 890 891 memset((char *)&newState, 0, sizeof(sdp_cont_state_t)); 892 newState.timestamp = sdp_cstate_alloc_buf(buf); 893 /* 894 * Reset the buffer size to the maximum expected and 895 * set the sdp_cont_state_t 896 */ 897 buf->data_size = max; 898 newState.cStateValue.maxBytesSent = max; 899 cstate_size = sdp_set_cstate_pdu(buf, &newState); 900 } else 901 cstate_size = sdp_set_cstate_pdu(buf, NULL); 902 } else { 903 /* continuation State exists -> get from cache */ 904 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate); 905 if (pCache) { 906 uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent); 907 pResponse = pCache->data; 908 memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent); 909 buf->data_size += sent; 910 cstate->cStateValue.maxBytesSent += sent; 911 if (cstate->cStateValue.maxBytesSent == pCache->data_size) 912 cstate_size = sdp_set_cstate_pdu(buf, NULL); 913 else 914 cstate_size = sdp_set_cstate_pdu(buf, cstate); 915 } else { 916 status = SDP_INVALID_CSTATE; 917 SDPDBG("Non-null continuation state, but null cache buffer"); 918 } 919 } 920 921 if (!rsp_count && !cstate) { 922 // found nothing 923 buf->data_size = 0; 924 sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size); 925 sdp_set_cstate_pdu(buf, NULL); 926 } 927 928 // push header 929 buf->data -= sizeof(uint16_t); 930 buf->buf_size += sizeof(uint16_t); 931 932 if (!status) { 933 /* set attribute list byte count */ 934 bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data); 935 buf->data_size += sizeof(uint16_t); 936 } 937 938done: 939 free(cstate); 940 free(tmpbuf.data); 941 if (pattern) 942 sdp_list_free(pattern, free); 943 if (seq) 944 sdp_list_free(seq, free); 945 return status; 946} 947 948/* 949 * Top level request processor. Calls the appropriate processing 950 * function based on request type. Handles service registration 951 * client requests also. 952 */ 953static void process_request(sdp_req_t *req) 954{ 955 sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)req->buf; 956 sdp_pdu_hdr_t *rsphdr; 957 sdp_buf_t rsp; 958 uint8_t *buf = malloc(USHRT_MAX); 959 int sent = 0; 960 int status = SDP_INVALID_SYNTAX; 961 962 memset(buf, 0, USHRT_MAX); 963 rsp.data = buf + sizeof(sdp_pdu_hdr_t); 964 rsp.data_size = 0; 965 rsp.buf_size = USHRT_MAX - sizeof(sdp_pdu_hdr_t); 966 rsphdr = (sdp_pdu_hdr_t *)buf; 967 968 if (ntohs(reqhdr->plen) != req->len - sizeof(sdp_pdu_hdr_t)) { 969 status = SDP_INVALID_PDU_SIZE; 970 goto send_rsp; 971 } 972 switch (reqhdr->pdu_id) { 973 case SDP_SVC_SEARCH_REQ: 974 SDPDBG("Got a svc srch req"); 975 status = service_search_req(req, &rsp); 976 rsphdr->pdu_id = SDP_SVC_SEARCH_RSP; 977 break; 978 case SDP_SVC_ATTR_REQ: 979 SDPDBG("Got a svc attr req"); 980 status = service_attr_req(req, &rsp); 981 rsphdr->pdu_id = SDP_SVC_ATTR_RSP; 982 break; 983 case SDP_SVC_SEARCH_ATTR_REQ: 984 SDPDBG("Got a svc srch attr req"); 985 status = service_search_attr_req(req, &rsp); 986 rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP; 987 break; 988 /* Following requests are allowed only for local connections */ 989 case SDP_SVC_REGISTER_REQ: 990 SDPDBG("Service register request"); 991 if (req->local) { 992 status = service_register_req(req, &rsp); 993 rsphdr->pdu_id = SDP_SVC_REGISTER_RSP; 994 } 995 break; 996 case SDP_SVC_UPDATE_REQ: 997 SDPDBG("Service update request"); 998 if (req->local) { 999 status = service_update_req(req, &rsp); 1000 rsphdr->pdu_id = SDP_SVC_UPDATE_RSP; 1001 } 1002 break; 1003 case SDP_SVC_REMOVE_REQ: 1004 SDPDBG("Service removal request"); 1005 if (req->local) { 1006 status = service_remove_req(req, &rsp); 1007 rsphdr->pdu_id = SDP_SVC_REMOVE_RSP; 1008 } 1009 break; 1010 default: 1011 error("Unknown PDU ID : 0x%x received", reqhdr->pdu_id); 1012 status = SDP_INVALID_SYNTAX; 1013 break; 1014 } 1015 1016send_rsp: 1017 if (status) { 1018 rsphdr->pdu_id = SDP_ERROR_RSP; 1019 bt_put_unaligned(htons(status), (uint16_t *)rsp.data); 1020 rsp.data_size = sizeof(uint16_t); 1021 } 1022 1023 SDPDBG("Sending rsp. status %d", status); 1024 1025 rsphdr->tid = reqhdr->tid; 1026 rsphdr->plen = htons(rsp.data_size); 1027 1028 /* point back to the real buffer start and set the real rsp length */ 1029 rsp.data_size += sizeof(sdp_pdu_hdr_t); 1030 rsp.data = buf; 1031 1032 /* stream the rsp PDU */ 1033 sent = send(req->sock, rsp.data, rsp.data_size, 0); 1034 1035 SDPDBG("Bytes Sent : %d", sent); 1036 1037 free(rsp.data); 1038 free(req->buf); 1039} 1040 1041void handle_request(int sk, uint8_t *data, int len) 1042{ 1043 struct sockaddr_l2 sa; 1044 socklen_t size; 1045 sdp_req_t req; 1046 1047 size = sizeof(sa); 1048 if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0) { 1049 error("getpeername: %s", strerror(errno)); 1050 return; 1051 } 1052 1053 if (sa.l2_family == AF_BLUETOOTH) { 1054 struct l2cap_options lo; 1055 1056 memset(&lo, 0, sizeof(lo)); 1057 size = sizeof(lo); 1058 1059 if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &lo, &size) < 0) { 1060 error("getsockopt: %s", strerror(errno)); 1061 return; 1062 } 1063 1064 bacpy(&req.bdaddr, &sa.l2_bdaddr); 1065 req.mtu = lo.omtu; 1066 req.local = 0; 1067 memset(&sa, 0, sizeof(sa)); 1068 size = sizeof(sa); 1069 1070 if (getsockname(sk, (struct sockaddr *) &sa, &size) < 0) { 1071 error("getsockname: %s", strerror(errno)); 1072 return; 1073 } 1074 1075 bacpy(&req.device, &sa.l2_bdaddr); 1076 } else { 1077 bacpy(&req.device, BDADDR_ANY); 1078 bacpy(&req.bdaddr, BDADDR_LOCAL); 1079 req.mtu = 2048; 1080 req.local = 1; 1081 } 1082 1083 req.sock = sk; 1084 req.buf = data; 1085 req.len = len; 1086 1087 process_request(&req); 1088} 1089