Home | History | Annotate | Download | only in src
      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 (at) qualcomm.com>
      7  *  Copyright (C) 2002-2009  Marcel Holtmann <marcel (at) holtmann.org>
      8  *  Copyright (C) 2002-2003  Stephen Crane <steve.crane (at) 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 "logging.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
     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 
     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  */
    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 
    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 
    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  */
    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  */
    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 	if (cstate)
    530 		free(cstate);
    531 	if (pattern)
    532 		sdp_list_free(pattern, free);
    533 
    534 	return status;
    535 }
    536 
    537 /*
    538  * Extract attribute identifiers from the request PDU.
    539  * Clients could request a subset of attributes (by id)
    540  * from a service record, instead of the whole set. The
    541  * requested identifiers are present in the PDU form of
    542  * the request
    543  */
    544 static int extract_attrs(sdp_record_t *rec, sdp_list_t *seq, sdp_buf_t *buf)
    545 {
    546 	sdp_buf_t pdu;
    547 
    548 	if (!rec)
    549 		return SDP_INVALID_RECORD_HANDLE;
    550 
    551 	if (seq) {
    552 		SDPDBG("Entries in attr seq : %d", sdp_list_len(seq));
    553 	} else {
    554 		SDPDBG("NULL attribute descriptor");
    555 	}
    556 
    557 	if (seq == NULL) {
    558 		SDPDBG("Attribute sequence is NULL");
    559 		return 0;
    560 	}
    561 
    562 	sdp_gen_record_pdu(rec, &pdu);
    563 
    564 	for (; seq; seq = seq->next) {
    565 		struct attrid *aid = seq->data;
    566 
    567 		SDPDBG("AttrDataType : %d", aid->dtd);
    568 
    569 		if (aid->dtd == SDP_UINT16) {
    570 			uint16_t attr = bt_get_unaligned((uint16_t *)&aid->uint16);
    571 			sdp_data_t *a = (sdp_data_t *)sdp_data_get(rec, attr);
    572 			if (a)
    573 				sdp_append_to_pdu(buf, a);
    574 		} else if (aid->dtd == SDP_UINT32) {
    575 			uint32_t range = bt_get_unaligned((uint32_t *)&aid->uint32);
    576 			uint16_t attr;
    577 			uint16_t low = (0xffff0000 & range) >> 16;
    578 			uint16_t high = 0x0000ffff & range;
    579 			sdp_data_t *data;
    580 
    581 			SDPDBG("attr range : 0x%x", range);
    582 			SDPDBG("Low id : 0x%x", low);
    583 			SDPDBG("High id : 0x%x", high);
    584 
    585 			if (low == 0x0000 && high == 0xffff && pdu.data_size <= buf->buf_size) {
    586 				/* copy it */
    587 				memcpy(buf->data, pdu.data, pdu.data_size);
    588 				buf->data_size = pdu.data_size;
    589 				break;
    590 			}
    591 			/* (else) sub-range of attributes */
    592 			for (attr = low; attr < high; attr++) {
    593 				data = sdp_data_get(rec, attr);
    594 				if (data)
    595 					sdp_append_to_pdu(buf, data);
    596 			}
    597 			data = sdp_data_get(rec, high);
    598 			if (data)
    599 				sdp_append_to_pdu(buf, data);
    600 		} else {
    601 			error("Unexpected data type : 0x%x", aid->dtd);
    602 			error("Expect uint16_t or uint32_t");
    603 			free(pdu.data);
    604 			return SDP_INVALID_SYNTAX;
    605 		}
    606 	}
    607 
    608 	free(pdu.data);
    609 
    610 	return 0;
    611 }
    612 
    613 /*
    614  * A request for the attributes of a service record.
    615  * First check if the service record (specified by
    616  * service record handle) exists, then call the attribute
    617  * streaming function
    618  */
    619 static int service_attr_req(sdp_req_t *req, sdp_buf_t *buf)
    620 {
    621 	sdp_cont_state_t *cstate = NULL;
    622 	uint8_t *pResponse = NULL;
    623 	short cstate_size = 0;
    624 	sdp_list_t *seq = NULL;
    625 	uint8_t dtd = 0;
    626 	int scanned = 0;
    627 	unsigned int max_rsp_size;
    628 	int status = 0, plen, mlen;
    629 	uint8_t *pdata = req->buf + sizeof(sdp_pdu_hdr_t);
    630 	size_t data_left = req->len - sizeof(sdp_pdu_hdr_t);
    631 	uint32_t handle;
    632 
    633 	if (data_left < sizeof(uint32_t)) {
    634 		status = SDP_INVALID_SYNTAX;
    635 		goto done;
    636 	}
    637 
    638 	handle = ntohl(bt_get_unaligned((uint32_t *)pdata));
    639 
    640 	pdata += sizeof(uint32_t);
    641 	data_left -= sizeof(uint32_t);
    642 
    643 	if (data_left < sizeof(uint16_t)) {
    644 		status = SDP_INVALID_SYNTAX;
    645 		goto done;
    646 	}
    647 
    648 	max_rsp_size = ntohs(bt_get_unaligned((uint16_t *)pdata));
    649 
    650 	pdata += sizeof(uint16_t);
    651 	data_left -= sizeof(uint16_t);
    652 
    653 	if (data_left < sizeof(sdp_pdu_hdr_t)) {
    654 		status = SDP_INVALID_SYNTAX;
    655 		goto done;
    656 	}
    657 
    658 	/* extract the attribute list */
    659 	scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID);
    660 	if (scanned == -1) {
    661 		status = SDP_INVALID_SYNTAX;
    662 		goto done;
    663 	}
    664 	pdata += scanned;
    665 	data_left -= scanned;
    666 
    667 	plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
    668 	mlen = scanned + sizeof(uint32_t) + sizeof(uint16_t) + 1;
    669 	// ensure we don't read past buffer
    670 	if (plen < mlen || plen != mlen + *(uint8_t *)pdata) {
    671 		status = SDP_INVALID_SYNTAX;
    672 		goto done;
    673 	}
    674 
    675 	/*
    676 	 * if continuation state exists, attempt
    677 	 * to get rsp remainder from cache, else send error
    678 	 */
    679 	if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
    680 		status = SDP_INVALID_SYNTAX;
    681 		goto done;
    682 	}
    683 
    684 	SDPDBG("SvcRecHandle : 0x%x", handle);
    685 	SDPDBG("max_rsp_size : %d", max_rsp_size);
    686 
    687 	/*
    688 	 * Calculate Attribute size acording to MTU
    689 	 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
    690 	 */
    691 	max_rsp_size = MIN(max_rsp_size, req->mtu - sizeof(sdp_pdu_hdr_t) -
    692 			sizeof(uint32_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
    693 
    694 	/* pull header for AttributeList byte count */
    695 	buf->data += sizeof(uint16_t);
    696 	buf->buf_size -= sizeof(uint16_t);
    697 
    698 	if (cstate) {
    699 		sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
    700 
    701 		SDPDBG("Obtained cached rsp : %p", pCache);
    702 
    703 		if (pCache) {
    704 			short sent = MIN(max_rsp_size, pCache->data_size - cstate->cStateValue.maxBytesSent);
    705 			pResponse = pCache->data;
    706 			memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
    707 			buf->data_size += sent;
    708 			cstate->cStateValue.maxBytesSent += sent;
    709 
    710 			SDPDBG("Response size : %d sending now : %d bytes sent so far : %d",
    711 				pCache->data_size, sent, cstate->cStateValue.maxBytesSent);
    712 			if (cstate->cStateValue.maxBytesSent == pCache->data_size)
    713 				cstate_size = sdp_set_cstate_pdu(buf, NULL);
    714 			else
    715 				cstate_size = sdp_set_cstate_pdu(buf, cstate);
    716 		} else {
    717 			status = SDP_INVALID_CSTATE;
    718 			error("NULL cache buffer and non-NULL continuation state");
    719 		}
    720 	} else {
    721 		sdp_record_t *rec = sdp_record_find(handle);
    722 		status = extract_attrs(rec, seq, buf);
    723 		if (buf->data_size > max_rsp_size) {
    724 			sdp_cont_state_t newState;
    725 
    726 			memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
    727 			newState.timestamp = sdp_cstate_alloc_buf(buf);
    728 			/*
    729 			 * Reset the buffer size to the maximum expected and
    730 			 * set the sdp_cont_state_t
    731 			 */
    732 			SDPDBG("Creating continuation state of size : %d", buf->data_size);
    733 			buf->data_size = max_rsp_size;
    734 			newState.cStateValue.maxBytesSent = max_rsp_size;
    735 			cstate_size = sdp_set_cstate_pdu(buf, &newState);
    736 		} else {
    737 			if (buf->data_size == 0)
    738 				sdp_append_to_buf(buf, 0, 0);
    739 			cstate_size = sdp_set_cstate_pdu(buf, NULL);
    740 		}
    741 	}
    742 
    743 	// push header
    744 	buf->data -= sizeof(uint16_t);
    745 	buf->buf_size += sizeof(uint16_t);
    746 
    747 done:
    748 	if (cstate)
    749 		free(cstate);
    750 	if (seq)
    751 		sdp_list_free(seq, free);
    752 	if (status)
    753 		return status;
    754 
    755 	/* set attribute list byte count */
    756 	bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data);
    757 	buf->data_size += sizeof(uint16_t);
    758 	return 0;
    759 }
    760 
    761 /*
    762  * combined service search and attribute extraction
    763  */
    764 static int service_search_attr_req(sdp_req_t *req, sdp_buf_t *buf)
    765 {
    766 	int status = 0, plen, totscanned;
    767 	uint8_t *pdata, *pResponse = NULL;
    768 	unsigned int max;
    769 	int scanned, rsp_count = 0;
    770 	sdp_list_t *pattern = NULL, *seq = NULL, *svcList;
    771 	sdp_cont_state_t *cstate = NULL;
    772 	short cstate_size = 0;
    773 	uint8_t dtd = 0;
    774 	sdp_buf_t tmpbuf;
    775 	size_t data_left = req->len;
    776 
    777 	tmpbuf.data = NULL;
    778 	pdata = req->buf + sizeof(sdp_pdu_hdr_t);
    779 	data_left = req->len - sizeof(sdp_pdu_hdr_t);
    780 	scanned = extract_des(pdata, data_left, &pattern, &dtd, SDP_TYPE_UUID);
    781 	if (scanned == -1) {
    782 		status = SDP_INVALID_SYNTAX;
    783 		goto done;
    784 	}
    785 	totscanned = scanned;
    786 
    787 	SDPDBG("Bytes scanned: %d", scanned);
    788 
    789 	pdata += scanned;
    790 	data_left -= scanned;
    791 
    792 	if (data_left < sizeof(uint16_t)) {
    793 		status = SDP_INVALID_SYNTAX;
    794 		goto done;
    795 	}
    796 
    797 	max = ntohs(bt_get_unaligned((uint16_t *)pdata));
    798 
    799 	pdata += sizeof(uint16_t);
    800 	data_left -= sizeof(uint16_t);
    801 
    802 	SDPDBG("Max Attr expected: %d", max);
    803 
    804 	if (data_left < sizeof(sdp_pdu_hdr_t)) {
    805 		status = SDP_INVALID_SYNTAX;
    806 		goto done;
    807 	}
    808 
    809 	/* extract the attribute list */
    810 	scanned = extract_des(pdata, data_left, &seq, &dtd, SDP_TYPE_ATTRID);
    811 	if (scanned == -1) {
    812 		status = SDP_INVALID_SYNTAX;
    813 		goto done;
    814 	}
    815 
    816 	pdata += scanned;
    817 	data_left -= scanned;
    818 
    819 	totscanned += scanned + sizeof(uint16_t) + 1;
    820 
    821 	plen = ntohs(((sdp_pdu_hdr_t *)(req->buf))->plen);
    822 	if (plen < totscanned || plen != totscanned + *(uint8_t *)pdata) {
    823 		status = SDP_INVALID_SYNTAX;
    824 		goto done;
    825 	}
    826 
    827 	/*
    828 	 * if continuation state exists attempt
    829 	 * to get rsp remainder from cache, else send error
    830 	 */
    831 	if (sdp_cstate_get(pdata, data_left, &cstate) < 0) {
    832 		status = SDP_INVALID_SYNTAX;
    833 		goto done;
    834 	}
    835 
    836 	svcList = sdp_get_record_list();
    837 
    838 	tmpbuf.data = malloc(USHRT_MAX);
    839 	tmpbuf.data_size = 0;
    840 	tmpbuf.buf_size = USHRT_MAX;
    841 	memset(tmpbuf.data, 0, USHRT_MAX);
    842 
    843 	/*
    844 	 * Calculate Attribute size acording to MTU
    845 	 * We can send only (MTU - sizeof(sdp_pdu_hdr_t) - sizeof(sdp_cont_state_t))
    846 	 */
    847 	max = MIN(max, req->mtu - sizeof(sdp_pdu_hdr_t) - SDP_CONT_STATE_SIZE - sizeof(uint16_t));
    848 
    849 	/* pull header for AttributeList byte count */
    850 	buf->data += sizeof(uint16_t);
    851 	buf->buf_size -= sizeof(uint16_t);
    852 
    853 	if (cstate == NULL) {
    854 		/* no continuation state -> create new response */
    855 		sdp_list_t *p;
    856 		for (p = svcList; p; p = p->next) {
    857 			sdp_record_t *rec = (sdp_record_t *) p->data;
    858 			if (sdp_match_uuid(pattern, rec->pattern) > 0 &&
    859 					sdp_check_access(rec->handle, &req->device)) {
    860 				rsp_count++;
    861 				status = extract_attrs(rec, seq, &tmpbuf);
    862 
    863 				SDPDBG("Response count : %d", rsp_count);
    864 				SDPDBG("Local PDU size : %d", tmpbuf.data_size);
    865 				if (status) {
    866 					SDPDBG("Extract attr from record returns err");
    867 					break;
    868 				}
    869 				if (buf->data_size + tmpbuf.data_size < buf->buf_size) {
    870 					// to be sure no relocations
    871 					sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
    872 					tmpbuf.data_size = 0;
    873 					memset(tmpbuf.data, 0, USHRT_MAX);
    874 				} else {
    875 					error("Relocation needed");
    876 					break;
    877 				}
    878 				SDPDBG("Net PDU size : %d", buf->data_size);
    879 			}
    880 		}
    881 		if (buf->data_size > max) {
    882 			sdp_cont_state_t newState;
    883 
    884 			memset((char *)&newState, 0, sizeof(sdp_cont_state_t));
    885 			newState.timestamp = sdp_cstate_alloc_buf(buf);
    886 			/*
    887 			 * Reset the buffer size to the maximum expected and
    888 			 * set the sdp_cont_state_t
    889 			 */
    890 			buf->data_size = max;
    891 			newState.cStateValue.maxBytesSent = max;
    892 			cstate_size = sdp_set_cstate_pdu(buf, &newState);
    893 		} else
    894 			cstate_size = sdp_set_cstate_pdu(buf, NULL);
    895 	} else {
    896 		/* continuation State exists -> get from cache */
    897 		sdp_buf_t *pCache = sdp_get_cached_rsp(cstate);
    898 		if (pCache) {
    899 			uint16_t sent = MIN(max, pCache->data_size - cstate->cStateValue.maxBytesSent);
    900 			pResponse = pCache->data;
    901 			memcpy(buf->data, pResponse + cstate->cStateValue.maxBytesSent, sent);
    902 			buf->data_size += sent;
    903 			cstate->cStateValue.maxBytesSent += sent;
    904 			if (cstate->cStateValue.maxBytesSent == pCache->data_size)
    905 				cstate_size = sdp_set_cstate_pdu(buf, NULL);
    906 			else
    907 				cstate_size = sdp_set_cstate_pdu(buf, cstate);
    908 		} else {
    909 			status = SDP_INVALID_CSTATE;
    910 			SDPDBG("Non-null continuation state, but null cache buffer");
    911 		}
    912 	}
    913 
    914 	if (!rsp_count && !cstate) {
    915 		// found nothing
    916 		buf->data_size = 0;
    917 		sdp_append_to_buf(buf, tmpbuf.data, tmpbuf.data_size);
    918 		sdp_set_cstate_pdu(buf, NULL);
    919 	}
    920 
    921 	// push header
    922 	buf->data -= sizeof(uint16_t);
    923 	buf->buf_size += sizeof(uint16_t);
    924 
    925 	if (!status) {
    926 		/* set attribute list byte count */
    927 		bt_put_unaligned(htons(buf->data_size - cstate_size), (uint16_t *)buf->data);
    928 		buf->data_size += sizeof(uint16_t);
    929 	}
    930 
    931 done:
    932 	if (cstate)
    933 		free(cstate);
    934 	if (tmpbuf.data)
    935 		free(tmpbuf.data);
    936 	if (pattern)
    937 		sdp_list_free(pattern, free);
    938 	if (seq)
    939 		sdp_list_free(seq, free);
    940 	return status;
    941 }
    942 
    943 /*
    944  * Top level request processor. Calls the appropriate processing
    945  * function based on request type. Handles service registration
    946  * client requests also.
    947  */
    948 static void process_request(sdp_req_t *req)
    949 {
    950 	sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)req->buf;
    951 	sdp_pdu_hdr_t *rsphdr;
    952 	sdp_buf_t rsp;
    953 	uint8_t *buf = malloc(USHRT_MAX);
    954 	int sent = 0;
    955 	int status = SDP_INVALID_SYNTAX;
    956 
    957 	memset(buf, 0, USHRT_MAX);
    958 	rsp.data = buf + sizeof(sdp_pdu_hdr_t);
    959 	rsp.data_size = 0;
    960 	rsp.buf_size = USHRT_MAX - sizeof(sdp_pdu_hdr_t);
    961 	rsphdr = (sdp_pdu_hdr_t *)buf;
    962 
    963 	if (ntohs(reqhdr->plen) != req->len - sizeof(sdp_pdu_hdr_t)) {
    964 		status = SDP_INVALID_PDU_SIZE;
    965 		goto send_rsp;
    966 	}
    967 	switch (reqhdr->pdu_id) {
    968 	case SDP_SVC_SEARCH_REQ:
    969 		SDPDBG("Got a svc srch req");
    970 		status = service_search_req(req, &rsp);
    971 		rsphdr->pdu_id = SDP_SVC_SEARCH_RSP;
    972 		break;
    973 	case SDP_SVC_ATTR_REQ:
    974 		SDPDBG("Got a svc attr req");
    975 		status = service_attr_req(req, &rsp);
    976 		rsphdr->pdu_id = SDP_SVC_ATTR_RSP;
    977 		break;
    978 	case SDP_SVC_SEARCH_ATTR_REQ:
    979 		SDPDBG("Got a svc srch attr req");
    980 		status = service_search_attr_req(req, &rsp);
    981 		rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
    982 		break;
    983 	/* Following requests are allowed only for local connections */
    984 	case SDP_SVC_REGISTER_REQ:
    985 		SDPDBG("Service register request");
    986 		if (req->local) {
    987 			status = service_register_req(req, &rsp);
    988 			rsphdr->pdu_id = SDP_SVC_REGISTER_RSP;
    989 		}
    990 		break;
    991 	case SDP_SVC_UPDATE_REQ:
    992 		SDPDBG("Service update request");
    993 		if (req->local) {
    994 			status = service_update_req(req, &rsp);
    995 			rsphdr->pdu_id = SDP_SVC_UPDATE_RSP;
    996 		}
    997 		break;
    998 	case SDP_SVC_REMOVE_REQ:
    999 		SDPDBG("Service removal request");
   1000 		if (req->local) {
   1001 			status = service_remove_req(req, &rsp);
   1002 			rsphdr->pdu_id = SDP_SVC_REMOVE_RSP;
   1003 		}
   1004 		break;
   1005 	default:
   1006 		error("Unknown PDU ID : 0x%x received", reqhdr->pdu_id);
   1007 		status = SDP_INVALID_SYNTAX;
   1008 		break;
   1009 	}
   1010 
   1011 send_rsp:
   1012 	if (status) {
   1013 		rsphdr->pdu_id = SDP_ERROR_RSP;
   1014 		bt_put_unaligned(htons(status), (uint16_t *)rsp.data);
   1015 		rsp.data_size = sizeof(uint16_t);
   1016 	}
   1017 
   1018 	SDPDBG("Sending rsp. status %d", status);
   1019 
   1020 	rsphdr->tid  = reqhdr->tid;
   1021 	rsphdr->plen = htons(rsp.data_size);
   1022 
   1023 	/* point back to the real buffer start and set the real rsp length */
   1024 	rsp.data_size += sizeof(sdp_pdu_hdr_t);
   1025 	rsp.data = buf;
   1026 
   1027 	/* stream the rsp PDU */
   1028 	sent = send(req->sock, rsp.data, rsp.data_size, 0);
   1029 
   1030 	SDPDBG("Bytes Sent : %d", sent);
   1031 
   1032 	free(rsp.data);
   1033 	free(req->buf);
   1034 }
   1035 
   1036 void handle_request(int sk, uint8_t *data, int len)
   1037 {
   1038 	struct sockaddr_l2 sa;
   1039 	socklen_t size;
   1040 	sdp_req_t req;
   1041 
   1042 	size = sizeof(sa);
   1043 	if (getpeername(sk, (struct sockaddr *) &sa, &size) < 0)
   1044 		return;
   1045 
   1046 	if (sa.l2_family == AF_BLUETOOTH) {
   1047 		struct l2cap_options lo;
   1048 		memset(&lo, 0, sizeof(lo));
   1049 		size = sizeof(lo);
   1050 		getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &lo, &size);
   1051 		bacpy(&req.bdaddr, &sa.l2_bdaddr);
   1052 		req.mtu = lo.omtu;
   1053 		req.local = 0;
   1054 		memset(&sa, 0, sizeof(sa));
   1055 		size = sizeof(sa);
   1056 		getsockname(sk, (struct sockaddr *) &sa, &size);
   1057 		bacpy(&req.device, &sa.l2_bdaddr);
   1058 	} else {
   1059 		bacpy(&req.device, BDADDR_ANY);
   1060 		bacpy(&req.bdaddr, BDADDR_LOCAL);
   1061 		req.mtu = 2048;
   1062 		req.local = 1;
   1063 	}
   1064 
   1065 	req.sock = sk;
   1066 	req.buf  = data;
   1067 	req.len  = len;
   1068 
   1069 	process_request(&req);
   1070 }
   1071