3 * BlueZ - Bluetooth protocol stack for Linux
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>
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.
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.
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
36 #include "lib/bluetooth.h"
37 #include "lib/l2cap.h"
39 #include "lib/sdp_lib.h"
41 #include "src/shared/util.h"
49 uint16_t maxBytesSent;
50 uint16_t lastIndexSent;
54 #define SDP_CONT_STATE_SIZE (sizeof(uint8_t) + sizeof(sdp_cont_state_t))
56 #define MIN(x, y) ((x) < (y)) ? (x): (y)
58 typedef struct _sdp_cstate_list sdp_cstate_list_t;
60 struct _sdp_cstate_list {
61 sdp_cstate_list_t *next;
66 static sdp_cstate_list_t *cstates;
68 /* FIXME: should probably remove it when it's found */
69 static sdp_buf_t *sdp_get_cached_rsp(sdp_cont_state_t *cstate)
73 for (p = cstates; p; p = p->next)
74 if (p->timestamp == cstate->timestamp)
79 static uint32_t sdp_cstate_alloc_buf(sdp_buf_t *buf)
81 sdp_cstate_list_t *cstate = malloc(sizeof(sdp_cstate_list_t));
82 uint8_t *data = malloc(buf->data_size);
84 memcpy(data, buf->data, buf->data_size);
85 memset((char *)cstate, 0, sizeof(sdp_cstate_list_t));
86 cstate->buf.data = data;
87 cstate->buf.data_size = buf->data_size;
88 cstate->buf.buf_size = buf->data_size;
89 cstate->timestamp = sdp_get_time();
90 cstate->next = cstates;
92 return cstate->timestamp;
95 /* Additional values for checking datatype (not in spec) */
96 #define SDP_TYPE_UUID 0xfe
97 #define SDP_TYPE_ATTRID 0xff
108 * Generic data element sequence extractor. Builds
109 * a list whose elements are those found in the
110 * sequence. The data type of elements found in the
111 * sequence is returned in the reference pDataType
113 static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *pDataType, uint8_t expectedType)
116 int scanned, data_size = 0;
117 short numberOfElements = 0;
119 sdp_list_t *pSeq = NULL;
125 scanned = sdp_extract_seqtype(buf, len, &seqType, &data_size);
127 SDPDBG("Seq type : %d", seqType);
128 if (!scanned || (seqType != SDP_SEQ8 && seqType != SDP_SEQ16)) {
129 error("Unknown seq type");
133 bufsize = len - scanned;
135 SDPDBG("Data size : %d", data_size);
139 int localSeqLength = 0;
142 if (bufsize < sizeof(uint8_t)) {
143 SDPDBG("->Unexpected end of buffer");
149 SDPDBG("Data type: 0x%02x", dataType);
151 if (expectedType == SDP_TYPE_UUID) {
152 if (dataType != SDP_UUID16 && dataType != SDP_UUID32 && dataType != SDP_UUID128) {
153 SDPDBG("->Unexpected Data type (expected UUID_ANY)");
156 } else if (expectedType == SDP_TYPE_ATTRID &&
157 (dataType != SDP_UINT16 && dataType != SDP_UINT32)) {
158 SDPDBG("->Unexpected Data type (expected 0x%02x or 0x%02x)",
159 SDP_UINT16, SDP_UINT32);
161 } else if (expectedType != SDP_TYPE_ATTRID && dataType != expectedType) {
162 SDPDBG("->Unexpected Data type (expected 0x%02x)", expectedType);
168 p += sizeof(uint8_t);
169 seqlen += sizeof(uint8_t);
170 bufsize -= sizeof(uint8_t);
171 if (bufsize < sizeof(uint16_t)) {
172 SDPDBG("->Unexpected end of buffer");
176 if (expectedType == SDP_TYPE_ATTRID) {
178 aid = malloc(sizeof(struct attrid));
180 aid->uint16 = get_be16(p);
181 pElem = (char *) aid;
185 memcpy(&tmp, p, sizeof(tmp));
187 pElem = malloc(sizeof(uint16_t));
188 put_be16(tmp, pElem);
190 p += sizeof(uint16_t);
191 seqlen += sizeof(uint16_t);
192 bufsize -= sizeof(uint16_t);
195 p += sizeof(uint8_t);
196 seqlen += sizeof(uint8_t);
197 bufsize -= sizeof(uint8_t);
198 if (bufsize < (int)sizeof(uint32_t)) {
199 SDPDBG("->Unexpected end of buffer");
203 if (expectedType == SDP_TYPE_ATTRID) {
205 aid = malloc(sizeof(struct attrid));
207 aid->uint32 = get_be32(p);
209 pElem = (char *) aid;
213 memcpy(&tmp, p, sizeof(tmp));
215 pElem = malloc(sizeof(uint32_t));
216 put_be32(tmp, pElem);
218 p += sizeof(uint32_t);
219 seqlen += sizeof(uint32_t);
220 bufsize -= sizeof(uint32_t);
225 puuid = malloc(sizeof(uuid_t));
226 status = sdp_uuid_extract(p, bufsize, puuid, &localSeqLength);
232 pElem = (char *) puuid;
233 seqlen += localSeqLength;
235 bufsize -= localSeqLength;
241 pSeq = sdp_list_append(pSeq, pElem);
243 SDPDBG("No of elements : %d", numberOfElements);
245 if (seqlen == data_size)
247 else if (seqlen > data_size || seqlen > len)
254 *pDataType = dataType;
258 sdp_list_free(pSeq, free);
262 static int sdp_set_cstate_pdu(sdp_buf_t *buf, sdp_cont_state_t *cstate)
264 uint8_t *pdata = buf->data + buf->data_size;
268 SDPDBG("Non null sdp_cstate_t id : 0x%x", cstate->timestamp);
269 *pdata = sizeof(sdp_cont_state_t);
270 pdata += sizeof(uint8_t);
271 length += sizeof(uint8_t);
272 memcpy(pdata, cstate, sizeof(sdp_cont_state_t));
273 length += sizeof(sdp_cont_state_t);
275 /* set "null" continuation state */
277 length += sizeof(uint8_t);
279 buf->data_size += length;
283 static int sdp_cstate_get(uint8_t *buffer, size_t len,
284 sdp_cont_state_t **cstate)
286 uint8_t cStateSize = *buffer;
288 SDPDBG("Continuation State size : %d", cStateSize);
290 if (cStateSize == 0) {
298 if (len < sizeof(sdp_cont_state_t))
302 * Check if continuation state exists, if yes attempt
303 * to get response remainder from cache, else send error
306 *cstate = malloc(sizeof(sdp_cont_state_t));
310 memcpy(*cstate, buffer, sizeof(sdp_cont_state_t));
312 SDPDBG("Cstate TS : 0x%x", (*cstate)->timestamp);
313 SDPDBG("Bytes sent : %d", (*cstate)->cStateValue.maxBytesSent);
319 * The matching process is defined as "each and every UUID
320 * specified in the "search pattern" must be present in the
321 * "target pattern". Here "search pattern" is the set of UUIDs
322 * specified by the service discovery client and "target pattern"
323 * is the set of UUIDs present in a service record.
325 * Return 1 if each and every UUID in the search
326 * pattern exists in the target pattern, 0 if the
327 * match succeeds and -1 on error.
329 static int sdp_match_uuid(sdp_list_t *search, sdp_list_t *pattern)
332 * The target is a sorted list, so we need not look
333 * at all elements to confirm existence of an element
334 * from the search pattern
336 int patlen = sdp_list_len(pattern);
338 if (patlen < sdp_list_len(search))
340 for (; search; search = search->next) {
342 void *data = search->data;
347 /* create 128-bit form of the search UUID */
348 uuid128 = sdp_uuid_to_uuid128((uuid_t *)data);
349 list = sdp_list_find(pattern, uuid128, sdp_uuid128_cmp);
358 * Service search request PDU. This method extracts the search pattern
359 * (a sequence of UUIDs) and calls the matching function
360 * to find matching services
362 static int service_search_req(sdp_req_t *req, sdp_buf_t *buf)
364 int status = 0, i, plen, mlen, mtu, scanned;
365 sdp_list_t *pattern = NULL;
366 uint16_t expected, actual, rsp_count = 0;
368 sdp_cont_state_t *cstate = NULL;
369 uint8_t *pCacheBuffer = NULL;
371 uint32_t cStateId = 0;
372 uint8_t *pTotalRecordCount, *pCurrentRecordCount;
373 uint8_t *pdata = req->buf + sizeof(sdp_pdu_hdr_t);
374 size_t data_left = req->len - sizeof(sdp_pdu_hdr_t);
376 scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID);
379 status = SDP_INVALID_SYNTAX;
383 data_left -= scanned;
385 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
386 mlen = scanned + sizeof(uint16_t) + 1;
387 /* ensure we don't read past buffer */
388 if (plen < mlen || plen != mlen + *(uint8_t *)(pdata+sizeof(uint16_t))) {
389 status = SDP_INVALID_SYNTAX;
393 if (data_left < sizeof(uint16_t)) {
394 status = SDP_INVALID_SYNTAX;
398 expected = get_be16(pdata);
400 SDPDBG("Expected count: %d", expected);
401 SDPDBG("Bytes scanned : %d", scanned);
403 pdata += sizeof(uint16_t);
404 data_left -= sizeof(uint16_t);
407 * Check if continuation state exists, if yes attempt
408 * to get rsp remainder from cache, else send error
410 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
411 status = SDP_INVALID_SYNTAX;
415 mtu = req->mtu - sizeof(sdp_pdu_hdr_t) - sizeof(uint16_t) - sizeof(uint16_t) - SDP_CONT_STATE_SIZE;
416 actual = MIN(expected, mtu >> 2);
418 /* make space in the rsp buffer for total and current record counts */
421 /* total service record count = 0 */
422 pTotalRecordCount = pdata;
424 pdata += sizeof(uint16_t);
425 buf->data_size += sizeof(uint16_t);
427 /* current service record count = 0 */
428 pCurrentRecordCount = pdata;
430 pdata += sizeof(uint16_t);
431 buf->data_size += sizeof(uint16_t);
433 if (cstate == NULL) {
434 /* for every record in the DB, do a pattern search */
435 sdp_list_t *list = sdp_get_record_list();
438 for (; list && rsp_count < expected; list = list->next) {
439 sdp_record_t *rec = list->data;
441 SDPDBG("Checking svcRec : 0x%x", rec->handle);
443 if (sdp_match_uuid(pattern, rec->pattern) > 0 &&
444 sdp_check_access(rec->handle, &req->device)) {
446 put_be32(rec->handle, pdata);
447 pdata += sizeof(uint32_t);
448 handleSize += sizeof(uint32_t);
452 SDPDBG("Match count: %d", rsp_count);
454 buf->data_size += handleSize;
455 put_be16(rsp_count, pTotalRecordCount);
456 put_be16(rsp_count, pCurrentRecordCount);
458 if (rsp_count > actual) {
459 /* cache the rsp and generate a continuation state */
460 cStateId = sdp_cstate_alloc_buf(buf);
462 * subtract handleSize since we now send only
463 * a subset of handles
465 buf->data_size -= handleSize;
467 /* NULL continuation state */
468 sdp_set_cstate_pdu(buf, NULL);
472 /* under both the conditions below, the rsp buffer is not built yet */
473 if (cstate || cStateId > 0) {
478 * Get the previous sdp_cont_state_t and obtain
481 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
483 pCacheBuffer = pCache->data;
484 /* get the rsp_count from the cached buffer */
485 rsp_count = get_be16(pCacheBuffer);
487 /* get index of the last sdp_record_t sent */
488 lastIndex = cstate->cStateValue.lastIndexSent;
490 status = SDP_INVALID_CSTATE;
494 pCacheBuffer = buf->data;
499 * Set the local buffer pointer to after the
500 * current record count and increment the cached
501 * buffer pointer to beyond the counters
503 pdata = pCurrentRecordCount + sizeof(uint16_t);
505 /* increment beyond the totalCount and the currentCount */
506 pCacheBuffer += 2 * sizeof(uint16_t);
510 for (i = lastIndex; (i - lastIndex) < actual && i < rsp_count; i++) {
511 memcpy(pdata, pCacheBuffer + i * sizeof(uint32_t), sizeof(uint32_t));
512 pdata += sizeof(uint32_t);
513 handleSize += sizeof(uint32_t);
516 handleSize = actual << 2;
520 buf->data_size += handleSize;
521 put_be16(rsp_count, pTotalRecordCount);
522 put_be16(i - lastIndex, pCurrentRecordCount);
524 if (i == rsp_count) {
525 /* set "null" continuationState */
526 sdp_set_cstate_pdu(buf, NULL);
529 * there's more: set lastIndexSent to
530 * the new value and move on
532 sdp_cont_state_t newState;
534 SDPDBG("Setting non-NULL sdp_cstate_t");
537 memcpy(&newState, cstate, sizeof(sdp_cont_state_t));
539 memset(&newState, 0, sizeof(sdp_cont_state_t));
540 newState.timestamp = cStateId;
542 newState.cStateValue.lastIndexSent = i;
543 sdp_set_cstate_pdu(buf, &newState);
550 sdp_list_free(pattern, free);
556 * Extract attribute identifiers from the request PDU.
557 * Clients could request a subset of attributes (by id)
558 * from a service record, instead of the whole set. The
559 * requested identifiers are present in the PDU form of
562 static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, sdp_buf_t *buf)
567 return SDP_INVALID_RECORD_HANDLE;
570 SDPDBG("Attribute sequence is NULL");
574 SDPDBG("Entries in attr seq : %d", sdp_list_len(seq));
576 sdp_gen_record_pdu(rec, &pdu);
578 for (; seq; seq = seq->next) {
579 struct attrid *aid = seq->data;
581 SDPDBG("AttrDataType : %d", aid->dtd);
583 if (aid->dtd == SDP_UINT16) {
584 uint16_t attr = aid->uint16;
585 sdp_data_t *a = sdp_data_get(rec, attr);
587 sdp_append_to_pdu(buf, a);
588 } else if (aid->dtd == SDP_UINT32) {
589 uint32_t range = aid->uint32;
591 uint16_t low = (0xffff0000 & range) >> 16;
592 uint16_t high = 0x0000ffff & range;
595 SDPDBG("attr range : 0x%x", range);
596 SDPDBG("Low id : 0x%x", low);
597 SDPDBG("High id : 0x%x", high);
599 if (low == 0x0000 && high == 0xffff && pdu.data_size <= buf->buf_size) {
601 memcpy(buf->data, pdu.data, pdu.data_size);
602 buf->data_size = pdu.data_size;
605 /* (else) sub-range of attributes */
606 for (attr = low; attr < high; attr++) {
607 data = sdp_data_get(rec, attr);
609 sdp_append_to_pdu(buf, data);
611 data = sdp_data_get(rec, high);
613 sdp_append_to_pdu(buf, data);
615 error("Unexpected data type : 0x%x", aid->dtd);
616 error("Expect uint16_t or uint32_t");
618 return SDP_INVALID_SYNTAX;
628 * A request for the attributes of a service record.
629 * First check if the service record (specified by
630 * service record handle) exists, then call the attribute
633 static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf)
635 sdp_cont_state_t *cstate = NULL;
636 uint8_t *pResponse = NULL;
637 short cstate_size = 0;
638 sdp_list_t *seq = NULL;
641 unsigned int max_rsp_size;
642 int status = 0, plen, mlen;
643 uint8_t *pdata = req->buf + sizeof(sdp_pdu_hdr_t);
644 size_t data_left = req->len - sizeof(sdp_pdu_hdr_t);
647 if (data_left < sizeof(uint32_t)) {
648 status = SDP_INVALID_SYNTAX;
652 handle = get_be32(pdata);
654 pdata += sizeof(uint32_t);
655 data_left -= sizeof(uint32_t);
657 if (data_left < sizeof(uint16_t)) {
658 status = SDP_INVALID_SYNTAX;
662 max_rsp_size = get_be16(pdata);
664 pdata += sizeof(uint16_t);
665 data_left -= sizeof(uint16_t);
667 if (data_left < sizeof(sdp_pdu_hdr_t)) {
668 status = SDP_INVALID_SYNTAX;
672 /* extract the attribute list */
673 scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID);
675 status = SDP_INVALID_SYNTAX;
679 data_left -= scanned;
681 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
682 mlen = scanned + sizeof(uint32_t) + sizeof(uint16_t) + 1;
683 /* ensure we don't read past buffer */
684 if (plen < mlen || plen != mlen + *(uint8_t *)pdata) {
685 status = SDP_INVALID_PDU_SIZE;
690 * if continuation state exists, attempt
691 * to get rsp remainder from cache, else send error
693 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
694 status = SDP_INVALID_SYNTAX;
698 SDPDBG("SvcRecHandle : 0x%x", handle);
699 SDPDBG("max_rsp_size : %d", max_rsp_size);
702 * Check that max_rsp_size is within valid range
703 * a minimum size of 0x0007 has to be used for data field
705 if (max_rsp_size < 0x0007) {
706 status = SDP_INVALID_SYNTAX;
711 * Calculate Attribute size according to MTU
712 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
714 max_rsp_size = MIN(max_rsp_size, req->mtu - sizeof(sdp_pdu_hdr_t) -
715 sizeof(uint32_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
717 /* pull header for AttributeList byte count */
718 buf->data += sizeof(uint16_t);
719 buf->buf_size -= sizeof(uint16_t);
722 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
724 SDPDBG("Obtained cached rsp : %p", pCache);
727 short sent = MIN(max_rsp_size, pCache->data_size - cstate->cStateValue.maxBytesSent);
728 pResponse = pCache->data;
729 memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
730 buf->data_size += sent;
731 cstate->cStateValue.maxBytesSent += sent;
733 SDPDBG("Response size : %d sending now : %d bytes sent so far : %d",
734 pCache->data_size, sent, cstate->cStateValue.maxBytesSent);
735 if (cstate->cStateValue.maxBytesSent == pCache->data_size)
736 cstate_size = sdp_set_cstate_pdu(buf, NULL);
738 cstate_size = sdp_set_cstate_pdu(buf, cstate);
740 status = SDP_INVALID_CSTATE;
741 error("NULL cache buffer and non-NULL continuation state");
744 sdp_record_t *rec = sdp_record_find(handle);
745 status = extract_attrs(rec, seq, buf);
746 if (buf->data_size > max_rsp_size) {
747 sdp_cont_state_t newState;
749 memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
750 newState.timestamp = sdp_cstate_alloc_buf(buf);
752 * Reset the buffer size to the maximum expected and
753 * set the sdp_cont_state_t
755 SDPDBG("Creating continuation state of size : %d", buf->data_size);
756 buf->data_size = max_rsp_size;
757 newState.cStateValue.maxBytesSent = max_rsp_size;
758 cstate_size = sdp_set_cstate_pdu(buf, &newState);
760 if (buf->data_size == 0)
761 sdp_append_to_buf(buf, NULL, 0);
762 cstate_size = sdp_set_cstate_pdu(buf, NULL);
767 buf->data -= sizeof(uint16_t);
768 buf->buf_size += sizeof(uint16_t);
773 sdp_list_free(seq, free);
777 /* set attribute list byte count */
778 put_be16(buf->data_size - cstate_size, buf->data);
779 buf->data_size += sizeof(uint16_t);
784 * combined service search and attribute extraction
786 static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf)
788 int status = 0, plen, totscanned;
789 uint8_t *pdata, *pResponse = NULL;
791 int scanned, rsp_count = 0;
792 sdp_list_t *pattern = NULL, *seq = NULL, *svcList;
793 sdp_cont_state_t *cstate = NULL;
794 short cstate_size = 0;
800 pdata = req->buf + sizeof(sdp_pdu_hdr_t);
801 data_left = req->len - sizeof(sdp_pdu_hdr_t);
802 scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID);
804 status = SDP_INVALID_SYNTAX;
807 totscanned = scanned;
809 SDPDBG("Bytes scanned: %d", scanned);
812 data_left -= scanned;
814 if (data_left < sizeof(uint16_t)) {
815 status = SDP_INVALID_SYNTAX;
819 max = get_be16(pdata);
821 pdata += sizeof(uint16_t);
822 data_left -= sizeof(uint16_t);
824 SDPDBG("Max Attr expected: %d", max);
826 if (data_left < sizeof(sdp_pdu_hdr_t)) {
827 status = SDP_INVALID_SYNTAX;
831 /* extract the attribute list */
832 scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID);
834 status = SDP_INVALID_SYNTAX;
839 data_left -= scanned;
841 totscanned += scanned + sizeof(uint16_t) + 1;
843 plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
844 if (plen < totscanned || plen != totscanned + *(uint8_t *)pdata) {
845 status = SDP_INVALID_PDU_SIZE;
850 * if continuation state exists attempt
851 * to get rsp remainder from cache, else send error
853 if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
854 status = SDP_INVALID_SYNTAX;
858 svcList = sdp_get_record_list();
860 tmpbuf.data = malloc(USHRT_MAX);
861 tmpbuf.data_size = 0;
862 tmpbuf.buf_size = USHRT_MAX;
863 memset(tmpbuf.data, 0, USHRT_MAX);
866 * Calculate Attribute size according to MTU
867 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
869 max = MIN(max, req->mtu - sizeof(sdp_pdu_hdr_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
871 /* pull header for AttributeList byte count */
872 buf->data += sizeof(uint16_t);
873 buf->buf_size -= sizeof(uint16_t);
875 if (cstate == NULL) {
876 /* no continuation state -> create new response */
878 for (p = svcList; p; p = p->next) {
879 sdp_record_t *rec = p->data;
880 if (sdp_match_uuid(pattern, rec->pattern) > 0 &&
881 sdp_check_access(rec->handle, &req->device)) {
883 status = extract_attrs(rec, seq, &tmpbuf);
885 SDPDBG("Response count : %d", rsp_count);
886 SDPDBG("Local PDU size : %d", tmpbuf.data_size);
888 SDPDBG("Extract attr from record returns err");
891 if (buf->data_size + tmpbuf.data_size < buf->buf_size) {
892 /* to be sure no relocations */
893 sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
894 tmpbuf.data_size = 0;
895 memset(tmpbuf.data, 0, USHRT_MAX);
897 error("Relocation needed");
900 SDPDBG("Net PDU size : %d", buf->data_size);
903 if (buf->data_size > max) {
904 sdp_cont_state_t newState;
906 memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
907 newState.timestamp = sdp_cstate_alloc_buf(buf);
909 * Reset the buffer size to the maximum expected and
910 * set the sdp_cont_state_t
912 buf->data_size = max;
913 newState.cStateValue.maxBytesSent = max;
914 cstate_size = sdp_set_cstate_pdu(buf, &newState);
916 cstate_size = sdp_set_cstate_pdu(buf, NULL);
918 /* continuation State exists -> get from cache */
919 sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
921 uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent);
922 pResponse = pCache->data;
923 memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
924 buf->data_size += sent;
925 cstate->cStateValue.maxBytesSent += sent;
926 if (cstate->cStateValue.maxBytesSent == pCache->data_size)
927 cstate_size = sdp_set_cstate_pdu(buf, NULL);
929 cstate_size = sdp_set_cstate_pdu(buf, cstate);
931 status = SDP_INVALID_CSTATE;
932 SDPDBG("Non-null continuation state, but null cache buffer");
936 if (!rsp_count && !cstate) {
939 sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
940 sdp_set_cstate_pdu(buf, NULL);
944 buf->data -= sizeof(uint16_t);
945 buf->buf_size += sizeof(uint16_t);
948 /* set attribute list byte count */
949 put_be16(buf->data_size - cstate_size, buf->data);
950 buf->data_size += sizeof(uint16_t);
957 sdp_list_free(pattern, free);
959 sdp_list_free(seq, free);
964 * Top level request processor. Calls the appropriate processing
965 * function based on request type. Handles service registration
966 * client requests also.
968 static void process_request(sdp_req_t *req)
970 sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)req->buf;
971 sdp_pdu_hdr_t *rsphdr;
973 uint8_t *buf = malloc(USHRT_MAX);
974 int status = SDP_INVALID_SYNTAX;
976 memset(buf, 0, USHRT_MAX);
977 rsp.data = buf + sizeof(sdp_pdu_hdr_t);
979 rsp.buf_size = USHRT_MAX - sizeof(sdp_pdu_hdr_t);
980 rsphdr = (sdp_pdu_hdr_t *)buf;
982 if (ntohs(reqhdr->plen) != req->len - sizeof(sdp_pdu_hdr_t)) {
983 status = SDP_INVALID_PDU_SIZE;
986 switch (reqhdr->pdu_id) {
987 case SDP_SVC_SEARCH_REQ:
988 SDPDBG("Got a svc srch req");
989 status = service_search_req(req, &rsp);
990 rsphdr->pdu_id = SDP_SVC_SEARCH_RSP;
992 case SDP_SVC_ATTR_REQ:
993 SDPDBG("Got a svc attr req");
994 status = service_attr_req(req, &rsp);
995 rsphdr->pdu_id = SDP_SVC_ATTR_RSP;
997 case SDP_SVC_SEARCH_ATTR_REQ:
998 SDPDBG("Got a svc srch attr req");
999 status = service_search_attr_req(req, &rsp);
1000 rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
1002 /* Following requests are allowed only for local connections */
1003 case SDP_SVC_REGISTER_REQ:
1004 SDPDBG("Service register request");
1006 status = service_register_req(req, &rsp);
1007 rsphdr->pdu_id = SDP_SVC_REGISTER_RSP;
1010 case SDP_SVC_UPDATE_REQ:
1011 SDPDBG("Service update request");
1013 status = service_update_req(req, &rsp);
1014 rsphdr->pdu_id = SDP_SVC_UPDATE_RSP;
1017 case SDP_SVC_REMOVE_REQ:
1018 SDPDBG("Service removal request");
1020 status = service_remove_req(req, &rsp);
1021 rsphdr->pdu_id = SDP_SVC_REMOVE_RSP;
1025 error("Unknown PDU ID : 0x%x received", reqhdr->pdu_id);
1026 status = SDP_INVALID_SYNTAX;
1032 rsphdr->pdu_id = SDP_ERROR_RSP;
1033 put_be16(status, rsp.data);
1034 rsp.data_size = sizeof(uint16_t);
1037 SDPDBG("Sending rsp. status %d", status);
1039 rsphdr->tid = reqhdr->tid;
1040 rsphdr->plen = htons(rsp.data_size);
1042 /* point back to the real buffer start and set the real rsp length */
1043 rsp.data_size += sizeof(sdp_pdu_hdr_t);
1046 /* stream the rsp PDU */
1047 if (send(req->sock, rsp.data, rsp.data_size, 0) < 0)
1048 error("send: %s (%d)", strerror(errno), errno);
1050 SDPDBG("Bytes Sent : %d", rsp.data_size);
1056 void handle_internal_request(int sk, int mtu, void *data, int len)
1060 bacpy(&req.device, BDADDR_ANY);
1061 bacpy(&req.bdaddr, BDADDR_LOCAL);
1069 process_request(&req);
1072 void handle_request(int sk, uint8_t *data, int len)
1074 struct sockaddr_l2 sa;
1079 if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0) {
1080 error("getpeername: %s", strerror(errno));
1084 if (sa.l2_family == AF_BLUETOOTH) {
1085 struct l2cap_options lo;
1087 memset(&lo, 0, sizeof(lo));
1090 if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &lo, &size) < 0) {
1091 error("getsockopt: %s", strerror(errno));
1095 bacpy(&req.bdaddr, &sa.l2_bdaddr);
1098 memset(&sa, 0, sizeof(sa));
1101 if (getsockname(sk, (struct sockaddr *) &sa, &size) < 0) {
1102 error("getsockname: %s", strerror(errno));
1106 bacpy(&req.device, &sa.l2_bdaddr);
1108 bacpy(&req.device, BDADDR_ANY);
1109 bacpy(&req.bdaddr, BDADDR_LOCAL);
1118 process_request(&req);