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