• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
50 typedef struct _sdp_cstate_list sdp_cstate_list_t;
51 
52 struct _sdp_cstate_list {
53 	sdp_cstate_list_t *next;
54 	uint32_t timestamp;
55 	sdp_buf_t buf;
56 };
57 
58 static sdp_cstate_list_t *cstates;
59 
60 // FIXME: should probably remove it when it's found
sdp_get_cached_rsp(sdp_cont_state_t * cstate)61 sdp_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 
sdp_cstate_alloc_buf(sdp_buf_t * buf)71 static 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 
91 struct 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  */
extract_des(uint8_t * buf,int len,sdp_list_t ** svcReqSeq,uint8_t * pDataType,uint8_t expectedType)105 static 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 
237 failed:
238 	sdp_list_free(pSeq, free);
239 	return -1;
240 }
241 
sdp_set_cstate_pdu(sdp_buf_t * buf,sdp_cont_state_t * cstate)242 static 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 
sdp_cstate_get(uint8_t * buffer,size_t len,sdp_cont_state_t ** cstate)264 static 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  */
sdp_match_uuid(sdp_list_t * search,sdp_list_t * pattern)310 static 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  */
service_search_req(sdp_req_t * req,sdp_buf_t * buf)343 static 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_SYNTAX;
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 
528 done:
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  */
extract_attrs(sdp_record_t * rec,sdp_list_t * seq,sdp_buf_t * buf)543 static 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  */
service_attr_req(sdp_req_t * req,sdp_buf_t * buf)618 static 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_SYNTAX;
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 	 * Calculate Attribute size acording to MTU
688 	 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
689 	 */
690 	max_rsp_size = MIN(max_rsp_size, req->mtu - sizeof(sdp_pdu_hdr_t) -
691 			sizeof(uint32_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
692 
693 	/* pull header for AttributeList byte count */
694 	buf->data += sizeof(uint16_t);
695 	buf->buf_size -= sizeof(uint16_t);
696 
697 	if (cstate) {
698 		sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
699 
700 		SDPDBG("Obtained cached rsp : %p", pCache);
701 
702 		if (pCache) {
703 			short sent = MIN(max_rsp_size, pCache->data_size - cstate->cStateValue.maxBytesSent);
704 			pResponse = pCache->data;
705 			memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
706 			buf->data_size += sent;
707 			cstate->cStateValue.maxBytesSent += sent;
708 
709 			SDPDBG("Response size : %d sending now : %d bytes sent so far : %d",
710 				pCache->data_size, sent, cstate->cStateValue.maxBytesSent);
711 			if (cstate->cStateValue.maxBytesSent == pCache->data_size)
712 				cstate_size = sdp_set_cstate_pdu(buf, NULL);
713 			else
714 				cstate_size = sdp_set_cstate_pdu(buf, cstate);
715 		} else {
716 			status = SDP_INVALID_CSTATE;
717 			error("NULL cache buffer and non-NULL continuation state");
718 		}
719 	} else {
720 		sdp_record_t *rec = sdp_record_find(handle);
721 		status = extract_attrs(rec, seq, buf);
722 		if (buf->data_size > max_rsp_size) {
723 			sdp_cont_state_t newState;
724 
725 			memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
726 			newState.timestamp = sdp_cstate_alloc_buf(buf);
727 			/*
728 			 * Reset the buffer size to the maximum expected and
729 			 * set the sdp_cont_state_t
730 			 */
731 			SDPDBG("Creating continuation state of size : %d", buf->data_size);
732 			buf->data_size = max_rsp_size;
733 			newState.cStateValue.maxBytesSent = max_rsp_size;
734 			cstate_size = sdp_set_cstate_pdu(buf, &newState);
735 		} else {
736 			if (buf->data_size == 0)
737 				sdp_append_to_buf(buf, 0, 0);
738 			cstate_size = sdp_set_cstate_pdu(buf, NULL);
739 		}
740 	}
741 
742 	// push header
743 	buf->data -= sizeof(uint16_t);
744 	buf->buf_size += sizeof(uint16_t);
745 
746 done:
747 	free(cstate);
748 	if (seq)
749 		sdp_list_free(seq, free);
750 	if (status)
751 		return status;
752 
753 	/* set attribute list byte count */
754 	bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data);
755 	buf->data_size += sizeof(uint16_t);
756 	return 0;
757 }
758 
759 /*
760  * combined service search and attribute extraction
761  */
service_search_attr_req(sdp_req_t * req,sdp_buf_t * buf)762 static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf)
763 {
764 	int status = 0, plen, totscanned;
765 	uint8_t *pdata, *pResponse = NULL;
766 	unsigned int max;
767 	int scanned, rsp_count = 0;
768 	sdp_list_t *pattern = NULL, *seq = NULL, *svcList;
769 	sdp_cont_state_t *cstate = NULL;
770 	short cstate_size = 0;
771 	uint8_t dtd = 0;
772 	sdp_buf_t tmpbuf;
773 	size_t data_left = req->len;
774 
775 	tmpbuf.data = NULL;
776 	pdata = req->buf + sizeof(sdp_pdu_hdr_t);
777 	data_left = req->len - sizeof(sdp_pdu_hdr_t);
778 	scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID);
779 	if (scanned == -1) {
780 		status = SDP_INVALID_SYNTAX;
781 		goto done;
782 	}
783 	totscanned = scanned;
784 
785 	SDPDBG("Bytes scanned: %d", scanned);
786 
787 	pdata += scanned;
788 	data_left -= scanned;
789 
790 	if (data_left < sizeof(uint16_t)) {
791 		status = SDP_INVALID_SYNTAX;
792 		goto done;
793 	}
794 
795 	max = ntohs(bt_get_unaligned((uint16_t *)pdata));
796 
797 	pdata += sizeof(uint16_t);
798 	data_left -= sizeof(uint16_t);
799 
800 	SDPDBG("Max Attr expected: %d", max);
801 
802 	if (data_left < sizeof(sdp_pdu_hdr_t)) {
803 		status = SDP_INVALID_SYNTAX;
804 		goto done;
805 	}
806 
807 	/* extract the attribute list */
808 	scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID);
809 	if (scanned == -1) {
810 		status = SDP_INVALID_SYNTAX;
811 		goto done;
812 	}
813 
814 	pdata += scanned;
815 	data_left -= scanned;
816 
817 	totscanned += scanned + sizeof(uint16_t) + 1;
818 
819 	plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
820 	if (plen < totscanned || plen != totscanned + *(uint8_t *)pdata) {
821 		status = SDP_INVALID_SYNTAX;
822 		goto done;
823 	}
824 
825 	/*
826 	 * if continuation state exists attempt
827 	 * to get rsp remainder from cache, else send error
828 	 */
829 	if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
830 		status = SDP_INVALID_SYNTAX;
831 		goto done;
832 	}
833 
834 	svcList = sdp_get_record_list();
835 
836 	tmpbuf.data = malloc(USHRT_MAX);
837 	tmpbuf.data_size = 0;
838 	tmpbuf.buf_size = USHRT_MAX;
839 	memset(tmpbuf.data, 0, USHRT_MAX);
840 
841 	/*
842 	 * Calculate Attribute size acording to MTU
843 	 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
844 	 */
845 	max = MIN(max, req->mtu - sizeof(sdp_pdu_hdr_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
846 
847 	/* pull header for AttributeList byte count */
848 	buf->data += sizeof(uint16_t);
849 	buf->buf_size -= sizeof(uint16_t);
850 
851 	if (cstate == NULL) {
852 		/* no continuation state -> create new response */
853 		sdp_list_t *p;
854 		for (p = svcList; p; p = p->next) {
855 			sdp_record_t *rec = (sdp_record_t *) p->data;
856 			if (sdp_match_uuid(pattern, rec->pattern) > 0 &&
857 					sdp_check_access(rec->handle, &req->device)) {
858 				rsp_count++;
859 				status = extract_attrs(rec, seq, &tmpbuf);
860 
861 				SDPDBG("Response count : %d", rsp_count);
862 				SDPDBG("Local PDU size : %d", tmpbuf.data_size);
863 				if (status) {
864 					SDPDBG("Extract attr from record returns err");
865 					break;
866 				}
867 				if (buf->data_size + tmpbuf.data_size < buf->buf_size) {
868 					// to be sure no relocations
869 					sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
870 					tmpbuf.data_size = 0;
871 					memset(tmpbuf.data, 0, USHRT_MAX);
872 				} else {
873 					error("Relocation needed");
874 					break;
875 				}
876 				SDPDBG("Net PDU size : %d", buf->data_size);
877 			}
878 		}
879 		if (buf->data_size > max) {
880 			sdp_cont_state_t newState;
881 
882 			memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
883 			newState.timestamp = sdp_cstate_alloc_buf(buf);
884 			/*
885 			 * Reset the buffer size to the maximum expected and
886 			 * set the sdp_cont_state_t
887 			 */
888 			buf->data_size = max;
889 			newState.cStateValue.maxBytesSent = max;
890 			cstate_size = sdp_set_cstate_pdu(buf, &newState);
891 		} else
892 			cstate_size = sdp_set_cstate_pdu(buf, NULL);
893 	} else {
894 		/* continuation State exists -> get from cache */
895 		sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
896 		if (pCache) {
897 			uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent);
898 			pResponse = pCache->data;
899 			memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
900 			buf->data_size += sent;
901 			cstate->cStateValue.maxBytesSent += sent;
902 			if (cstate->cStateValue.maxBytesSent == pCache->data_size)
903 				cstate_size = sdp_set_cstate_pdu(buf, NULL);
904 			else
905 				cstate_size = sdp_set_cstate_pdu(buf, cstate);
906 		} else {
907 			status = SDP_INVALID_CSTATE;
908 			SDPDBG("Non-null continuation state, but null cache buffer");
909 		}
910 	}
911 
912 	if (!rsp_count && !cstate) {
913 		// found nothing
914 		buf->data_size = 0;
915 		sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
916 		sdp_set_cstate_pdu(buf, NULL);
917 	}
918 
919 	// push header
920 	buf->data -= sizeof(uint16_t);
921 	buf->buf_size += sizeof(uint16_t);
922 
923 	if (!status) {
924 		/* set attribute list byte count */
925 		bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data);
926 		buf->data_size += sizeof(uint16_t);
927 	}
928 
929 done:
930 	free(cstate);
931 	free(tmpbuf.data);
932 	if (pattern)
933 		sdp_list_free(pattern, free);
934 	if (seq)
935 		sdp_list_free(seq, free);
936 	return status;
937 }
938 
939 /*
940  * Top level request processor. Calls the appropriate processing
941  * function based on request type. Handles service registration
942  * client requests also.
943  */
process_request(sdp_req_t * req)944 static void process_request(sdp_req_t *req)
945 {
946 	sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)req->buf;
947 	sdp_pdu_hdr_t *rsphdr;
948 	sdp_buf_t rsp;
949 	uint8_t *buf = malloc(USHRT_MAX);
950 	int sent = 0;
951 	int status = SDP_INVALID_SYNTAX;
952 
953 	memset(buf, 0, USHRT_MAX);
954 	rsp.data = buf + sizeof(sdp_pdu_hdr_t);
955 	rsp.data_size = 0;
956 	rsp.buf_size = USHRT_MAX - sizeof(sdp_pdu_hdr_t);
957 	rsphdr = (sdp_pdu_hdr_t *)buf;
958 
959 	if (ntohs(reqhdr->plen) != req->len - sizeof(sdp_pdu_hdr_t)) {
960 		status = SDP_INVALID_PDU_SIZE;
961 		goto send_rsp;
962 	}
963 	switch (reqhdr->pdu_id) {
964 	case SDP_SVC_SEARCH_REQ:
965 		SDPDBG("Got a svc srch req");
966 		status = service_search_req(req, &rsp);
967 		rsphdr->pdu_id = SDP_SVC_SEARCH_RSP;
968 		break;
969 	case SDP_SVC_ATTR_REQ:
970 		SDPDBG("Got a svc attr req");
971 		status = service_attr_req(req, &rsp);
972 		rsphdr->pdu_id = SDP_SVC_ATTR_RSP;
973 		break;
974 	case SDP_SVC_SEARCH_ATTR_REQ:
975 		SDPDBG("Got a svc srch attr req");
976 		status = service_search_attr_req(req, &rsp);
977 		rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
978 		break;
979 	/* Following requests are allowed only for local connections */
980 	case SDP_SVC_REGISTER_REQ:
981 		SDPDBG("Service register request");
982 		if (req->local) {
983 			status = service_register_req(req, &rsp);
984 			rsphdr->pdu_id = SDP_SVC_REGISTER_RSP;
985 		}
986 		break;
987 	case SDP_SVC_UPDATE_REQ:
988 		SDPDBG("Service update request");
989 		if (req->local) {
990 			status = service_update_req(req, &rsp);
991 			rsphdr->pdu_id = SDP_SVC_UPDATE_RSP;
992 		}
993 		break;
994 	case SDP_SVC_REMOVE_REQ:
995 		SDPDBG("Service removal request");
996 		if (req->local) {
997 			status = service_remove_req(req, &rsp);
998 			rsphdr->pdu_id = SDP_SVC_REMOVE_RSP;
999 		}
1000 		break;
1001 	default:
1002 		error("Unknown PDU ID : 0x%x received", reqhdr->pdu_id);
1003 		status = SDP_INVALID_SYNTAX;
1004 		break;
1005 	}
1006 
1007 send_rsp:
1008 	if (status) {
1009 		rsphdr->pdu_id = SDP_ERROR_RSP;
1010 		bt_put_unaligned(htons(status), (uint16_t *)rsp.data);
1011 		rsp.data_size = sizeof(uint16_t);
1012 	}
1013 
1014 	SDPDBG("Sending rsp. status %d", status);
1015 
1016 	rsphdr->tid  = reqhdr->tid;
1017 	rsphdr->plen = htons(rsp.data_size);
1018 
1019 	/* point back to the real buffer start and set the real rsp length */
1020 	rsp.data_size += sizeof(sdp_pdu_hdr_t);
1021 	rsp.data = buf;
1022 
1023 	/* stream the rsp PDU */
1024 	sent = send(req->sock, rsp.data, rsp.data_size, 0);
1025 
1026 	SDPDBG("Bytes Sent : %d", sent);
1027 
1028 	free(rsp.data);
1029 	free(req->buf);
1030 }
1031 
handle_request(int sk,uint8_t * data,int len)1032 void handle_request(int sk, uint8_t *data, int len)
1033 {
1034 	struct sockaddr_l2 sa;
1035 	socklen_t size;
1036 	sdp_req_t req;
1037 
1038 	size = sizeof(sa);
1039 	if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0) {
1040 		error("getpeername: %s", strerror(errno));
1041 		return;
1042 	}
1043 
1044 	if (sa.l2_family == AF_BLUETOOTH) {
1045 		struct l2cap_options lo;
1046 
1047 		memset(&lo, 0, sizeof(lo));
1048 		size = sizeof(lo);
1049 
1050 		if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &lo, &size) < 0) {
1051 			error("getsockopt: %s", strerror(errno));
1052 			return;
1053 		}
1054 
1055 		bacpy(&req.bdaddr, &sa.l2_bdaddr);
1056 		req.mtu = lo.omtu;
1057 		req.local = 0;
1058 		memset(&sa, 0, sizeof(sa));
1059 		size = sizeof(sa);
1060 
1061 		if (getsockname(sk, (struct sockaddr *) &sa, &size) < 0) {
1062 			error("getsockname: %s", strerror(errno));
1063 			return;
1064 		}
1065 
1066 		bacpy(&req.device, &sa.l2_bdaddr);
1067 	} else {
1068 		bacpy(&req.device, BDADDR_ANY);
1069 		bacpy(&req.bdaddr, BDADDR_LOCAL);
1070 		req.mtu = 2048;
1071 		req.local = 1;
1072 	}
1073 
1074 	req.sock = sk;
1075 	req.buf  = data;
1076 	req.len  = len;
1077 
1078 	process_request(&req);
1079 }
1080