sdp.c revision a8efcfa5ca81ef29e4d56dac70761d9b9ffc9708
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-2004  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 version 2 as
13 *  published by the Free Software Foundation;
14 *
15 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
18 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
19 *  CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
20 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 *  ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
25 *  COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
26 *  SOFTWARE IS DISCLAIMED.
27 *
28 *
29 *  $Id$
30 */
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include <stdio.h>
37#include <errno.h>
38#include <unistd.h>
39#include <stdlib.h>
40#include <malloc.h>
41#include <sys/un.h>
42#include <sys/socket.h>
43
44#include <bluetooth/bluetooth.h>
45#include <bluetooth/hci.h>
46#include <bluetooth/hci_lib.h>
47#include <bluetooth/l2cap.h>
48#include <bluetooth/sdp.h>
49#include <bluetooth/sdp_lib.h>
50#include <bluetooth/sdp_internal.h>
51
52#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB"
53
54static uint128_t *bluetooth_base_uuid = NULL;
55
56/* Message structure. */
57struct tupla {
58	int index;
59	char *str;
60};
61
62static struct tupla Protocol[] = {
63	{ SDP_UUID,     "SDP"     },
64	{ RFCOMM_UUID,  "RFCOMM"  },
65	{ TCS_BIN_UUID, "TCS-BIN" },
66	{ L2CAP_UUID,   "L2CAP"   },
67	{ IP_UUID,      "IP"      },
68	{ UDP_UUID,     "UDP"     },
69	{ TCP_UUID,     "TCP"     },
70	{ TCS_AT_UUID,  "TCS-AT"  },
71	{ OBEX_UUID,    "OBEX"    },
72	{ FTP_UUID,     "FTP"     },
73	{ HTTP_UUID,    "HTTP"    },
74	{ WSP_UUID,     "WSP"     },
75	{ BNEP_UUID,    "BNEP"    },
76	{ HIDP_UUID,    "HIDP"    },
77	{ CMTP_UUID,    "CMTP"    },
78	{ 0 }
79};
80
81static struct tupla ServiceClass[] = {
82	{ SDP_SERVER_SVCLASS_ID,        "SDP Server" },
83	{ BROWSE_GRP_DESC_SVCLASS_ID,   "Browse Group Descriptor" },
84	{ PUBLIC_BROWSE_GROUP,          "Public Browse Group" },
85	{ SERIAL_PORT_SVCLASS_ID,       "Serial Port" },
86	{ LAN_ACCESS_SVCLASS_ID,        "LAN Access Using PPP" },
87	{ DIALUP_NET_SVCLASS_ID,        "Dialup Networking" },
88	{ IRMC_SYNC_SVCLASS_ID,	        "IrMCSync" },
89	{ OBEX_OBJPUSH_SVCLASS_ID,      "OBEX Object Push" },
90	{ OBEX_FILETRANS_SVCLASS_ID,    "OBEX File Transfer" },
91	{ IRMC_SYNC_CMD_SVCLASS_ID,     "IrMCSync Command" },
92	{ HEADSET_SVCLASS_ID,           "Headset" },
93	{ CORDLESS_TELEPHONY_SVCLASS_ID,"Cordless Telephony" },
94	{ INTERCOM_SVCLASS_ID,          "Intercom" },
95	{ FAX_SVCLASS_ID,               "Fax" },
96	{ HEADSET_AGW_SVCLASS_ID,       "Headset Audio Gateway" },
97	{ PNP_INFO_SVCLASS_ID,          "PnP Information" },
98	{ GENERIC_NETWORKING_SVCLASS_ID,"Generic Networking" },
99	{ GENERIC_FILETRANS_SVCLASS_ID, "Generic File Transfer" },
100	{ GENERIC_AUDIO_SVCLASS_ID,     "Generic Audio" },
101	{ GENERIC_TELEPHONY_SVCLASS_ID, "Generic Telephony" },
102	{ PANU_SVCLASS_ID,              "PAN user" },
103	{ NAP_SVCLASS_ID,               "Network access point" },
104	{ GN_SVCLASS_ID,                "PAN group network" },
105	{ HID_SVCLASS_ID,               "Human Interface Device" },
106	{ CIP_SVCLASS_ID,               "Common ISDN Access" },
107	{ 0 }
108};
109
110static struct tupla Profile[] = {
111	{ SERIAL_PORT_PROFILE_ID,        "Serial Port" },
112	{ LAN_ACCESS_PROFILE_ID,         "LAN Access Using PPP" },
113	{ DIALUP_NET_PROFILE_ID,         "Dialup Networking" },
114	{ IRMC_SYNC_PROFILE_ID,          "IrMCSync" },
115	{ OBEX_OBJPUSH_PROFILE_ID,       "OBEX Object Push" },
116	{ OBEX_FILETRANS_PROFILE_ID,     "OBEX File Transfer" },
117	{ IRMC_SYNC_CMD_PROFILE_ID,      "IrMCSync Command" },
118	{ HEADSET_PROFILE_ID,            "Headset" },
119	{ CORDLESS_TELEPHONY_PROFILE_ID, "Cordless Telephony" },
120	{ INTERCOM_PROFILE_ID,           "Intercom" },
121	{ FAX_PROFILE_ID,                "Fax" },
122	{ HEADSET_AGW_PROFILE_ID,        "Headset Audio Gateway" },
123	{ PANU_PROFILE_ID,               "PAN user" },
124	{ NAP_PROFILE_ID,                "PAN access point" },
125	{ GN_PROFILE_ID,                 "PAN group network" },
126	{ HID_SVCLASS_ID,                "Human Interface Device" },
127	{ CIP_SVCLASS_ID,                "Common ISDN Access" },
128	{ 0 }
129};
130
131static char *string_lookup(struct tupla *pt0, int index)
132{
133	struct tupla *pt;
134	for (pt = pt0; pt->index; pt++)
135		if (pt->index == index)
136			return pt->str;
137	return "";
138}
139
140/*
141 * Prints into a string the Protocol UUID
142 * coping a maximum of n characters.
143 */
144static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n)
145{
146	char *str2;
147
148	if (!uuid) {
149		snprintf(str, n, "NULL");
150		return -2;
151	}
152	switch (uuid->type) {
153	case SDP_UUID16:
154		str2 = string_lookup(message, uuid->value.uuid16);
155		snprintf(str, n, str2);
156		break;
157	case SDP_UUID32:
158		snprintf(str, n, "Error: This is uuid32");
159		return -3;
160	case SDP_UUID128:
161		snprintf(str, n, "Error: This is uuid128");
162		return -4;
163	default:
164		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);
165		return -1;
166	}
167	return 0;
168}
169
170int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n)
171{
172	return uuid2str(Protocol, uuid, str, n);
173}
174
175int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n)
176{
177	return uuid2str(ServiceClass, uuid, str, n);
178}
179
180int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n)
181{
182	return uuid2str(Profile, uuid, str, n);
183}
184
185/*
186 * convert the UUID to string, copying a maximum of n characters.
187 */
188int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n)
189{
190	if (!uuid) {
191		snprintf(str, n, "NULL");
192		return -2;
193	}
194	switch (uuid->type) {
195	case SDP_UUID16:
196		snprintf(str, n, "%.4x", uuid->value.uuid16);
197		break;
198	case SDP_UUID32:
199		snprintf(str, n, "%.8x", uuid->value.uuid32);
200		break;
201	case SDP_UUID128:{
202		unsigned int   data0;
203		unsigned short data1;
204		unsigned short data2;
205		unsigned short data3;
206		unsigned int   data4;
207		unsigned short data5;
208
209		memcpy(&data0, &uuid->value.uuid128.data[0], 4);
210		memcpy(&data1, &uuid->value.uuid128.data[4], 2);
211		memcpy(&data2, &uuid->value.uuid128.data[6], 2);
212		memcpy(&data3, &uuid->value.uuid128.data[8], 2);
213		memcpy(&data4, &uuid->value.uuid128.data[10], 4);
214		memcpy(&data5, &uuid->value.uuid128.data[14], 2);
215
216		snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
217				ntohl(data0), ntohs(data1),
218				ntohs(data2), ntohs(data3),
219				ntohl(data4), ntohs(data5));
220		}
221		break;
222	default:
223		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);
224		return -1;	// Enum type of UUID not set
225	}
226	return 0;
227}
228
229#ifdef SDP_DEBUG
230/*
231 * Function prints the UUID in hex as per defined syntax -
232 *
233 * 4bytes-2bytes-2bytes-2bytes-6bytes
234 *
235 * There is some ugly code, including hardcoding, but
236 * that is just the way it is converting 16 and 32 bit
237 * UUIDs to 128 bit as defined in the SDP doc
238 */
239void sdp_uuid_print(const uuid_t *uuid)
240{
241	if (uuid == NULL) {
242		SDPERR("Null passed to print UUID\n");
243		return;
244	}
245	if (uuid->type == SDP_UUID16) {
246		SDPDBG("  uint16_t : 0x%.4x\n", uuid->value.uuid16);
247	} else if (uuid->type == SDP_UUID32) {
248		SDPDBG("  uint32_t : 0x%.8x\n", uuid->value.uuid32);
249	} else if (uuid->type == SDP_UUID128) {
250		unsigned int data0;
251		unsigned short data1;
252		unsigned short data2;
253		unsigned short data3;
254		unsigned int data4;
255		unsigned short data5;
256
257		memcpy(&data0, &uuid->value.uuid128.data[0], 4);
258		memcpy(&data1, &uuid->value.uuid128.data[4], 2);
259		memcpy(&data2, &uuid->value.uuid128.data[6], 2);
260		memcpy(&data3, &uuid->value.uuid128.data[8], 2);
261		memcpy(&data4, &uuid->value.uuid128.data[10], 4);
262		memcpy(&data5, &uuid->value.uuid128.data[14], 2);
263
264		SDPDBG("  uint128_t : 0x%.8x-", ntohl(data0));
265		SDPDBG("%.4x-", ntohs(data1));
266		SDPDBG("%.4x-", ntohs(data2));
267		SDPDBG("%.4x-", ntohs(data3));
268		SDPDBG("%.8x", ntohl(data4));
269		SDPDBG("%.4x\n", ntohs(data5));
270	} else
271		SDPERR("Enum type of UUID not set\n");
272}
273#endif
274
275sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value)
276{
277	sdp_data_t *seq;
278	int len = 0;
279	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));
280
281	if (!d)
282		return NULL;
283
284	memset(d, 0, sizeof(sdp_data_t));
285	d->dtd = dtd;
286	d->unitSize = sizeof(uint8_t);
287
288	switch (dtd) {
289	case SDP_DATA_NIL:
290		break;
291	case SDP_UINT8:
292		d->val.uint8 = *(uint8_t *)value;
293		d->unitSize += sizeof(uint8_t);
294		break;
295	case SDP_INT8:
296	case SDP_BOOL:
297		d->val.int8 = *(int8_t *)value;
298		d->unitSize += sizeof(int8_t);
299		break;
300	case SDP_UINT16:
301		d->val.uint16 = sdp_get_unaligned((uint16_t *)value);
302		d->unitSize += sizeof(uint16_t);
303		break;
304	case SDP_INT16:
305		d->val.int16 = sdp_get_unaligned((int16_t *)value);
306		d->unitSize += sizeof(int16_t);
307		break;
308	case SDP_UINT32:
309		d->val.uint32 = sdp_get_unaligned((uint32_t *)value);
310		d->unitSize += sizeof(uint32_t);
311		break;
312	case SDP_INT32:
313		d->val.int32 = sdp_get_unaligned((int32_t *)value);
314		d->unitSize += sizeof(int32_t);
315		break;
316	case SDP_INT64:
317		d->val.int64 = sdp_get_unaligned((int64_t *)value);
318		d->unitSize += sizeof(int64_t);
319		break;
320	case SDP_UINT64:
321		d->val.uint64 = sdp_get_unaligned((uint64_t *)value);
322		d->unitSize += sizeof(uint64_t);
323		break;
324	case SDP_UINT128:
325		memcpy(&d->val.uint128.data, value, sizeof(uint128_t));
326		d->unitSize += sizeof(uint128_t);
327		break;
328	case SDP_INT128:
329		memcpy(&d->val.int128.data, value, sizeof(uint128_t));
330		d->unitSize += sizeof(uint128_t);
331		break;
332	case SDP_UUID16:
333		sdp_uuid16_create(&d->val.uuid, sdp_get_unaligned((uint16_t *)value));
334		d->unitSize += sizeof(uint16_t);
335		break;
336	case SDP_UUID32:
337		sdp_uuid32_create(&d->val.uuid, sdp_get_unaligned((uint32_t *)value));
338		d->unitSize += sizeof(uint32_t);
339		break;
340	case SDP_UUID128:
341		sdp_uuid128_create(&d->val.uuid, value);
342		d->unitSize += sizeof(uint128_t);
343		break;
344	case SDP_URL_STR8:
345	case SDP_TEXT_STR8:
346	case SDP_URL_STR16:
347	case SDP_TEXT_STR16:
348		if (!value)
349			goto out_error;
350
351		len = strlen(value);
352		d->unitSize += len;
353		if (len <= USHRT_MAX) {
354			d->val.str = (char *)malloc(len + 1);
355			if (!d->val.str)
356				goto out_error;
357
358			strcpy(d->val.str, value);
359			if (len <= UCHAR_MAX) {
360				d->unitSize += sizeof(uint8_t);
361				if (dtd != SDP_URL_STR8 && dtd != SDP_TEXT_STR8) {
362					if (dtd == SDP_URL_STR16)
363						dtd = SDP_URL_STR8;
364					else
365						dtd = SDP_TEXT_STR8;
366				}
367			} else {
368				d->unitSize += sizeof(uint16_t);
369				if (dtd == SDP_TEXT_STR8)
370					dtd = SDP_TEXT_STR16;
371				else
372					dtd = SDP_URL_STR16;
373			}
374		} else {
375			SDPERR("Strings of size > USHRT_MAX not supported\n");
376			goto out_error;
377		}
378		break;
379	case SDP_URL_STR32:
380	case SDP_TEXT_STR32:
381		SDPERR("Strings of size > USHRT_MAX not supported\n");
382		break;
383	case SDP_ALT8:
384	case SDP_ALT16:
385	case SDP_ALT32:
386	case SDP_SEQ8:
387	case SDP_SEQ16:
388	case SDP_SEQ32:
389		if (dtd == SDP_ALT8 || dtd == SDP_SEQ8)
390			d->unitSize += sizeof(uint8_t);
391		else if (dtd == SDP_ALT16 || dtd == SDP_SEQ16)
392			d->unitSize += sizeof(uint16_t);
393		else if (dtd == SDP_ALT32 || dtd == SDP_SEQ32)
394			d->unitSize += sizeof(uint32_t);
395		seq = (sdp_data_t *)value;
396		d->val.dataseq = seq;
397		for (; seq; seq = seq->next)
398			d->unitSize += seq->unitSize;
399		break;
400	default:
401		goto out_error;
402	}
403	return d;
404
405out_error:
406	free(d);
407	return NULL;
408}
409
410sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *d)
411{
412	if (seq) {
413		sdp_data_t *p;
414		for (p = seq; p->next; p = p->next);
415		p->next = d;
416	} else
417		seq = d;
418	d->next = NULL;
419	return seq;
420}
421
422sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len)
423{
424	sdp_data_t *curr = NULL, *seq = NULL;
425	int i;
426
427	for (i = 0; i < len; i++) {
428		sdp_data_t *data;
429		uint8_t dtd = *(uint8_t *)dtds[i];
430		if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32)
431			data = (sdp_data_t *)values[i];
432		else
433			data = sdp_data_alloc(dtd, values[i]);
434		if (!data)
435			return NULL;
436		if (curr)
437			curr->next = data;
438		else
439			seq = data;
440		curr = data;
441	}
442	return sdp_data_alloc(SDP_SEQ8, seq);
443}
444
445int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d)
446{
447	sdp_data_t *p = sdp_data_get(rec, attr);
448
449	if (p)
450		return -1;
451	d->attrId = attr;
452	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func);
453	return 0;
454}
455
456void sdp_attr_remove(sdp_record_t *rec, uint16_t attr)
457{
458	sdp_data_t *d = sdp_data_get(rec, attr);
459	if (d)
460		rec->attrlist = sdp_list_remove(rec->attrlist, d);
461}
462
463void sdp_set_seq_len(char *ptr, int length)
464{
465	uint8_t dtd = *(uint8_t *)ptr++;
466
467	switch (dtd) {
468	case SDP_SEQ8:
469	case SDP_ALT8:
470	case SDP_TEXT_STR8:
471	case SDP_URL_STR8:
472		*(uint8_t *)ptr = (uint8_t)length;
473		break;
474	case SDP_SEQ16:
475	case SDP_ALT16:
476	case SDP_TEXT_STR16:
477	case SDP_URL_STR16:
478		sdp_put_unaligned(htons(length), (uint16_t *)ptr);
479		break;
480	case SDP_SEQ32:
481	case SDP_ALT32:
482	case SDP_TEXT_STR32:
483	case SDP_URL_STR32:
484		sdp_put_unaligned(htons(length), (uint32_t *)ptr);
485		break;
486	}
487}
488
489int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd)
490{
491	int orig = buf->data_size;
492	uint8_t *p = buf->data + buf->data_size;
493
494	*p++ = dtd;
495	buf->data_size += sizeof(uint8_t);
496	switch (dtd) {
497	case SDP_SEQ8:
498	case SDP_TEXT_STR8:
499	case SDP_URL_STR8:
500	case SDP_ALT8:
501		buf->data_size += sizeof(uint8_t);
502		break;
503	case SDP_SEQ16:
504	case SDP_TEXT_STR16:
505	case SDP_URL_STR16:
506	case SDP_ALT16:
507		buf->data_size += sizeof(uint16_t);
508		break;
509	case SDP_SEQ32:
510	case SDP_TEXT_STR32:
511	case SDP_URL_STR32:
512	case SDP_ALT32:
513		buf->data_size += sizeof(uint32_t);
514		break;
515	}
516	return buf->data_size - orig;
517}
518
519void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr)
520{
521	uint8_t *p = buf->data;
522
523	// data type for attr
524	*p++ = SDP_UINT16;
525	buf->data_size = sizeof(uint8_t);
526	sdp_put_unaligned(htons(attr), (uint16_t *)p);
527	p += sizeof(uint16_t);
528	buf->data_size += sizeof(uint16_t);
529}
530
531static int get_data_size(sdp_buf_t *buf, sdp_data_t *sdpdata)
532{
533	sdp_data_t *d;
534	int n = 0;
535
536	for (d = sdpdata->val.dataseq; d; d = d->next)
537		n += sdp_gen_pdu(buf, d);
538	return n;
539}
540
541int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
542{
543	int pdu_size = 0, data_size = 0;
544	unsigned char *src = NULL, is_seq = 0, is_alt = 0;
545	uint8_t dtd = d->dtd;
546	uint16_t u16;
547	uint32_t u32;
548	uint64_t u64;
549	uint128_t u128;
550	char *seqp = buf->data + buf->data_size;
551
552	pdu_size = sdp_set_data_type(buf, dtd);
553	switch (dtd) {
554	case SDP_DATA_NIL:
555		break;
556	case SDP_UINT8:
557		src = &d->val.uint8;
558		data_size = sizeof(uint8_t);
559		break;
560	case SDP_UINT16:
561		u16 = htons(d->val.uint16);
562		src = (unsigned char *)&u16;
563		data_size = sizeof(uint16_t);
564		break;
565	case SDP_UINT32:
566		u32 = htonl(d->val.uint32);
567		src = (unsigned char *)&u32;
568		data_size = sizeof(uint32_t);
569		break;
570	case SDP_UINT64:
571		u64 = hton64(d->val.uint64);
572		src = (unsigned char *)&u64;
573		data_size = sizeof(uint64_t);
574		break;
575	case SDP_UINT128:
576		hton128(&d->val.uint128, &u128);
577		src = (unsigned char *)&u128;
578		data_size = sizeof(uint128_t);
579		break;
580	case SDP_INT8:
581	case SDP_BOOL:
582		src = (unsigned char *)&d->val.int8;
583		data_size = sizeof(int8_t);
584		break;
585	case SDP_INT16:
586		u16 = htons(d->val.int16);
587		src = (unsigned char *)&u16;
588		data_size = sizeof(int16_t);
589		break;
590	case SDP_INT32:
591		u32 = htonl(d->val.int32);
592		src = (unsigned char *)&u32;
593		data_size = sizeof(int32_t);
594		break;
595	case SDP_INT64:
596		u64 = hton64(d->val.int64);
597		src = (unsigned char *)&u64;
598		data_size = sizeof(int64_t);
599		break;
600	case SDP_INT128:
601		hton128(&d->val.int128, &u128);
602		src = (unsigned char *)&u128;
603		data_size = sizeof(uint128_t);
604		break;
605	case SDP_TEXT_STR8:
606	case SDP_URL_STR8:
607	case SDP_TEXT_STR16:
608	case SDP_TEXT_STR32:
609	case SDP_URL_STR16:
610	case SDP_URL_STR32:
611		src = (unsigned char *)d->val.str;
612		data_size = strlen(d->val.str);
613		sdp_set_seq_len(seqp, data_size);
614		break;
615	case SDP_SEQ8:
616	case SDP_SEQ16:
617	case SDP_SEQ32:
618		is_seq = 1;
619		data_size = get_data_size(buf, d);
620		sdp_set_seq_len(seqp, data_size);
621		break;
622	case SDP_ALT8:
623	case SDP_ALT16:
624	case SDP_ALT32:
625		is_alt = 1;
626		data_size = get_data_size(buf, d);
627		sdp_set_seq_len(seqp, data_size);
628		break;
629	case SDP_UUID16:
630		u16 = htons(d->val.uuid.value.uuid16);
631		src = (unsigned char *)&u16;
632		data_size = sizeof(uint16_t);
633		break;
634	case SDP_UUID32:
635		u32 = htonl(d->val.uuid.value.uuid32);
636		src = (unsigned char *)&u32;
637		data_size = sizeof(uint32_t);
638		break;
639	case SDP_UUID128:
640		src = (unsigned char *)&d->val.uuid.value.uuid128;
641		data_size = sizeof(uint128_t);
642		break;
643	default:
644		break;
645	}
646	if (!is_seq && !is_alt) {
647		if (src && buf) {
648			memcpy(buf->data + buf->data_size, src, data_size);
649			buf->data_size += data_size;
650		} else if (dtd != SDP_DATA_NIL)
651			SDPDBG("Gen PDU : Cant copy from NULL source or dest\n");
652	}
653	pdu_size += data_size;
654	return pdu_size;
655}
656
657static void sdp_attr_pdu(void *value, void *udata)
658{
659	sdp_append_to_pdu((sdp_buf_t *)udata, (sdp_data_t *)value);
660}
661
662int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *buf)
663{
664	buf->data = (char *)malloc(SDP_PDU_CHUNK_SIZE);
665	if (buf->data) {
666		buf->buf_size = SDP_PDU_CHUNK_SIZE;
667		buf->data_size = 0;
668		memset(buf->data, 0, buf->buf_size);
669		sdp_list_foreach(rec->attrlist, sdp_attr_pdu, buf);
670		return 0;
671	}
672	return -1;
673}
674
675void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *d)
676{
677	sdp_data_t *p = sdp_data_get(rec, attr);
678
679	if (p) {
680		rec->attrlist = sdp_list_remove(rec->attrlist, p);
681		sdp_data_free(p);
682	}
683	d->attrId = attr;
684	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, (void *)d, sdp_attrid_comp_func);
685}
686
687int sdp_attrid_comp_func(const void *key1, const void *key2)
688{
689	const sdp_data_t *d1 = (const sdp_data_t *)key1;
690	const sdp_data_t *d2 = (const sdp_data_t *)key2;
691
692	if (d1 && d2)
693		return d1->attrId - d2->attrId;
694	return 0;
695}
696
697static void data_seq_free(sdp_data_t *seq)
698{
699	sdp_data_t *d = seq->val.dataseq;
700
701	while (d) {
702		sdp_data_t *next = d->next;
703		sdp_data_free(d);
704		d = next;
705	}
706}
707
708void sdp_data_free(sdp_data_t *d)
709{
710	switch (d->dtd) {
711	case SDP_SEQ8:
712	case SDP_SEQ16:
713	case SDP_SEQ32:
714		data_seq_free(d);
715		break;
716	case SDP_URL_STR8:
717	case SDP_URL_STR16:
718	case SDP_URL_STR32:
719	case SDP_TEXT_STR8:
720	case SDP_TEXT_STR16:
721	case SDP_TEXT_STR32:
722		free(d->val.str);
723		break;
724	}
725	free(d);
726}
727
728static sdp_data_t *extract_int(const void *p, int *len)
729{
730	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));
731
732	SDPDBG("Extracting integer\n");
733	memset(d, 0, sizeof(sdp_data_t));
734	d->dtd = *(uint8_t *)p;
735	p += sizeof(uint8_t);
736	*len += sizeof(uint8_t);
737
738	switch (d->dtd) {
739	case SDP_DATA_NIL:
740		break;
741	case SDP_BOOL:
742	case SDP_INT8:
743	case SDP_UINT8:
744		*len += sizeof(uint8_t);
745		d->val.uint8 = *(uint8_t *)p;
746		break;
747	case SDP_INT16:
748	case SDP_UINT16:
749		*len += sizeof(uint16_t);
750		d->val.uint16 = ntohs(sdp_get_unaligned((uint16_t *)p));
751		break;
752	case SDP_INT32:
753	case SDP_UINT32:
754		*len += sizeof(uint32_t);
755		d->val.uint32 = ntohl(sdp_get_unaligned((uint32_t *)p));
756		break;
757	case SDP_INT64:
758	case SDP_UINT64:
759		*len += sizeof(uint64_t);
760		d->val.uint64 = ntoh64(sdp_get_unaligned((uint64_t *)p));
761		break;
762	case SDP_INT128:
763	case SDP_UINT128:
764		*len += sizeof(uint128_t);
765		ntoh128((uint128_t *)p, &d->val.uint128);
766		break;
767	default:
768		free(d);
769		d = NULL;
770	}
771	return d;
772}
773
774static sdp_data_t *extract_uuid(const void *p, int *len, sdp_record_t *rec)
775{
776	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));
777
778	SDPDBG("Extracting UUID");
779	memset(d, 0, sizeof(sdp_data_t));
780	if (0 > sdp_uuid_extract(p, &d->val.uuid, len)) {
781		free(d);
782		return NULL;
783	}
784	d->dtd = *(uint8_t *)p;
785	sdp_pattern_add_uuid(rec, &d->val.uuid);
786	return d;
787}
788
789/*
790 * Extract strings from the PDU (could be service description and similar info)
791 */
792static sdp_data_t *extract_str(const void *p, int *len)
793{
794	char *s;
795	int n;
796	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));
797
798	memset(d, 0, sizeof(sdp_data_t));
799	d->dtd = *(uint8_t *)p;
800	p += sizeof(uint8_t);
801	*len += sizeof(uint8_t);
802
803	switch (d->dtd) {
804	case SDP_TEXT_STR8:
805	case SDP_URL_STR8:
806		n = *(uint8_t *)p;
807		p += sizeof(uint8_t);
808		*len += sizeof(uint8_t) + n;
809		break;
810	case SDP_TEXT_STR16:
811	case SDP_URL_STR16:
812		n = ntohs(sdp_get_unaligned((uint16_t *)p));
813		p += sizeof(uint16_t);
814		*len += sizeof(uint16_t) + n;
815		break;
816	default:
817		SDPERR("Sizeof text string > UINT16_MAX\n");
818		free(d);
819		return 0;
820	}
821
822	s = malloc(n + 1);
823	memset(s, 0, n + 1);
824	memcpy(s, p, n);
825
826	SDPDBG("Len : %d\n", n);
827	SDPDBG("Str : %s\n", s);
828
829	d->val.str = s;
830	d->unitSize = n;
831	return d;
832}
833
834static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec)
835{
836	int seqlen, n = 0;
837	sdp_data_t *curr, *prev;
838	sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t));
839
840	SDPDBG("Extracting SEQ");
841	memset(d, 0, sizeof(sdp_data_t));
842	*len = sdp_extract_seqtype(p, &d->dtd, &seqlen);
843	SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen);
844
845	if (*len == 0)
846		return d;
847
848	p += *len;
849	curr = prev = NULL;
850	while (n < seqlen) {
851		int attrlen = 0;
852		curr = sdp_extract_attr(p, &attrlen, rec);
853		if (curr == NULL)
854			break;
855
856		if (prev)
857			prev->next = curr;
858		else
859			d->val.dataseq = curr;
860		prev = curr;
861		p += attrlen;
862		n += attrlen;
863
864		SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen);
865	}
866
867	*len += n;
868	return d;
869}
870
871sdp_data_t *sdp_extract_attr(const char *p, int *size, sdp_record_t *rec)
872{
873	sdp_data_t *elem;
874	int n = 0;
875	uint8_t dtd = *(const uint8_t *)p;
876
877	SDPDBG("extract_attr: dtd=0x%x", dtd);
878	switch (dtd) {
879	case SDP_DATA_NIL:
880	case SDP_BOOL:
881	case SDP_UINT8:
882	case SDP_UINT16:
883	case SDP_UINT32:
884	case SDP_UINT64:
885	case SDP_UINT128:
886	case SDP_INT8:
887	case SDP_INT16:
888	case SDP_INT32:
889	case SDP_INT64:
890	case SDP_INT128:
891		elem = extract_int(p, &n);
892		break;
893	case SDP_UUID16:
894	case SDP_UUID32:
895	case SDP_UUID128:
896		elem = extract_uuid(p, &n, rec);
897		break;
898	case SDP_TEXT_STR8:
899	case SDP_TEXT_STR16:
900	case SDP_TEXT_STR32:
901	case SDP_URL_STR8:
902	case SDP_URL_STR16:
903	case SDP_URL_STR32:
904		elem = extract_str(p, &n);
905		break;
906	case SDP_SEQ8:
907	case SDP_SEQ16:
908	case SDP_SEQ32:
909	case SDP_ALT8:
910	case SDP_ALT16:
911	case SDP_ALT32:
912		elem = extract_seq(p, &n, rec);
913		break;
914	default:
915		SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd);
916		return NULL;
917	}
918	*size += n;
919	return elem;
920}
921
922#ifdef SDP_DEBUG
923static void attr_print_func(void *value, void *userData)
924{
925	sdp_data_t *d = (sdp_data_t *)value;
926
927	SDPDBG("=====================================\n");
928	SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n",  d->attrId);
929	SDPDBG("ATTRIBUTE VALUE PTR : 0x%x\n", (uint32_t)value);
930	if (d)
931		sdp_data_print(d);
932	else
933		SDPDBG("NULL value\n");
934	SDPDBG("=====================================\n");
935}
936
937void sdp_print_service_attr(sdp_list_t *svcAttrList)
938{
939	sdp_list_foreach(svcAttrList, attr_print_func, NULL);
940}
941#endif
942
943sdp_record_t *sdp_extract_pdu(const char *buf, int *scanned)
944{
945	int extracted = 0, seqlen = 0;
946	uint8_t dtd;
947	uint16_t attr;
948	sdp_record_t *rec = sdp_record_alloc();
949	const char *p = buf;
950
951	*scanned = sdp_extract_seqtype(buf, &dtd, &seqlen);
952	p += *scanned;
953	rec->attrlist = NULL;
954	while (extracted < seqlen) {
955		int n = sizeof(uint8_t), attrlen = 0;
956		sdp_data_t *data = NULL;
957
958		SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, extracted);
959		dtd = *(uint8_t *)p;
960		attr = ntohs(sdp_get_unaligned((uint16_t *)(p+n)));
961		n += sizeof(uint16_t);
962
963		SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr);
964
965		data = sdp_extract_attr(p+n, &attrlen, rec);
966
967		SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen);
968
969		n += attrlen;
970		if (data == NULL) {
971			SDPDBG("Terminating extraction of attributes");
972			break;
973		}
974		if (attr == SDP_ATTR_RECORD_HANDLE)
975			rec->handle = data->val.uint32;
976		extracted += n;
977		p += n;
978		sdp_attr_replace(rec, attr, data);
979		SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d",
980					seqlen, extracted);
981	}
982#ifdef SDP_DEBUG
983	SDPDBG("Successful extracting of Svc Rec attributes\n");
984	sdp_print_service_attr(rec->attrlist);
985#endif
986	*scanned += seqlen;
987	return rec;
988}
989
990#ifdef SDP_DEBUG
991static void print_dataseq(sdp_data_t *p)
992{
993	sdp_data_t *d;
994
995	for (d = p; d; d = d->next)
996		sdp_data_print(d);
997}
998#endif
999
1000void sdp_record_print(const sdp_record_t *rec)
1001{
1002	sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY);
1003	if (d)
1004		printf("Service Name: %s\n", d->val.str);
1005	d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY);
1006	if (d)
1007		printf("Service Description: %s\n", d->val.str);
1008	d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY);
1009	if (d)
1010		printf("Service Provider: %s\n", d->val.str);
1011}
1012
1013#ifdef SDP_DEBUG
1014void sdp_data_print(sdp_data_t *d)
1015{
1016	switch (d->dtd) {
1017	case SDP_DATA_NIL:
1018		SDPDBG("NIL\n");
1019		break;
1020	case SDP_BOOL:
1021	case SDP_UINT8:
1022	case SDP_UINT16:
1023	case SDP_UINT32:
1024	case SDP_UINT64:
1025	case SDP_UINT128:
1026	case SDP_INT8:
1027	case SDP_INT16:
1028	case SDP_INT32:
1029	case SDP_INT64:
1030	case SDP_INT128:
1031		SDPDBG("Integer : 0x%x\n", d->val.uint32);
1032		break;
1033	case SDP_UUID16:
1034	case SDP_UUID32:
1035	case SDP_UUID128:
1036		SDPDBG("UUID\n");
1037		sdp_uuid_print(&d->val.uuid);
1038		break;
1039	case SDP_TEXT_STR8:
1040	case SDP_TEXT_STR16:
1041	case SDP_TEXT_STR32:
1042		SDPDBG("Text : %s\n", d->val.str);
1043		break;
1044	case SDP_URL_STR8:
1045	case SDP_URL_STR16:
1046	case SDP_URL_STR32:
1047		SDPDBG("URL : %s\n", d->val.str);
1048		break;
1049	case SDP_SEQ8:
1050	case SDP_SEQ16:
1051	case SDP_SEQ32:
1052		print_dataseq(d->val.dataseq);
1053		break;
1054	case SDP_ALT8:
1055	case SDP_ALT16:
1056	case SDP_ALT32:
1057		SDPDBG("Data Sequence Alternates\n");
1058		print_dataseq(d->val.dataseq);
1059		break;
1060	}
1061}
1062#endif
1063
1064sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId)
1065{
1066	if (rec->attrlist) {
1067		sdp_data_t sdpTemplate;
1068		sdp_list_t *p;
1069
1070		sdpTemplate.attrId = attrId;
1071		p = sdp_list_find(rec->attrlist, &sdpTemplate, sdp_attrid_comp_func);
1072		if (p)
1073			return (sdp_data_t *)p->data;
1074	}
1075	return 0;
1076}
1077
1078/*
1079 * Extract the sequence type and its length, and return offset into buf
1080 * or 0 on failure.
1081 */
1082int sdp_extract_seqtype(const char *buf, uint8_t *dtdp, int *size)
1083{
1084	uint8_t dtd = *(uint8_t *)buf;
1085	int scanned = sizeof(uint8_t);
1086
1087	buf += sizeof(uint8_t);
1088	*dtdp = dtd;
1089	switch (dtd) {
1090	case SDP_SEQ8:
1091	case SDP_ALT8:
1092		*size = *(uint8_t *)buf;
1093		scanned += sizeof(uint8_t);
1094		break;
1095	case SDP_SEQ16:
1096	case SDP_ALT16:
1097		*size = ntohs(sdp_get_unaligned((uint16_t *)buf));
1098		scanned += sizeof(uint16_t);
1099		break;
1100	case SDP_SEQ32:
1101	case SDP_ALT32:
1102		*size = ntohl(sdp_get_unaligned((uint32_t *)buf));
1103		scanned += sizeof(uint32_t);
1104		break;
1105	default:
1106		SDPERR("Unknown sequence type, aborting\n");
1107		return 0;
1108	}
1109	return scanned;
1110}
1111
1112int sdp_send_req(sdp_session_t *session, char *buf, int size)
1113{
1114	int sent = 0;
1115
1116	while (sent < size) {
1117		int n = send(session->sock, buf + sent, size - sent, 0);
1118		if (n < 0)
1119			return -1;
1120		sent += n;
1121	}
1122	return 0;
1123}
1124
1125int sdp_read_rsp(sdp_session_t *session, char *buf, int size)
1126{
1127	fd_set readFds;
1128	struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 };
1129
1130	FD_SET(session->sock, &readFds);
1131	SDPDBG("Waiting for response\n");
1132	if (0 == select(session->sock + 1, &readFds, NULL, NULL, &timeout)) {
1133		SDPERR("Client timed out\n");
1134		errno = ETIMEDOUT;
1135		return -1;
1136	}
1137	return recv(session->sock, buf, size, 0);
1138}
1139
1140/*
1141 * generic send request, wait for response method.
1142 */
1143int sdp_send_req_w4_rsp(sdp_session_t *session, char *reqbuf, char *rspbuf, int reqsize, int *rspsize)
1144{
1145	int n;
1146	sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)reqbuf;
1147	sdp_pdu_hdr_t *rsphdr = (sdp_pdu_hdr_t *)rspbuf;
1148
1149	SDPDBG("");
1150	if (0 > sdp_send_req(session, reqbuf, reqsize)) {
1151		SDPERR("Error sending data:%s", strerror(errno));
1152		return -1;
1153	}
1154	n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE);
1155	if (0 > n)
1156		return -1;
1157	SDPDBG("Read : %d\n", n);
1158	if (n == 0 || reqhdr->tid != rsphdr->tid) {
1159		errno = EPROTO;
1160		return -1;
1161	}
1162	*rspsize = n;
1163	return 0;
1164}
1165
1166/*
1167 * singly-linked lists (after openobex implementation)
1168 */
1169sdp_list_t *sdp_list_append(sdp_list_t *p, void *d)
1170{
1171	sdp_list_t *q, *n = (sdp_list_t *)malloc(sizeof(sdp_list_t));
1172
1173	if (!n)
1174		return 0;
1175
1176	n->data = d;
1177	n->next = 0;
1178
1179	if (!p)
1180		return n;
1181
1182	for (q = p; q->next; q = q->next);
1183	q->next = n;
1184
1185	return p;
1186}
1187
1188sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d)
1189{
1190	sdp_list_t *p, *q;
1191
1192	for (q = 0, p = list; p; q = p, p = p->next)
1193		if (p->data == d) {
1194			if (q)
1195				q->next = p->next;
1196			else
1197				list = p->next;
1198			free(p);
1199			break;
1200		}
1201
1202	return list;
1203}
1204
1205sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *d, sdp_comp_func_t f)
1206{
1207	sdp_list_t *q, *p, *n;
1208
1209	n = (sdp_list_t *)malloc(sizeof(sdp_list_t));
1210	if (!n)
1211		return 0;
1212	n->data = d;
1213	for (q = 0, p = list; p; q = p, p = p->next)
1214		if (f(p->data, d) >= 0)
1215			break;
1216	// insert between q and p; if !q insert at head
1217	if (q)
1218		q->next = n;
1219	else
1220		list = n;
1221	n->next = p;
1222	return list;
1223}
1224
1225/*
1226 * Every element of the list points to things which need
1227 * to be free()'d. This method frees the list's contents
1228 */
1229void sdp_list_free(sdp_list_t *list, sdp_free_func_t f)
1230{
1231	sdp_list_t *next;
1232	while (list) {
1233		next = list->next;
1234		if (f)
1235			f(list->data);
1236		free(list);
1237		list = next;
1238	}
1239}
1240
1241static inline int __find_port(sdp_data_t *seq, int proto)
1242{
1243	if (!seq || !seq->next)
1244		return 0;
1245
1246	if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) {
1247		seq = seq->next;
1248		switch (seq->dtd) {
1249		case SDP_UINT8:
1250			return seq->val.uint8;
1251		case SDP_UINT16:
1252			return seq->val.uint16;
1253		}
1254	}
1255	return 0;
1256}
1257
1258int sdp_get_proto_port(const sdp_list_t *list, int proto)
1259{
1260	if (proto != L2CAP_UUID && proto != RFCOMM_UUID) {
1261		errno = EINVAL;
1262		return -1;
1263	}
1264
1265	for (; list; list = list->next) {
1266		sdp_list_t *p;
1267		for (p = list->data; p; p = p->next) {
1268			sdp_data_t *seq = (sdp_data_t *) p->data;
1269			int port = __find_port(seq, proto);
1270			if (port)
1271				return port;
1272		}
1273	}
1274	return 0;
1275}
1276
1277sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto)
1278{
1279	for (; list; list = list->next) {
1280		sdp_list_t *p;
1281		for (p = list->data; p; p = p->next) {
1282			sdp_data_t *seq = (sdp_data_t *) p->data;
1283			if (SDP_IS_UUID(seq->dtd) &&
1284					sdp_uuid_to_proto(&seq->val.uuid) == proto)
1285				return seq->next;
1286		}
1287	}
1288	return NULL;
1289}
1290
1291int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
1292{
1293	sdp_data_t *pdlist, *curr;
1294	sdp_list_t *ap = 0;
1295
1296	pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
1297	if (pdlist == NULL) {
1298		errno = ENODATA;
1299		return -1;
1300	}
1301	SDPDBG("AP type : 0%x\n", pdlist->dtd);
1302
1303	for (; pdlist; pdlist = pdlist->next) {
1304		sdp_list_t *pds = 0;
1305		for (curr = pdlist->val.dataseq; curr; curr = curr->next)
1306			pds = sdp_list_append(pds, curr->val.dataseq);
1307		ap = sdp_list_append(ap, pds);
1308	}
1309	*pap = ap;
1310	return 0;
1311}
1312
1313int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
1314{
1315	sdp_data_t *pdlist, *curr;
1316	sdp_list_t *ap = 0;
1317
1318	pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
1319	if (pdlist == NULL) {
1320		errno = ENODATA;
1321		return -1;
1322	}
1323	SDPDBG("AP type : 0%x\n", pdlist->dtd);
1324
1325	pdlist = pdlist->val.dataseq;
1326
1327	for (; pdlist; pdlist = pdlist->next) {
1328		sdp_list_t *pds = 0;
1329		for (curr = pdlist->val.dataseq; curr; curr = curr->next)
1330			pds = sdp_list_append(pds, curr->val.dataseq);
1331		ap = sdp_list_append(ap, pds);
1332	}
1333	*pap = ap;
1334	return 0;
1335}
1336
1337int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp)
1338{
1339	sdp_data_t *sdpdata = sdp_data_get(rec, attr);
1340
1341	*seqp = NULL;
1342	if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) {
1343		sdp_data_t *d;
1344		for (d = sdpdata->val.dataseq; d; d = d->next) {
1345			uuid_t *u = (uuid_t *)malloc(sizeof(uuid_t));
1346			memset((char *)u, 0, sizeof(uuid_t));
1347			if (d->dtd >= SDP_UUID16 && d->dtd <= SDP_UUID128) {
1348			  	*u = d->val.uuid;
1349			  	*seqp = sdp_list_append(*seqp, u);
1350			} else
1351				goto fail;
1352		}
1353		return 0;
1354	}
1355fail:
1356	sdp_list_free(*seqp, free);
1357	errno = EINVAL;
1358	return -1;
1359}
1360
1361int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq)
1362{
1363	int status = 0, i, len;
1364	void **dtds, **values;
1365	uint8_t uuid16 = SDP_UUID16;
1366	uint8_t uuid32 = SDP_UUID32;
1367	uint8_t uuid128 = SDP_UUID128;
1368	sdp_list_t *p;
1369
1370	len = sdp_list_len(seq);
1371	if (!seq || len == 0)
1372		return -1;
1373	dtds = (void **)malloc(len * sizeof(void *));
1374	values = (void **)malloc(len * sizeof(void *));
1375	for (p = seq, i = 0; i < len; i++, p = p->next) {
1376		uuid_t *uuid = (uuid_t *)p->data;
1377		if (uuid)
1378			switch (uuid->type) {
1379			case SDP_UUID16:
1380				dtds[i] = &uuid16;
1381				values[i] = &uuid->value.uuid16;
1382				break;
1383			case SDP_UUID32:
1384				dtds[i] = &uuid32;
1385				values[i] = &uuid->value.uuid32;
1386				break;
1387			case SDP_UUID128:
1388				dtds[i] = &uuid128;
1389				values[i] = &uuid->value.uuid128;
1390				break;
1391			default:
1392				status = -1;
1393				break;
1394			}
1395		else {
1396			status = -1;
1397			break;
1398		}
1399	}
1400	if (status == 0) {
1401		sdp_data_t *data = sdp_seq_alloc(dtds, values, len);
1402		sdp_attr_replace(rec, aid, data);
1403		sdp_pattern_add_uuidseq(rec, seq);
1404	}
1405	free(dtds);
1406	free(values);
1407	return status;
1408}
1409
1410int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq)
1411{
1412	sdp_lang_attr_t *lang;
1413	sdp_data_t *sdpdata, *curr_data;
1414
1415	*langSeq = NULL;
1416	sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST);
1417	if (sdpdata == NULL) {
1418		errno = ENODATA;
1419		return -1;
1420	}
1421	curr_data = sdpdata->val.dataseq;
1422	while (curr_data) {
1423		sdp_data_t *pCode = curr_data;
1424		sdp_data_t *pEncoding = pCode->next;
1425		sdp_data_t *pOffset = pEncoding->next;
1426		if (pCode && pEncoding && pOffset) {
1427			lang = (sdp_lang_attr_t *)malloc(sizeof(sdp_lang_attr_t));
1428			lang->code_ISO639 = pCode->val.uint16;
1429			lang->encoding = pEncoding->val.uint16;
1430			lang->base_offset = pOffset->val.uint16;
1431			SDPDBG("code_ISO639 :  0x%02x\n", lang->code_ISO639);
1432			SDPDBG("encoding :     0x%02x\n", lang->encoding);
1433			SDPDBG("base_offfset : 0x%02x\n", lang->base_offset);
1434			*langSeq = sdp_list_append(*langSeq, lang);
1435		}
1436		curr_data = pOffset->next;
1437	}
1438	return 0;
1439}
1440
1441int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
1442{
1443	sdp_profile_desc_t *profDesc;
1444	sdp_data_t *sdpdata, *seq;
1445
1446	*profDescSeq = NULL;
1447	sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST);
1448	if (!sdpdata || !sdpdata->val.dataseq) {
1449		errno = ENODATA;
1450		return -1;
1451	}
1452	for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) {
1453		sdp_data_t *uuid = seq->val.dataseq;
1454		sdp_data_t *pVnum = seq->val.dataseq->next;
1455		if (uuid && pVnum) {
1456			profDesc = (sdp_profile_desc_t *)malloc(sizeof(sdp_profile_desc_t));
1457			profDesc->uuid = uuid->val.uuid;
1458			profDesc->version = pVnum->val.uint16;
1459#ifdef SDP_DEBUG
1460			sdp_uuid_print(&profDesc->uuid);
1461			SDPDBG("Vnum : 0x%04x\n", profDesc->version);
1462#endif
1463			*profDescSeq = sdp_list_append(*profDescSeq, profDesc);
1464		}
1465	}
1466	return 0;
1467}
1468
1469int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16)
1470{
1471	sdp_data_t *d, *curr;
1472
1473	*u16 = NULL;
1474	d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST);
1475	if (d == NULL) {
1476		errno = ENODATA;
1477		return -1;
1478	}
1479	for (curr = d->val.dataseq; curr; curr = curr->next)
1480		*u16 = sdp_list_append(*u16, &curr->val.uint16);
1481	return 0;
1482}
1483
1484/* flexible extraction of basic attributes - Jean II */
1485/* How do we expect caller to extract predefined data sequences? */
1486int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value)
1487{
1488	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);
1489
1490	if (sdpdata)
1491		/* Verify that it is what the caller expects */
1492		if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 ||
1493		sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 ||
1494		sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 ||
1495		sdpdata->dtd == SDP_INT32) {
1496			*value = sdpdata->val.uint32;
1497			return 0;
1498		}
1499	errno = EINVAL;
1500	return -1;
1501}
1502
1503int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, int valuelen)
1504{
1505	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);
1506	if (sdpdata)
1507		/* Verify that it is what the caller expects */
1508		if (sdpdata->dtd == SDP_TEXT_STR8 || sdpdata->dtd == SDP_TEXT_STR16 || sdpdata->dtd == SDP_TEXT_STR32)
1509			if (strlen(sdpdata->val.str) < valuelen) {
1510				strcpy(value, sdpdata->val.str);
1511				return 0;
1512			}
1513	errno = EINVAL;
1514	return -1;
1515}
1516
1517#define get_basic_attr(attrID, pAttrValue, fieldName)		\
1518	sdp_data_t *data = sdp_data_get(rec, attrID);		\
1519	if (data) {						\
1520		*pAttrValue = data->val.fieldName;		\
1521		return 0;					\
1522	}							\
1523	errno = EINVAL;						\
1524	return -1;
1525
1526int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid)
1527{
1528	get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid);
1529}
1530
1531int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid)
1532{
1533	get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid);
1534}
1535
1536int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState)
1537{
1538	get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32);
1539}
1540
1541int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail)
1542{
1543	get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8);
1544}
1545
1546int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo)
1547{
1548	get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32);
1549}
1550
1551int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState)
1552{
1553	get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32);
1554}
1555
1556/*
1557 * NOTE that none of the setXXX() functions below will
1558 * actually update the SDP server, unless the
1559 * {register, update}sdp_record_t() function is invoked.
1560 */
1561
1562int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *value)
1563{
1564	sdp_data_t *d = sdp_data_alloc(dtd, value);
1565	if (d) {
1566		sdp_attr_replace(rec, attr, d);
1567		return 0;
1568	}
1569	return -1;
1570}
1571
1572/*
1573 * Set the information attributes of the service
1574 * pointed to by rec. The attributes are
1575 * service name, description and provider name
1576 */
1577void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc)
1578{
1579	if (name)
1580		sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY, SDP_TEXT_STR8, (void *)name);
1581	if (prov)
1582		sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY, SDP_TEXT_STR8, (void *)prov);
1583	if (desc)
1584		sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY, SDP_TEXT_STR8, (void *)desc);
1585}
1586
1587static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto)
1588{
1589	sdp_data_t *seq = NULL;
1590	void *dtds[10], *values[10];
1591	void **seqDTDs, **seqs;
1592	int i, seqlen;
1593	sdp_list_t *p;
1594
1595	seqlen = sdp_list_len(proto);
1596	seqDTDs = (void **)malloc(seqlen * sizeof(void *));
1597	seqs = (void **)malloc(seqlen * sizeof(void *));
1598	for (i = 0, p = proto; p; p = p->next, i++) {
1599		sdp_list_t *elt = (sdp_list_t *)p->data;
1600		sdp_data_t *s;
1601		int pslen = 0;
1602		for (; elt && pslen < sizeof(dtds); elt = elt->next, pslen++) {
1603			sdp_data_t *d = (sdp_data_t *)elt->data;
1604			dtds[pslen] = &d->dtd;
1605			switch (d->dtd) {
1606			case SDP_UUID16:
1607				values[pslen] = &((uuid_t *)d)->value.uuid16;
1608				break;
1609			case SDP_UUID32:
1610				values[pslen] = &((uuid_t *)d)->value.uuid32;
1611				break;
1612			case SDP_UUID128:
1613				values[pslen] = &((uuid_t *)d)->value.uuid128;
1614				break;
1615			case SDP_UINT8:
1616				values[pslen] = &d->val.uint8;
1617				break;
1618			case SDP_UINT16:
1619				values[pslen] = &d->val.uint16;
1620				break;
1621			case SDP_SEQ8:
1622			case SDP_SEQ16:
1623			case SDP_SEQ32:
1624				values[pslen] = d;
1625				break;
1626			// FIXME: more
1627			}
1628		}
1629		s = sdp_seq_alloc(dtds, values, pslen);
1630		if (s) {
1631			seqDTDs[i] = &s->dtd;
1632			seqs[i] = s;
1633		}
1634	}
1635	seq = sdp_seq_alloc(seqDTDs, seqs, seqlen);
1636	free(seqDTDs);
1637	free(seqs);
1638	return seq;
1639}
1640
1641/*
1642 * sets the access protocols of the service specified
1643 * to the value specified in "access_proto"
1644 *
1645 * Note that if there are alternate mechanisms by
1646 * which the service is accessed, then they should
1647 * be specified as sequences
1648 *
1649 * Using a value of NULL for accessProtocols has
1650 * effect of removing this attribute (if previously set)
1651 *
1652 * This function replaces the existing sdp_access_proto_t
1653 * structure (if any) with the new one specified.
1654 *
1655 * returns 0 if successful or -1 if there is a failure.
1656 */
1657int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *ap)
1658{
1659	const sdp_list_t *p;
1660	sdp_data_t *protos = 0;
1661
1662	for (p = ap; p; p = p->next) {
1663		sdp_data_t *seq = access_proto_to_dataseq(rec, (sdp_list_t *)p->data);
1664		protos = sdp_seq_append(protos, seq);
1665	}
1666	sdp_attr_add(rec, SDP_ATTR_PROTO_DESC_LIST, protos);
1667	return 0;
1668}
1669
1670/*
1671 * set the "LanguageBase" attributes of the service record
1672 * record to the value specified in "langAttrList".
1673 *
1674 * "langAttrList" is a linked list of "sdp_lang_attr_t"
1675 * objects, one for each language in which user visible
1676 * attributes are present in the service record.
1677 *
1678 * Using a value of NULL for langAttrList has
1679 * effect of removing this attribute (if previously set)
1680 *
1681 * This function replaces the exisiting sdp_lang_attr_t
1682 * structure (if any) with the new one specified.
1683 *
1684 * returns 0 if successful or -1 if there is a failure.
1685 */
1686int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *seq)
1687{
1688	uint8_t uint16 = SDP_UINT16;
1689	int status = 0, i = 0, seqlen = sdp_list_len(seq);
1690	void **dtds = (void **)malloc(3 * seqlen * sizeof(void *));
1691	void **values = (void **)malloc(3 * seqlen * sizeof(void *));
1692	const sdp_list_t *p;
1693
1694	for (p = seq; p; p = p->next) {
1695		sdp_lang_attr_t *lang = (sdp_lang_attr_t *)p->data;
1696		if (!lang) {
1697			status = -1;
1698			break;
1699		}
1700		dtds[i] = &uint16;
1701		values[i] = &lang->code_ISO639;
1702		i++;
1703		dtds[i] = &uint16;
1704		values[i] = &lang->encoding;
1705		i++;
1706		dtds[i] = &uint16;
1707		values[i] = &lang->base_offset;
1708		i++;
1709	}
1710	if (status == 0) {
1711		sdp_data_t *seq = sdp_seq_alloc(dtds, values, 3 * seqlen);
1712		sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, seq);
1713	}
1714	free(dtds);
1715	free(values);
1716	return status;
1717}
1718
1719/*
1720 * set the "ServiceID" attribute of the service.
1721 *
1722 * This is the UUID of the service.
1723 *
1724 * returns 0 if successful or -1 if there is a failure.
1725 */
1726void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid)
1727{
1728	switch (uuid.type) {
1729	case SDP_UUID16:
1730		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID16, &uuid.value.uuid16);
1731		break;
1732	case SDP_UUID32:
1733		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID32, &uuid.value.uuid32);
1734		break;
1735	case SDP_UUID128:
1736		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID128, &uuid.value.uuid128);
1737		break;
1738	}
1739	sdp_pattern_add_uuid(rec, &uuid);
1740}
1741
1742/*
1743 * set the GroupID attribute of the service record defining a group.
1744 *
1745 * This is the UUID of the group.
1746 *
1747 * returns 0 if successful or -1 if there is a failure.
1748 */
1749void sdp_set_group_id(sdp_record_t *rec, uuid_t uuid)
1750{
1751	switch (uuid.type) {
1752	case SDP_UUID16:
1753		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID16, &uuid.value.uuid16);
1754		break;
1755	case SDP_UUID32:
1756		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID32, &uuid.value.uuid32);
1757		break;
1758	case SDP_UUID128:
1759		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID128, &uuid.value.uuid128);
1760		break;
1761	}
1762	sdp_pattern_add_uuid(rec, &uuid);
1763}
1764
1765/*
1766 * set the ProfileDescriptorList attribute of the service record
1767 * pointed to by record to the value specified in "profileDesc".
1768 *
1769 * Each element in the list is an object of type
1770 * sdp_profile_desc_t which is a definition of the
1771 * Bluetooth profile that this service conforms to.
1772 *
1773 * Using a value of NULL for profileDesc has
1774 * effect of removing this attribute (if previously set)
1775 *
1776 * This function replaces the exisiting ProfileDescriptorList
1777 * structure (if any) with the new one specified.
1778 *
1779 * returns 0 if successful or -1 if there is a failure.
1780 */
1781int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles)
1782{
1783	int status = 0;
1784	uint8_t uuid16 = SDP_UUID16;
1785	uint8_t uuid32 = SDP_UUID32;
1786	uint8_t uuid128 = SDP_UUID128;
1787	uint8_t uint16 = SDP_UINT16;
1788	int i = 0, seqlen = sdp_list_len(profiles);
1789	void **seqDTDs = (void **)malloc(seqlen * sizeof(void *));
1790	void **seqs = (void **)malloc(seqlen * sizeof(void *));
1791	const sdp_list_t *p;
1792
1793	for (p = profiles; p; p = p->next) {
1794		sdp_data_t *seq;
1795		void *dtds[2], *values[2];
1796		sdp_profile_desc_t *profile = (sdp_profile_desc_t *)p->data;
1797		if (!profile) {
1798			status = -1;
1799			break;
1800		}
1801		switch (profile->uuid.type) {
1802		case SDP_UUID16:
1803			dtds[0] = &uuid16;
1804			values[0] = &profile->uuid.value.uuid16;
1805			break;
1806		case SDP_UUID32:
1807			dtds[0] = &uuid32;
1808			values[0] = &profile->uuid.value.uuid32;
1809			break;
1810		case SDP_UUID128:
1811			dtds[0] = &uuid128;
1812			values[0] = &profile->uuid.value.uuid128;
1813			break;
1814		default:
1815			status = -1;
1816			break;
1817		}
1818		dtds[1] = &uint16;
1819		values[1] = &profile->version;
1820		seq = sdp_seq_alloc(dtds, values, 2);
1821		if (seq) {
1822			seqDTDs[i] = &seq->dtd;
1823			seqs[i] = seq;
1824			sdp_pattern_add_uuid(rec, &profile->uuid);
1825		}
1826		i++;
1827	}
1828	if (status == 0) {
1829		sdp_data_t *pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen);
1830		sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq);
1831	}
1832	free(seqDTDs);
1833	free(seqs);
1834	return status;
1835}
1836
1837/*
1838 * sets various URL attributes of the service
1839 * pointed to by record. The URL include
1840 *
1841 * client: a URL to the client's
1842 *   platform specific (WinCE, PalmOS) executable
1843 *   code that can be used to access this service.
1844 *
1845 * doc: a URL pointing to service documentation
1846 *
1847 * icon: a URL to an icon that can be used to represent
1848 *   this service.
1849 *
1850 * Note that you need to pass NULL for any URLs
1851 * that you don't want to set or remove
1852 */
1853void sdp_set_url_attr(sdp_record_t *rec, const char *client, const char *doc, const char *icon)
1854{
1855	sdp_attr_add_new(rec, SDP_ATTR_CLNT_EXEC_URL, SDP_URL_STR8, client);
1856	sdp_attr_add_new(rec, SDP_ATTR_DOC_URL, SDP_URL_STR8, doc);
1857	sdp_attr_add_new(rec, SDP_ATTR_ICON_URL, SDP_URL_STR8, icon);
1858}
1859
1860/*
1861 * The code in this function is executed only once per
1862 * thread. We compute the actual bit value of the Bluetooth
1863 * base UUID which is a string defined in bt_std_values.h
1864 * and is assumed to be of the standard form with "-" separators.
1865 *
1866 * The algorithm however converts the string to 4 unsigned longs
1867 * using the strtoul() and assigns the values in sequence to
1868 * the 128bit value
1869 */
1870uint128_t *sdp_create_base_uuid(void)
1871{
1872	char baseStr[128];
1873	int delim = '-';
1874	unsigned long dataLongValue;
1875	char *delimPtr;
1876	char *dataPtr;
1877	char temp[10];
1878	int toBeCopied;
1879	char *data;
1880
1881	if (bluetooth_base_uuid == NULL) {
1882		strcpy(baseStr, BASE_UUID);
1883		bluetooth_base_uuid = (uint128_t *)malloc(sizeof(uint128_t));
1884		data = bluetooth_base_uuid->data;
1885		memset(data, '\0', sizeof(uint128_t));
1886		memset(temp, '\0', 10);
1887		dataPtr = baseStr;
1888		delimPtr = NULL;
1889		delimPtr = strchr(dataPtr, delim);
1890		toBeCopied = delimPtr - dataPtr;
1891		if (toBeCopied != 8) {
1892			SDPDBG("To be copied(1) : %d\n", toBeCopied);
1893			return NULL;
1894		}
1895		strncpy(temp, dataPtr, toBeCopied);
1896		dataLongValue = htonl(strtoul(temp, NULL, 16));
1897		memcpy(&data[0], &dataLongValue, 4);
1898
1899		/*
1900		 * Get the next 4 bytes (note that there is a "-"
1901		 * between them now)
1902		 */
1903		memset(temp, '\0', 10);
1904		dataPtr = delimPtr + 1;
1905		delimPtr = strchr(dataPtr, delim);
1906		toBeCopied = delimPtr - dataPtr;
1907		if (toBeCopied != 4) {
1908			SDPDBG("To be copied(2) : %d\n", toBeCopied);
1909			return NULL;
1910		}
1911		strncpy(temp, dataPtr, toBeCopied);
1912		dataPtr = delimPtr + 1;
1913		delimPtr = strchr(dataPtr, delim);
1914		toBeCopied = delimPtr - dataPtr;
1915		if (toBeCopied != 4) {
1916			SDPDBG("To be copied(3) : %d\n", toBeCopied);
1917			return NULL;
1918		}
1919		strncat(temp, dataPtr, toBeCopied);
1920		dataLongValue = htonl(strtoul(temp, NULL, 16));
1921		memcpy(&data[4], &dataLongValue, 4);
1922
1923		/*
1924		 * Get the last 4 bytes (note that there are 6 bytes
1925		 * after the last separator, which is truncated (2+4)
1926		 */
1927		memset(temp, '\0', 10);
1928		dataPtr = delimPtr + 1;
1929		dataPtr = delimPtr + 1;
1930		delimPtr = strchr(dataPtr, delim);
1931		toBeCopied = delimPtr - dataPtr;
1932		if (toBeCopied != 4) {
1933			SDPDBG("To be copied(4) : %d\n", toBeCopied);
1934			return NULL;
1935		}
1936		strncpy(temp, dataPtr, toBeCopied);
1937		strncat(temp, (delimPtr + 1), 4);
1938		dataLongValue = htonl(strtoul(temp, NULL, 16));
1939		memcpy(&data[8], &dataLongValue, 4);
1940		dataLongValue = htonl(strtoul(delimPtr + 5, NULL, 16));
1941		memcpy(&data[12], &dataLongValue, 4);
1942	}
1943	return bluetooth_base_uuid;
1944}
1945
1946uuid_t *sdp_uuid16_create(uuid_t *u, uint16_t val)
1947{
1948	memset(u, 0, sizeof(uuid_t));
1949	u->type = SDP_UUID16;
1950	u->value.uuid16 = val;
1951	return u;
1952}
1953
1954uuid_t *sdp_uuid32_create(uuid_t *u, uint32_t val)
1955{
1956	memset(u, 0, sizeof(uuid_t));
1957	u->type = SDP_UUID32;
1958	u->value.uuid32 = val;
1959	return u;
1960}
1961
1962uuid_t *sdp_uuid128_create(uuid_t *u, const void *val)
1963{
1964	memset(u, 0, sizeof(uuid_t));
1965	u->type = SDP_UUID128;
1966	memcpy(&u->value.uuid128, val, sizeof(uint128_t));
1967	return u;
1968}
1969
1970/*
1971 * UUID comparison function
1972 * returns 0 if uuidValue1 == uuidValue2 else -1
1973 */
1974int sdp_uuid16_cmp(const void *p1, const void *p2)
1975{
1976	const uuid_t *u1 = (const uuid_t *)p1;
1977	const uuid_t *u2 = (const uuid_t *)p2;
1978	return memcmp(&u1->value.uuid16, &u2->value.uuid16, sizeof(uint16_t));
1979}
1980
1981/*
1982 * UUID comparison function
1983 * returns 0 if uuidValue1 == uuidValue2 else -1
1984 */
1985int sdp_uuid128_cmp(const void *p1, const void *p2)
1986{
1987	const uuid_t *u1 = (const uuid_t *)p1;
1988	const uuid_t *u2 = (const uuid_t *)p2;
1989	return memcmp(&u1->value.uuid128, &u2->value.uuid128, sizeof(uint128_t));
1990}
1991
1992/*
1993 * 128 to 16 bit and 32 to 16 bit UUID conversion functions
1994 * yet to be implemented. Note that the input is in NBO in
1995 * both 32 and 128 bit UUIDs and conversion is needed
1996 */
1997void sdp_uuid16_to_uuid128(uuid_t *uuid128, uuid_t *uuid16)
1998{
1999	/*
2000	 * We have a 16 bit value, which needs to be added to
2001	 * bytes 3 and 4 (at indices 2 and 3) of the Bluetooth base
2002	 */
2003	unsigned short data1;
2004
2005	// allocate a 128bit UUID and init to the Bluetooth base UUID
2006	uint128_t *pBTBase128Bit = sdp_create_base_uuid();
2007	uuid128->value.uuid128 = *pBTBase128Bit;
2008	uuid128->type = SDP_UUID128;
2009
2010	// extract bytes 2 and 3 of 128bit BT base UUID
2011	memcpy(&data1, &pBTBase128Bit->data[2], 2);
2012
2013	// add the given UUID (16 bits)
2014	data1 += htons(uuid16->value.uuid16);
2015
2016	// set bytes 2 and 3 of the 128 bit value
2017	memcpy(&uuid128->value.uuid128.data[2], &data1, 2);
2018}
2019
2020void sdp_uuid32_to_uuid128(uuid_t *uuid128, uuid_t *uuid32)
2021{
2022	/*
2023	 * We have a 32 bit value, which needs to be added to
2024	 * bytes 1->4 (at indices 0 thru 3) of the Bluetooth base
2025	 */
2026	unsigned int data0;
2027
2028	// allocate a 128bit UUID and init to the Bluetooth base UUID
2029	uint128_t *pBTBase128Bit = sdp_create_base_uuid();
2030	uuid128->value.uuid128 = *pBTBase128Bit;
2031	uuid128->type = SDP_UUID128;
2032
2033	// extract first 4 bytes
2034	memcpy(&data0, &pBTBase128Bit->data[0], 4);
2035
2036	// add the given UUID (32bits)
2037	data0 += htonl(uuid32->value.uuid32);
2038
2039	// set the 4 bytes of the 128 bit value
2040	memcpy(&uuid128->value.uuid128.data[0], &data0, 4);
2041}
2042
2043uuid_t *sdp_uuid_to_uuid128(uuid_t *uuid)
2044{
2045	uuid_t *uuid128 = (uuid_t *)malloc(sizeof(uuid_t));
2046	memset(uuid128, 0, sizeof(uuid_t));
2047	switch (uuid->type) {
2048	case SDP_UUID128:
2049		*uuid128 = *uuid;
2050		break;
2051	case SDP_UUID32:
2052		sdp_uuid32_to_uuid128(uuid128, uuid);
2053		break;
2054	case SDP_UUID16:
2055		sdp_uuid16_to_uuid128(uuid128, uuid);
2056		break;
2057	}
2058	return uuid128;
2059}
2060
2061/*
2062 * converts a 128-bit uuid to a 16/32-bit one if possible
2063 * returns true if uuid contains a 16/32-bit UUID at exit
2064 */
2065int sdp_uuid128_to_uuid(uuid_t *uuid)
2066{
2067	extern uint128_t *sdp_create_base_uuid();
2068	int i;
2069	uint128_t *b = sdp_create_base_uuid();
2070	uint128_t *u = &uuid->value.uuid128;
2071	uint32_t data;
2072
2073	if (uuid->type != SDP_UUID128)
2074		return 1;
2075
2076	for (i = 4; i < sizeof(b->data); i++)
2077		if (b->data[i] != u->data[i])
2078			return 0;
2079
2080	memcpy(&data, u->data, 4);
2081	data = htonl(data);
2082	if (data <= 0xffff) {
2083		uuid->type = SDP_UUID16;
2084		uuid->value.uuid16 = (uint16_t)data;
2085	} else {
2086		uuid->type = SDP_UUID32;
2087		uuid->value.uuid32 = data;
2088	}
2089	return 1;
2090}
2091
2092/*
2093 * convert a UUID to the 16-bit short-form
2094 */
2095int sdp_uuid_to_proto(uuid_t *uuid)
2096{
2097	uuid_t u = *uuid;
2098	if (sdp_uuid128_to_uuid(&u)) {
2099		switch (u.type) {
2100		case SDP_UUID16:
2101			return u.value.uuid16;
2102		case SDP_UUID32:
2103			return u.value.uuid32;
2104		}
2105	}
2106	return 0;
2107}
2108
2109int sdp_uuid_extract(const char *p, uuid_t *uuid, int *scanned)
2110{
2111	uint8_t type = *(const uint8_t *)p;
2112
2113	if (!SDP_IS_UUID(type)) {
2114		SDPERR("Unknown data type : %d expecting a svc UUID\n", type);
2115		return -1;
2116	}
2117	p += sizeof(uint8_t);
2118	*scanned += sizeof(uint8_t);
2119	if (type == SDP_UUID16) {
2120		sdp_uuid16_create(uuid, ntohs(sdp_get_unaligned((uint16_t *)p)));
2121		*scanned += sizeof(uint16_t);
2122		p += sizeof(uint16_t);
2123	} else if (type == SDP_UUID32) {
2124		sdp_uuid32_create(uuid, ntohl(sdp_get_unaligned((uint32_t *)p)));
2125		*scanned += sizeof(uint32_t);
2126		p += sizeof(uint32_t);
2127	} else {
2128		sdp_uuid128_create(uuid, p);
2129		*scanned += sizeof(uint128_t);
2130		p += sizeof(uint128_t);
2131	}
2132	return 0;
2133}
2134
2135/*
2136 * This function appends data to the PDU buffer "dst" from source "src".
2137 * The data length is also computed and set.
2138 * Should the PDU length exceed 2^8, then sequence type is
2139 * set accordingly and the data is memmove()'d.
2140 */
2141void sdp_append_to_buf(sdp_buf_t *dst, char *data, int len)
2142{
2143	char *p = dst->data;
2144	uint8_t dtd = *(uint8_t *)p;
2145
2146	SDPDBG("Append src size: %d\n", len);
2147	SDPDBG("Append dst size: %d\n", dst->data_size);
2148	SDPDBG("Dst buffer size: %d\n", dst->buf_size);
2149	if (dst->data_size + len > dst->buf_size) {
2150		int need = SDP_PDU_CHUNK_SIZE * ((len / SDP_PDU_CHUNK_SIZE) + 1);
2151		dst->data = (char *)realloc(dst->data, dst->buf_size + need);
2152
2153		SDPDBG("Realloc'ing : %d\n", need);
2154
2155		if (dst->data == NULL) {
2156			SDPERR("Realloc fails \n");
2157		}
2158		dst->buf_size += need;
2159	}
2160	if (dst->data_size == 0 && dtd == 0) {
2161		// create initial sequence
2162		*(uint8_t *)p = SDP_SEQ8;
2163		p += sizeof(uint8_t);
2164		dst->data_size += sizeof(uint8_t);
2165		// reserve space for sequence size
2166		p += sizeof(uint8_t);
2167		dst->data_size += sizeof(uint8_t);
2168	}
2169
2170	memcpy(dst->data + dst->data_size, data, len);
2171	dst->data_size += len;
2172
2173	dtd = *(uint8_t *)dst->data;
2174	if (dst->data_size > UCHAR_MAX && dtd == SDP_SEQ8) {
2175		short offset = sizeof(uint8_t) + sizeof(uint8_t);
2176		memmove(dst->data + offset + 1, dst->data + offset, dst->data_size - offset);
2177		p = dst->data;
2178		*(uint8_t *)p = SDP_SEQ16;
2179		p += sizeof(uint8_t);
2180		dst->data_size += 1;
2181	}
2182	p = dst->data;
2183	dtd = *(uint8_t *)p;
2184	p += sizeof(uint8_t);
2185	switch (dtd) {
2186	case SDP_SEQ8:
2187		*(uint8_t *)p = dst->data_size - sizeof(uint8_t) - sizeof(uint8_t);
2188		break;
2189	case SDP_SEQ16:
2190		sdp_put_unaligned(htons(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t)), (uint16_t *)p);
2191		break;
2192	case SDP_SEQ32:
2193		sdp_put_unaligned(htonl(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t)), (uint32_t *)p);
2194		break;
2195	}
2196}
2197
2198void sdp_append_to_pdu(sdp_buf_t *pdu, sdp_data_t *d)
2199{
2200	char buf[SDP_SEQ_PDUFORM_SIZE];
2201	sdp_buf_t append;
2202
2203	append.data = buf;
2204	append.buf_size = sizeof(buf);
2205	append.data_size = 0;
2206	sdp_set_attrid(&append, d->attrId);
2207	sdp_gen_pdu(&append, d);
2208	sdp_append_to_buf(pdu, append.data, append.data_size);
2209}
2210
2211/*
2212 * Registers an sdp record.
2213 *
2214 * It is incorrect to call this method on a record that
2215 * has been already registered with the server.
2216 *
2217 * Returns a non-null value (a pointer) to a service
2218 * record if successful, else -1 setting errno
2219 */
2220int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags)
2221{
2222	char *p;
2223	int status = 0;
2224	char *req, *rsp;
2225	int reqsize, rspsize;
2226	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2227	sdp_buf_t pdu;
2228
2229	SDPDBG("");
2230
2231	if (!session->local) {
2232		errno = EREMOTE;
2233		return -1;
2234	}
2235	req = (char *)malloc(SDP_REQ_BUFFER_SIZE);
2236	rsp = (char *)malloc(SDP_RSP_BUFFER_SIZE);
2237	if (req == NULL || rsp == NULL) {
2238		status = -1;
2239		errno = ENOMEM;
2240		goto end;
2241	}
2242	reqhdr = (sdp_pdu_hdr_t *)req;
2243	reqhdr->pdu_id = SDP_SVC_REGISTER_REQ;
2244	reqhdr->tid    = htons(sdp_gen_tid(session));
2245	reqsize = sizeof(sdp_pdu_hdr_t) + 1;
2246	p = req + sizeof(sdp_pdu_hdr_t);
2247	*p++ = flags;
2248	if (0 > sdp_gen_record_pdu(rec, &pdu)) {
2249		status = -1;
2250		errno = ENOMEM;
2251		goto end;
2252	}
2253	memcpy(p, pdu.data, pdu.data_size);
2254	free(pdu.data);
2255	reqsize += pdu.data_size;
2256	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2257
2258	status = sdp_send_req_w4_rsp(session, req, rsp, reqsize, &rspsize);
2259	if (status < 0)
2260		goto end;
2261	rsphdr = (sdp_pdu_hdr_t *)rsp;
2262	p = rsp + sizeof(sdp_pdu_hdr_t);
2263	if (rsphdr->pdu_id == SDP_SVC_REGISTER_RSP) {
2264		uint32_t handle  = ntohl(sdp_get_unaligned((uint32_t *)p));
2265		sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle);
2266		rec->handle = handle;
2267		sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data);
2268	}
2269end:
2270	if (req)
2271		free(req);
2272	if (rsp)
2273		free(rsp);
2274	return status;
2275}
2276
2277/*
2278 * unregister a service record
2279 */
2280int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec)
2281{
2282	char *p;
2283	int status = 0;
2284	char *reqbuf, *rspbuf;
2285	int reqsize = 0, rspsize = 0;
2286	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2287	uint32_t handle = 0;
2288
2289	SDPDBG("");
2290
2291	handle = rec->handle;
2292	if (handle == SDP_SERVER_RECORD_HANDLE) {
2293		errno = EINVAL;
2294		return -1;
2295	}
2296	if (!session->local) {
2297		errno = EREMOTE;
2298		return -1;
2299	}
2300	reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE);
2301	rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE);
2302	if (!reqbuf || !rspbuf) {
2303		errno = ENOMEM;
2304		status = -1;
2305		goto end;
2306	}
2307	reqhdr = (sdp_pdu_hdr_t *)reqbuf;
2308	reqhdr->pdu_id = SDP_SVC_REMOVE_REQ;
2309	reqhdr->tid    = htons(sdp_gen_tid(session));
2310
2311	p = reqbuf + sizeof(sdp_pdu_hdr_t);
2312	reqsize = sizeof(sdp_pdu_hdr_t);
2313	sdp_put_unaligned(htonl(handle), (uint32_t *)p);
2314	reqsize += sizeof(uint32_t);
2315
2316	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2317	status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
2318	if (status == 0) {
2319		rsphdr = (sdp_pdu_hdr_t *)rspbuf;
2320		p = rspbuf + sizeof(sdp_pdu_hdr_t);
2321		status = sdp_get_unaligned((uint16_t *)p);
2322		if (status == 0 && rsphdr->pdu_id == SDP_SVC_REMOVE_RSP) {
2323			SDPDBG("Removing local copy\n");
2324			sdp_record_free(rec);
2325		}
2326	}
2327end:
2328	if (reqbuf)
2329		free(reqbuf);
2330	if (rspbuf)
2331		free(rspbuf);
2332	return status;
2333}
2334
2335/*
2336 * modify an existing service record
2337 */
2338int sdp_record_update(sdp_session_t *session, const sdp_record_t *rec)
2339{
2340	char *p;
2341	int status = 0;
2342	char *reqbuf, *rspbuf;
2343	int reqsize, rspsize;
2344	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2345	uint32_t handle;
2346	sdp_buf_t pdu;
2347
2348	SDPDBG("");
2349	handle = rec->handle;
2350
2351	if (handle == SDP_SERVER_RECORD_HANDLE) {
2352		errno = EINVAL;
2353		return -1;
2354	}
2355	if (!session->local) {
2356		errno = EREMOTE;
2357		return -1;
2358	}
2359	reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE);
2360	rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE);
2361	if (!reqbuf || !rspbuf) {
2362		errno = ENOMEM;
2363		status = -1;
2364		goto end;
2365	}
2366	reqhdr = (sdp_pdu_hdr_t *)reqbuf;
2367	reqhdr->pdu_id = SDP_SVC_UPDATE_REQ;
2368	reqhdr->tid    = htons(sdp_gen_tid(session));
2369
2370	p = (char *)(reqbuf + sizeof(sdp_pdu_hdr_t));
2371	reqsize = sizeof(sdp_pdu_hdr_t);
2372
2373	sdp_put_unaligned(htonl(handle), (uint32_t *)p);
2374	reqsize += sizeof(uint32_t);
2375	p += sizeof(uint32_t);
2376
2377	if (0 > sdp_gen_record_pdu(rec, &pdu)) {
2378		errno = ENOMEM;
2379		status = -1;
2380		goto end;
2381	}
2382	memcpy(p, pdu.data, pdu.data_size);
2383	reqsize += pdu.data_size;
2384
2385	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2386	status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
2387
2388	SDPDBG("Send req status : %d\n", status);
2389
2390	if (status == 0) {
2391		rsphdr = (sdp_pdu_hdr_t *)rspbuf;
2392		p = rspbuf + sizeof(sdp_pdu_hdr_t);
2393		status = sdp_get_unaligned((uint16_t *)p);
2394	}
2395end:
2396	if (reqbuf)
2397		free(reqbuf);
2398	if (rspbuf)
2399		free(rspbuf);
2400	return status;
2401}
2402
2403sdp_record_t *sdp_record_alloc()
2404{
2405	sdp_record_t *rec = (sdp_record_t *)malloc(sizeof(sdp_record_t));
2406	memset((void *)rec, 0, sizeof(sdp_record_t));
2407	rec->handle = 0xffffffff;
2408	return rec;
2409}
2410
2411/*
2412 * Free the contents of a service record
2413 */
2414void sdp_record_free(sdp_record_t *rec)
2415{
2416	sdp_list_free(rec->attrlist, (sdp_free_func_t)sdp_data_free);
2417	sdp_list_free(rec->pattern, free);
2418	free(rec);
2419}
2420
2421void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid)
2422{
2423	uuid_t *uuid128 = sdp_uuid_to_uuid128(uuid);
2424
2425	SDPDBG("SvcRec : 0x%lx\n", (unsigned long)rec);
2426	SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern));
2427	SDPDBG("Trying to add : 0x%lx\n", (unsigned long)uuid128);
2428
2429	if (sdp_list_find(rec->pattern, uuid128, sdp_uuid128_cmp) == NULL)
2430		rec->pattern = sdp_list_insert_sorted(rec->pattern, uuid128, sdp_uuid128_cmp);
2431	else
2432		free(uuid128);
2433
2434	SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern));
2435}
2436
2437void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq)
2438{
2439	for (; seq; seq = seq->next) {
2440		uuid_t *uuid = (uuid_t *)seq->data;
2441		sdp_pattern_add_uuid(rec, uuid);
2442	}
2443}
2444
2445/*
2446 * Extract a sequence of service record handles from a PDU buffer
2447 * and add the entries to a sdp_list_t. Note that the service record
2448 * handles are not in "data element sequence" form, but just like
2449 * an array of service handles
2450 */
2451static void extract_record_handle_seq(char *pdu, sdp_list_t **seq, int count, int *scanned)
2452{
2453	sdp_list_t *pSeq = *seq;
2454	char *pdata = pdu;
2455	int n;
2456
2457	for (n = 0; n < count; n++) {
2458		uint32_t *pSvcRec = (uint32_t *) malloc(sizeof(uint32_t));
2459		*pSvcRec = ntohl(sdp_get_unaligned((uint32_t *)pdata));
2460		pSeq = sdp_list_append(pSeq, pSvcRec);
2461		pdata += sizeof(uint32_t);
2462		*scanned += sizeof(uint32_t);
2463	}
2464	*seq = pSeq;
2465}
2466/*
2467 * Generate the attribute sequence pdu form
2468 * from sdp_list_t elements. Return length of attr seq
2469 */
2470static int gen_dataseq_pdu(char *dst, const sdp_list_t *seq, uint8_t dtd)
2471{
2472	sdp_data_t *dataseq;
2473	void **types, **values;
2474	sdp_buf_t buf;
2475	int i, seqlen = sdp_list_len(seq);
2476
2477	// Fill up the value and the dtd arrays
2478	SDPDBG("");
2479
2480	memset(&buf, 0, sizeof(sdp_buf_t));
2481	buf.data = (char *)malloc(SDP_UUID_SEQ_SIZE);
2482	buf.buf_size = SDP_UUID_SEQ_SIZE;
2483
2484	SDPDBG("Seq length : %d\n", seqlen);
2485
2486	types = malloc(seqlen * sizeof(void *));
2487	values = malloc(seqlen * sizeof(void *));
2488	for (i = 0; i < seqlen; i++) {
2489		void *data = seq->data;
2490		types[i] = &dtd;
2491		if (SDP_IS_UUID(dtd))
2492			data = &((uuid_t *)data)->value;
2493		values[i] = data;
2494		seq = seq->next;
2495	}
2496
2497	dataseq = sdp_seq_alloc(types, values, seqlen);
2498	SDPDBG("Data Seq : 0x%p\n", seq);
2499	seqlen = sdp_gen_pdu(&buf, dataseq);
2500	SDPDBG("Copying : %d\n", buf.data_size);
2501	memcpy(dst, buf.data, buf.data_size);
2502
2503	sdp_data_free(dataseq);
2504
2505	free(types);
2506	free(values);
2507	free(buf.data);
2508	return seqlen;
2509}
2510
2511static int gen_searchseq_pdu(char *dst, const sdp_list_t *seq)
2512{
2513	uuid_t *uuid = (uuid_t *)seq->data;
2514	return gen_dataseq_pdu(dst, seq, uuid->type);
2515}
2516
2517static int gen_attridseq_pdu(char *dst, const sdp_list_t *seq, uint8_t dataType)
2518{
2519	return gen_dataseq_pdu(dst, seq, dataType);
2520}
2521
2522static int copy_cstate(char *pdata, const sdp_cstate_t *cstate)
2523{
2524	if (cstate) {
2525		*pdata++ = cstate->length;
2526		memcpy(pdata, cstate->data, cstate->length);
2527		return cstate->length + 1;
2528	}
2529	*pdata = 0;
2530	return 1;
2531}
2532
2533/*
2534 * This is a service search request.
2535 *
2536 * INPUT :
2537 *
2538 *   sdp_list_t *search_list
2539 *     Singly linked list containing elements of the search
2540 *     pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16)
2541 *     of the service to be searched
2542 *
2543 *   uint16_t max_rec_num
2544 *      A 16 bit integer which tells the service, the maximum
2545 *      entries that the client can handle in the response. The
2546 *      server is obliged not to return > max_rec_num entries
2547 *
2548 * OUTPUT :
2549 *
2550 *   int return value
2551 *     0:
2552 *       The request completed successfully. This does not
2553 *       mean the requested services were found
2554 *     -1:
2555 *       On any failure and sets errno
2556 *
2557 *   sdp_list_t **rsp_list
2558 *     This variable is set on a successful return if there are
2559 *     non-zero service handles. It is a singly linked list of
2560 *     service records (sdp_record_t *)
2561 *
2562 *   uint16_t *handleCount
2563 *     This is a pointer to a 16 bit integer, which is set to
2564 *     indicate the number of service record handles present in
2565 *     rec_list
2566 */
2567int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
2568			uint16_t max_rec_num, sdp_list_t **rsp)
2569{
2570	int status = 0;
2571	int reqsize = 0, _reqsize;
2572	int rspsize = 0, rsplen;
2573	int seqlen = 0;
2574	int scanned, total_rec_count, rec_count;
2575	char *pdata, *_pdata;
2576	char *reqbuf, *rspbuf;
2577	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2578	sdp_cstate_t *cstate = NULL;
2579
2580	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
2581	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
2582	if (!reqbuf || !rspbuf) {
2583		errno = ENOMEM;
2584		status = -1;
2585		goto end;
2586	}
2587	reqhdr = (sdp_pdu_hdr_t *)reqbuf;
2588	reqhdr->pdu_id = SDP_SVC_SEARCH_REQ;
2589	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
2590	reqsize = sizeof(sdp_pdu_hdr_t);
2591
2592	// add service class IDs for search
2593	seqlen = gen_searchseq_pdu(pdata, search);
2594
2595	SDPDBG("Data seq added : %d\n", seqlen);
2596
2597	// set the length and increment the pointer
2598	reqsize += seqlen;
2599	pdata += seqlen;
2600
2601	// specify the maximum svc rec count that client expects
2602	sdp_put_unaligned(htons(max_rec_num), (uint16_t *)pdata);
2603	reqsize += sizeof(uint16_t);
2604	pdata += sizeof(uint16_t);
2605
2606	_reqsize = reqsize;
2607	_pdata   = pdata;
2608	*rsp = NULL;
2609
2610	do {
2611		// Add continuation state or NULL (first time)
2612		reqsize = _reqsize + copy_cstate(_pdata, cstate);
2613
2614		// Set the request header's param length
2615		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2616
2617		reqhdr->tid  = htons(sdp_gen_tid(session));
2618		/*
2619		 * Send the request, wait for response and if
2620		 * no error, set the appropriate values and return
2621		 */
2622		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
2623		if (status < 0)
2624			goto end;
2625
2626		rsplen = 0;
2627		rsphdr = (sdp_pdu_hdr_t *)rspbuf;
2628		rsplen = ntohs(rsphdr->plen);
2629
2630		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
2631			SDPDBG("Status : 0x%x\n", rsphdr->pdu_id);
2632			status = -1;
2633			goto end;
2634		}
2635		scanned = 0;
2636		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
2637
2638		// net service record match count
2639		total_rec_count = ntohs(sdp_get_unaligned((uint16_t *)pdata));
2640		pdata += sizeof(uint16_t);
2641		scanned += sizeof(uint16_t);
2642		rec_count = ntohs(sdp_get_unaligned((uint16_t *)pdata));
2643		pdata += sizeof(uint16_t);
2644		scanned += sizeof(uint16_t);
2645
2646		SDPDBG("Total svc count: %d\n", total_rec_count);
2647		SDPDBG("Current svc count: %d\n", rec_count);
2648		SDPDBG("ResponseLength: %d\n", rsplen);
2649
2650		if (!rec_count) {
2651			status = -1;
2652			goto end;
2653		}
2654		extract_record_handle_seq(pdata, rsp, rec_count, &scanned);
2655		SDPDBG("BytesScanned : %d\n", scanned);
2656
2657		if (rsplen > scanned) {
2658			uint8_t cstate_len;
2659
2660			pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned;
2661			cstate_len = *(uint8_t *)pdata;
2662			if (cstate_len > 0) {
2663				cstate = (sdp_cstate_t *)pdata;
2664				SDPDBG("Cont state length: %d\n", cstate_len);
2665			} else
2666				cstate = NULL;
2667		}
2668	} while (cstate);
2669
2670  end:
2671	if (reqbuf)
2672		free(reqbuf);
2673	if (rspbuf)
2674		free(rspbuf);
2675
2676	return status;
2677}
2678
2679/*
2680 * This is a service attribute request.
2681 *
2682 * INPUT :
2683 *
2684 *   uint32_t handle
2685 *     The handle of the service for which the attribute(s) are
2686 *     requested
2687 *
2688 *   sdp_attrreq_type_t reqtype
2689 *     Attribute identifiers are 16 bit unsigned integers specified
2690 *     in one of 2 ways described below :
2691 *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
2692 *        They are the actual attribute identifiers in ascending order
2693 *
2694 *     SDP_ATTR_REQ_RANGE - 32bit identifier range
2695 *        The high-order 16bits is the start of range
2696 *        the low-order 16bits are the end of range
2697 *        0x0000 to 0xFFFF gets all attributes
2698 *
2699 *   sdp_list_t *attrid
2700 *     Singly linked list containing attribute identifiers desired.
2701 *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
2702 *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
2703 *
2704 * OUTPUT :
2705 *   return sdp_record_t *
2706 *     0:
2707 *       On any error and sets errno
2708 *     !0:
2709 *	 The service record
2710 */
2711sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
2712			sdp_attrreq_type_t reqtype, const sdp_list_t *attrids)
2713{
2714	int status = 0;
2715	int reqsize = 0, _reqsize;
2716	int rspsize = 0, rsp_count;
2717	int attr_list_len = 0;
2718	int seqlen = 0;
2719	char *pdata, *_pdata;
2720	char *reqbuf, *rspbuf;
2721	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2722	sdp_cstate_t *cstate = NULL;
2723	uint8_t cstate_len = 0;
2724	sdp_buf_t rsp_concat_buf;
2725	sdp_record_t *rec = 0;
2726
2727	if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) {
2728		errno = EINVAL;
2729		return 0;
2730	}
2731
2732	reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE);
2733	rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE);
2734	if (!reqbuf || !rspbuf) {
2735		errno = ENOMEM;
2736		status = -1;
2737		goto end;
2738	}
2739	memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t));
2740	reqhdr = (sdp_pdu_hdr_t *)reqbuf;
2741	reqhdr->pdu_id = SDP_SVC_ATTR_REQ;
2742
2743	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
2744	reqsize = sizeof(sdp_pdu_hdr_t);
2745
2746	// add the service record handle
2747	sdp_put_unaligned(htonl(handle), (uint32_t *)pdata);
2748	reqsize += sizeof(uint32_t);
2749	pdata += sizeof(uint32_t);
2750
2751	// specify the response limit
2752	sdp_put_unaligned(htons(65535), (uint16_t *)pdata);
2753	reqsize += sizeof(uint16_t);
2754	pdata += sizeof(uint16_t);
2755
2756	// get attr seq PDU form
2757	seqlen = gen_attridseq_pdu(pdata, attrids,
2758		reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32);
2759	if (seqlen == -1) {
2760		errno = EINVAL;
2761		status = -1;
2762		goto end;
2763	}
2764	pdata += seqlen;
2765	reqsize += seqlen;
2766	SDPDBG("Attr list length : %d\n", seqlen);
2767
2768	// save before Continuation State
2769	_pdata = pdata;
2770	_reqsize = reqsize;
2771
2772	do {
2773		// add NULL continuation state
2774		reqsize = _reqsize + copy_cstate(_pdata, cstate);
2775
2776		// set the request header's param length
2777		reqhdr->tid  = htons(sdp_gen_tid(session));
2778		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2779
2780		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
2781		if (status < 0)
2782			goto end;
2783		rsp_count = 0;
2784		rsphdr = (sdp_pdu_hdr_t *)rspbuf;
2785		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
2786			SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id);
2787			status = -1;
2788			goto end;
2789		}
2790		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
2791		rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata));
2792		attr_list_len += rsp_count;
2793		pdata += sizeof(uint16_t);
2794
2795		// if continuation state set need to re-issue request before parsing
2796		cstate_len = *(uint8_t *)(pdata + rsp_count);
2797
2798		SDPDBG("Response id : %d\n", rsphdr->pdu_id);
2799		SDPDBG("Attrlist byte count : %d\n", rsp_count);
2800		SDPDBG("sdp_cstate_t length : %d\n", cstate_len);
2801
2802		/*
2803		 * a split response: concatenate intermediate responses
2804		 * and the last one (which has cstate_len == 0)
2805		 */
2806		if (cstate_len > 0 || rsp_concat_buf.data_size != 0) {
2807			char *targetPtr = NULL;
2808
2809			cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0;
2810
2811			// build concatenated response buffer
2812			rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count);
2813			rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count;
2814			targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size;
2815			memcpy(targetPtr, pdata, rsp_count);
2816			rsp_concat_buf.data_size += rsp_count;
2817		}
2818	} while (cstate);
2819
2820	if (attr_list_len > 0) {
2821		int scanned = 0;
2822		if (rsp_concat_buf.data_size != 0)
2823			pdata = rsp_concat_buf.data;
2824		rec = sdp_extract_pdu(pdata, &scanned);
2825
2826		if (!rec)
2827			status = -1;
2828	}
2829
2830  end:
2831	if (reqbuf)
2832		free(reqbuf);
2833	if (rsp_concat_buf.data)
2834		free(rsp_concat_buf.data);
2835	if (rspbuf)
2836		free(rspbuf);
2837	return rec;
2838}
2839
2840/*
2841 * This is a service search request combined with the service
2842 * attribute request. First a service class match is done and
2843 * for matching service, requested attributes are extracted
2844 *
2845 * INPUT :
2846 *
2847 *   sdp_list_t *search
2848 *     Singly linked list containing elements of the search
2849 *     pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16)
2850 *     of the service to be searched
2851 *
2852 *   AttributeSpecification attrSpec
2853 *     Attribute identifiers are 16 bit unsigned integers specified
2854 *     in one of 2 ways described below :
2855 *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
2856 *        They are the actual attribute identifiers in ascending order
2857 *
2858 *     SDP_ATTR_REQ_RANGE - 32bit identifier range
2859 *        The high-order 16bits is the start of range
2860 *        the low-order 16bits are the end of range
2861 *        0x0000 to 0xFFFF gets all attributes
2862 *
2863 *   sdp_list_t *attrids
2864 *     Singly linked list containing attribute identifiers desired.
2865 *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
2866 *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
2867 *
2868 * OUTPUT :
2869 *   int return value
2870 *     0:
2871 *       The request completed successfully. This does not
2872 *       mean the requested services were found
2873 *     -1:
2874 *       On any error and sets errno
2875 *
2876 *   sdp_list_t **rsp
2877 *     This variable is set on a successful return to point to
2878 *     service(s) found. Each element of this list is of type
2879 *     sdp_record_t* (of the services which matched the search list)
2880 */
2881int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrids, sdp_list_t **rsp)
2882{
2883	int status = 0;
2884	int reqsize = 0, _reqsize;
2885	int rspsize = 0;
2886	int seqlen = 0, attr_list_len = 0;
2887	int rsp_count = 0, cstate_len = 0;
2888	char *pdata, *_pdata;
2889	char *reqbuf, *rspbuf;
2890	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2891	uint8_t dataType;
2892	sdp_list_t *rec_list = NULL;
2893	sdp_buf_t rsp_concat_buf;
2894	sdp_cstate_t *cstate = NULL;
2895
2896	if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) {
2897		errno = EINVAL;
2898		return -1;
2899	}
2900	reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE);
2901	rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE);
2902	if (!reqbuf || !rspbuf) {
2903		errno = ENOMEM;
2904		status = -1;
2905		goto end;
2906	}
2907
2908	memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t));
2909	reqhdr = (sdp_pdu_hdr_t *)reqbuf;
2910	reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ;
2911
2912	// generate PDU
2913	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
2914	reqsize = sizeof(sdp_pdu_hdr_t);
2915
2916	// add service class IDs for search
2917	seqlen = gen_searchseq_pdu(pdata, search);
2918
2919	SDPDBG("Data seq added : %d\n", seqlen);
2920
2921	// now set the length and increment the pointer
2922	reqsize += seqlen;
2923	pdata += seqlen;
2924
2925	sdp_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *)pdata);
2926	reqsize += sizeof(uint16_t);
2927	pdata += sizeof(uint16_t);
2928
2929	SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN);
2930
2931	// get attr seq PDU form
2932	seqlen = gen_attridseq_pdu(pdata, attrids,
2933		reqtype == SDP_ATTR_REQ_INDIVIDUAL?  SDP_UINT16: SDP_UINT32);
2934	if (seqlen == -1) {
2935		status = EINVAL;
2936		goto end;
2937	}
2938	pdata += seqlen;
2939	SDPDBG("Attr list length : %d\n", seqlen);
2940	reqsize += seqlen;
2941	*rsp = 0;
2942
2943	// save before Continuation State
2944	_pdata = pdata;
2945	_reqsize = reqsize;
2946
2947	do {
2948		reqhdr->tid = htons(sdp_gen_tid(session));
2949
2950		// add continuation state (can be null)
2951		reqsize = _reqsize + copy_cstate(_pdata, cstate);
2952
2953		// set the request header's param length
2954		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2955		rsphdr = (sdp_pdu_hdr_t *)rspbuf;
2956		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
2957		if (status < 0) {
2958			SDPDBG("Status : 0x%x\n", rsphdr->pdu_id);
2959			goto end;
2960		}
2961
2962		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
2963			status = -1;
2964			goto end;
2965		}
2966
2967		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
2968		rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata));
2969		attr_list_len += rsp_count;
2970		pdata += sizeof(uint16_t);	// pdata points to attribute list
2971		cstate_len = *(uint8_t *)(pdata + rsp_count);
2972
2973		SDPDBG("Attrlist byte count : %d\n", attr_list_len);
2974		SDPDBG("Response byte count : %d\n", rsp_count);
2975		SDPDBG("Cstate length : %d\n", cstate_len);
2976		/*
2977		 * This is a split response, need to concatenate intermediate
2978		 * responses and the last one which will have cstate_len == 0
2979		 */
2980		if (cstate_len > 0 || rsp_concat_buf.data_size != 0) {
2981			char *targetPtr = NULL;
2982
2983			cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0;
2984
2985			// build concatenated response buffer
2986			rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count);
2987			targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size;
2988			rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count;
2989			memcpy(targetPtr, pdata, rsp_count);
2990			rsp_concat_buf.data_size += rsp_count;
2991		}
2992	} while (cstate);
2993
2994	if (attr_list_len > 0) {
2995		int scanned = 0;
2996
2997		if (rsp_concat_buf.data_size != 0)
2998			pdata = rsp_concat_buf.data;
2999
3000		/*
3001		 * Response is a sequence of sequence(s) for one or
3002		 * more data element sequence(s) representing services
3003		 * for which attributes are returned
3004		 */
3005		scanned = sdp_extract_seqtype(pdata, &dataType, &seqlen);
3006
3007		SDPDBG("Bytes scanned : %d\n", scanned);
3008		SDPDBG("Seq length : %d\n", seqlen);
3009
3010		if (scanned && seqlen) {
3011			pdata += scanned;
3012			do {
3013				int recsize = 0;
3014				sdp_record_t *rec = sdp_extract_pdu(pdata, &recsize);
3015				if (rec == NULL) {
3016					SDPERR("SVC REC is null\n");
3017					status = -1;
3018					goto end;
3019				}
3020				scanned += recsize;
3021				pdata += recsize;
3022
3023				SDPDBG("Loc seq length : %d\n", recsize);
3024				SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle);
3025				SDPDBG("Bytes scanned : %d\n", scanned);
3026				SDPDBG("Attrlist byte count : %d\n", attr_list_len);
3027				rec_list = sdp_list_append(rec_list, rec);
3028			} while (scanned < attr_list_len);
3029
3030			SDPDBG("Successful scan of service attr lists\n");
3031			*rsp = rec_list;
3032		}
3033	}
3034  end:
3035	if (rsp_concat_buf.data)
3036		free(rsp_concat_buf.data);
3037	if (reqbuf)
3038		free(reqbuf);
3039	if (rspbuf)
3040		free(rspbuf);
3041	return status;
3042}
3043
3044/*
3045 * Find devices in the piconet.
3046 */
3047int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *found)
3048{
3049	int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0);
3050	if (n < 0) {
3051		SDPERR("Inquiry failed:%s", strerror(errno));
3052		return -1;
3053	}
3054	*found = n;
3055	return 0;
3056}
3057
3058int sdp_close(sdp_session_t *session)
3059{
3060	int ret = close(session->sock);
3061	free(session);
3062	return ret;
3063}
3064
3065static inline int sdp_is_local(const bdaddr_t *device)
3066{
3067	return memcmp(device, BDADDR_LOCAL, sizeof(bdaddr_t)) == 0;
3068}
3069
3070sdp_session_t *sdp_connect(const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags)
3071{
3072	sdp_session_t *session = malloc(sizeof(sdp_session_t));
3073	if (!session)
3074		return session;
3075	memset(session, 0, sizeof(*session));
3076	session->flags = flags;
3077	if (sdp_is_local(dst)) {
3078		struct sockaddr_un sa;
3079
3080		// create local unix connection
3081		session->sock = socket(PF_UNIX, SOCK_STREAM, 0);
3082		session->local = 1;
3083		if (session->sock >= 0) {
3084			sa.sun_family = AF_UNIX;
3085			strcpy(sa.sun_path, SDP_UNIX_PATH);
3086			if (connect(session->sock, (struct sockaddr *)&sa, sizeof(sa)) == 0)
3087				return session;
3088		}
3089	} else {
3090		struct sockaddr_l2 sa;
3091
3092		// create L2CAP connection
3093		session->sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
3094		session->local = 0;
3095		if (session->sock >= 0) {
3096			sa.l2_family = AF_BLUETOOTH;
3097			sa.l2_psm = 0;
3098			if (bacmp(src, BDADDR_ANY) != 0) {
3099				sa.l2_bdaddr = *src;
3100				if (0 > bind(session->sock, (struct sockaddr *)&sa, sizeof(sa)))
3101					goto fail;
3102			}
3103			sa.l2_psm = htobs(SDP_PSM);
3104			sa.l2_bdaddr = *dst;
3105			do
3106				if (connect(session->sock, (struct sockaddr *)&sa, sizeof(sa)) == 0)
3107					return session;
3108			while (errno == EBUSY && (flags & SDP_RETRY_IF_BUSY));
3109		}
3110	}
3111fail:
3112	if (session->sock >= 0)
3113		close(session->sock);
3114	free(session);
3115	return 0;
3116}
3117