• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2001-2002  Nokia Corporation
6  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
7  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
8  *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com>
9  *
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <limits.h>
37 #include <string.h>
38 #include <syslog.h>
39 #include <sys/time.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/un.h>
43 #include <netinet/in.h>
44 
45 #include "bluetooth.h"
46 #include "hci.h"
47 #include "hci_lib.h"
48 #include "l2cap.h"
49 #include "sdp.h"
50 #include "sdp_lib.h"
51 
52 #define SDPINF(fmt, arg...) syslog(LOG_INFO, fmt "\n", ## arg)
53 #define SDPERR(fmt, arg...) syslog(LOG_ERR, "%s: " fmt "\n", __func__ , ## arg)
54 
55 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
56 
57 #ifdef SDP_DEBUG
58 #define SDPDBG(fmt, arg...) syslog(LOG_DEBUG, "%s: " fmt "\n", __func__ , ## arg)
59 #else
60 #define SDPDBG(fmt...)
61 #endif
62 
63 #if __BYTE_ORDER == __BIG_ENDIAN
64 #define ntoh64(x) (x)
ntoh128(uint128_t * src,uint128_t * dst)65 static inline void ntoh128(uint128_t *src, uint128_t *dst)
66 {
67 	int i;
68 	for (i = 0; i < 16; i++)
69 		dst->data[i] = src->data[i];
70 }
71 #else
ntoh64(uint64_t n)72 static inline uint64_t ntoh64(uint64_t n)
73 {
74 	uint64_t h;
75 	uint64_t tmp = ntohl(n & 0x00000000ffffffff);
76 	h = ntohl(n >> 32);
77 	h |= tmp << 32;
78 	return h;
79 }
ntoh128(uint128_t * src,uint128_t * dst)80 static inline void ntoh128(uint128_t *src, uint128_t *dst)
81 {
82 	int i;
83 	for (i = 0; i < 16; i++)
84 		dst->data[15 - i] = src->data[i];
85 }
86 #endif
87 
88 #define hton64(x)     ntoh64(x)
89 #define hton128(x, y) ntoh128(x, y)
90 
91 #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB"
92 
93 static uint128_t bluetooth_base_uuid = {
94 	.data = {	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
95 			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
96 };
97 
98 #define SDP_MAX_ATTR_LEN 65535
99 
100 static sdp_data_t *sdp_copy_seq(sdp_data_t *data);
101 static int sdp_attr_add_new_with_length(sdp_record_t *rec,
102 	uint16_t attr, uint8_t dtd, const void *value, uint32_t len);
103 static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d);
104 
105 /* Message structure. */
106 struct tupla {
107 	int index;
108 	char *str;
109 };
110 
111 static struct tupla Protocol[] = {
112 	{ SDP_UUID,		"SDP"		},
113 	{ UDP_UUID,		"UDP"		},
114 	{ RFCOMM_UUID,		"RFCOMM"	},
115 	{ TCP_UUID,		"TCP"		},
116 	{ TCS_BIN_UUID,		"TCS-BIN"	},
117 	{ TCS_AT_UUID,		"TCS-AT"	},
118 	{ OBEX_UUID,		"OBEX"		},
119 	{ IP_UUID,		"IP"		},
120 	{ FTP_UUID,		"FTP"		},
121 	{ HTTP_UUID,		"HTTP"		},
122 	{ WSP_UUID,		"WSP"		},
123 	{ BNEP_UUID,		"BNEP"		},
124 	{ UPNP_UUID,		"UPNP"		},
125 	{ HIDP_UUID,		"HIDP"		},
126 	{ HCRP_CTRL_UUID,	"HCRP-Ctrl"	},
127 	{ HCRP_DATA_UUID,	"HCRP-Data"	},
128 	{ HCRP_NOTE_UUID,	"HCRP-Notify"	},
129 	{ AVCTP_UUID,		"AVCTP"		},
130 	{ AVDTP_UUID,		"AVDTP"		},
131 	{ CMTP_UUID,		"CMTP"		},
132 	{ UDI_UUID,		"UDI"		},
133 	{ MCAP_CTRL_UUID,	"MCAP-Ctrl"	},
134 	{ MCAP_DATA_UUID,	"MCAP-Data"	},
135 	{ L2CAP_UUID,		"L2CAP"		},
136 	{ 0 }
137 };
138 
139 static struct tupla ServiceClass[] = {
140 	{ SDP_SERVER_SVCLASS_ID,		"SDP Server"			},
141 	{ BROWSE_GRP_DESC_SVCLASS_ID,		"Browse Group Descriptor"	},
142 	{ PUBLIC_BROWSE_GROUP,			"Public Browse Group"		},
143 	{ SERIAL_PORT_SVCLASS_ID,		"Serial Port"			},
144 	{ LAN_ACCESS_SVCLASS_ID,		"LAN Access Using PPP"		},
145 	{ DIALUP_NET_SVCLASS_ID,		"Dialup Networking"		},
146 	{ IRMC_SYNC_SVCLASS_ID,			"IrMC Sync"			},
147 	{ OBEX_OBJPUSH_SVCLASS_ID,		"OBEX Object Push"		},
148 	{ OBEX_FILETRANS_SVCLASS_ID,		"OBEX File Transfer"		},
149 	{ IRMC_SYNC_CMD_SVCLASS_ID,		"IrMC Sync Command"		},
150 	{ HEADSET_SVCLASS_ID,			"Headset"			},
151 	{ CORDLESS_TELEPHONY_SVCLASS_ID,	"Cordless Telephony"		},
152 	{ AUDIO_SOURCE_SVCLASS_ID,		"Audio Source"			},
153 	{ AUDIO_SINK_SVCLASS_ID,		"Audio Sink"			},
154 	{ AV_REMOTE_TARGET_SVCLASS_ID,		"AV Remote Target"		},
155 	{ ADVANCED_AUDIO_SVCLASS_ID,		"Advanced Audio"		},
156 	{ AV_REMOTE_SVCLASS_ID,			"AV Remote"			},
157 	{ VIDEO_CONF_SVCLASS_ID,		"Video Conferencing"		},
158 	{ INTERCOM_SVCLASS_ID,			"Intercom"			},
159 	{ FAX_SVCLASS_ID,			"Fax"				},
160 	{ HEADSET_AGW_SVCLASS_ID,		"Headset Audio Gateway"		},
161 	{ WAP_SVCLASS_ID,			"WAP"				},
162 	{ WAP_CLIENT_SVCLASS_ID,		"WAP Client"			},
163 	{ PANU_SVCLASS_ID,			"PAN User"			},
164 	{ NAP_SVCLASS_ID,			"Network Access Point"		},
165 	{ GN_SVCLASS_ID,			"PAN Group Network"		},
166 	{ DIRECT_PRINTING_SVCLASS_ID,		"Direct Printing"		},
167 	{ REFERENCE_PRINTING_SVCLASS_ID,	"Reference Printing"		},
168 	{ IMAGING_SVCLASS_ID,			"Imaging"			},
169 	{ IMAGING_RESPONDER_SVCLASS_ID,		"Imaging Responder"		},
170 	{ IMAGING_ARCHIVE_SVCLASS_ID,		"Imaging Automatic Archive"	},
171 	{ IMAGING_REFOBJS_SVCLASS_ID,		"Imaging Referenced Objects"	},
172 	{ HANDSFREE_SVCLASS_ID,			"Handsfree"			},
173 	{ HANDSFREE_AGW_SVCLASS_ID,		"Handsfree Audio Gateway"	},
174 	{ DIRECT_PRT_REFOBJS_SVCLASS_ID,	"Direct Printing Ref. Objects"	},
175 	{ REFLECTED_UI_SVCLASS_ID,		"Reflected UI"			},
176 	{ BASIC_PRINTING_SVCLASS_ID,		"Basic Printing"		},
177 	{ PRINTING_STATUS_SVCLASS_ID,		"Printing Status"		},
178 	{ HID_SVCLASS_ID,			"Human Interface Device"	},
179 	{ HCR_SVCLASS_ID,			"Hardcopy Cable Replacement"	},
180 	{ HCR_PRINT_SVCLASS_ID,			"HCR Print"			},
181 	{ HCR_SCAN_SVCLASS_ID,			"HCR Scan"			},
182 	{ CIP_SVCLASS_ID,			"Common ISDN Access"		},
183 	{ VIDEO_CONF_GW_SVCLASS_ID,		"Video Conferencing Gateway"	},
184 	{ UDI_MT_SVCLASS_ID,			"UDI MT"			},
185 	{ UDI_TA_SVCLASS_ID,			"UDI TA"			},
186 	{ AV_SVCLASS_ID,			"Audio/Video"			},
187 	{ SAP_SVCLASS_ID,			"SIM Access"			},
188 	{ PBAP_PCE_SVCLASS_ID,			"Phonebook Access - PCE"	},
189 	{ PBAP_PSE_SVCLASS_ID,			"Phonebook Access - PSE"	},
190 	{ PBAP_SVCLASS_ID,			"Phonebook Access"		},
191 	{ PNP_INFO_SVCLASS_ID,			"PnP Information"		},
192 	{ GENERIC_NETWORKING_SVCLASS_ID,	"Generic Networking"		},
193 	{ GENERIC_FILETRANS_SVCLASS_ID,		"Generic File Transfer"		},
194 	{ GENERIC_AUDIO_SVCLASS_ID,		"Generic Audio"			},
195 	{ GENERIC_TELEPHONY_SVCLASS_ID,		"Generic Telephony"		},
196 	{ UPNP_SVCLASS_ID,			"UPnP"				},
197 	{ UPNP_IP_SVCLASS_ID,			"UPnP IP"			},
198 	{ UPNP_PAN_SVCLASS_ID,			"UPnP PAN"			},
199 	{ UPNP_LAP_SVCLASS_ID,			"UPnP LAP"			},
200 	{ UPNP_L2CAP_SVCLASS_ID,		"UPnP L2CAP"			},
201 	{ VIDEO_SOURCE_SVCLASS_ID,		"Video Source"			},
202 	{ VIDEO_SINK_SVCLASS_ID,		"Video Sink"			},
203 	{ VIDEO_DISTRIBUTION_SVCLASS_ID,	"Video Distribution"		},
204 	{ HDP_SVCLASS_ID,			"HDP"				},
205 	{ HDP_SOURCE_SVCLASS_ID,		"HDP Source"			},
206 	{ HDP_SINK_SVCLASS_ID,			"HDP Sink"			},
207 	{ APPLE_AGENT_SVCLASS_ID,		"Apple Agent"			},
208 	{ 0 }
209 };
210 
211 #define Profile ServiceClass
212 
string_lookup(struct tupla * pt0,int index)213 static char *string_lookup(struct tupla *pt0, int index)
214 {
215 	struct tupla *pt;
216 
217 	for (pt = pt0; pt->index; pt++)
218 		if (pt->index == index)
219 			return pt->str;
220 
221 	return "";
222 }
223 
string_lookup_uuid(struct tupla * pt0,const uuid_t * uuid)224 static char *string_lookup_uuid(struct tupla *pt0, const uuid_t* uuid)
225 {
226 	uuid_t tmp_uuid;
227 
228 	memcpy(&tmp_uuid, uuid, sizeof(tmp_uuid));
229 
230 	if (sdp_uuid128_to_uuid(&tmp_uuid)) {
231 		switch (tmp_uuid.type) {
232 		case SDP_UUID16:
233 			return string_lookup(pt0, tmp_uuid.value.uuid16);
234 		case SDP_UUID32:
235 			return string_lookup(pt0, tmp_uuid.value.uuid32);
236 		}
237 	}
238 
239 	return "";
240 }
241 
242 /*
243  * Prints into a string the Protocol UUID
244  * coping a maximum of n characters.
245  */
uuid2str(struct tupla * message,const uuid_t * uuid,char * str,size_t n)246 static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n)
247 {
248 	char *str2;
249 
250 	if (!uuid) {
251 		snprintf(str, n, "NULL");
252 		return -2;
253 	}
254 
255 	switch (uuid->type) {
256 	case SDP_UUID16:
257 		str2 = string_lookup(message, uuid->value.uuid16);
258 		snprintf(str, n, "%s", str2);
259 		break;
260 	case SDP_UUID32:
261 		str2 = string_lookup(message, uuid->value.uuid32);
262 		snprintf(str, n, "%s", str2);
263 		break;
264 	case SDP_UUID128:
265 		str2 = string_lookup_uuid(message, uuid);
266 		snprintf(str, n, "%s", str2);
267 		break;
268 	default:
269 		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);
270 		return -1;
271 	}
272 
273 	return 0;
274 }
275 
sdp_proto_uuid2strn(const uuid_t * uuid,char * str,size_t n)276 int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n)
277 {
278 	return uuid2str(Protocol, uuid, str, n);
279 }
280 
sdp_svclass_uuid2strn(const uuid_t * uuid,char * str,size_t n)281 int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n)
282 {
283 	return uuid2str(ServiceClass, uuid, str, n);
284 }
285 
sdp_profile_uuid2strn(const uuid_t * uuid,char * str,size_t n)286 int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n)
287 {
288 	return uuid2str(Profile, uuid, str, n);
289 }
290 
291 /*
292  * convert the UUID to string, copying a maximum of n characters.
293  */
sdp_uuid2strn(const uuid_t * uuid,char * str,size_t n)294 int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n)
295 {
296 	if (!uuid) {
297 		snprintf(str, n, "NULL");
298 		return -2;
299 	}
300 	switch (uuid->type) {
301 	case SDP_UUID16:
302 		snprintf(str, n, "%.4x", uuid->value.uuid16);
303 		break;
304 	case SDP_UUID32:
305 		snprintf(str, n, "%.8x", uuid->value.uuid32);
306 		break;
307 	case SDP_UUID128:{
308 		unsigned int   data0;
309 		unsigned short data1;
310 		unsigned short data2;
311 		unsigned short data3;
312 		unsigned int   data4;
313 		unsigned short data5;
314 
315 		memcpy(&data0, &uuid->value.uuid128.data[0], 4);
316 		memcpy(&data1, &uuid->value.uuid128.data[4], 2);
317 		memcpy(&data2, &uuid->value.uuid128.data[6], 2);
318 		memcpy(&data3, &uuid->value.uuid128.data[8], 2);
319 		memcpy(&data4, &uuid->value.uuid128.data[10], 4);
320 		memcpy(&data5, &uuid->value.uuid128.data[14], 2);
321 
322 		snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
323 				ntohl(data0), ntohs(data1),
324 				ntohs(data2), ntohs(data3),
325 				ntohl(data4), ntohs(data5));
326 		}
327 		break;
328 	default:
329 		snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type);
330 		return -1;	/* Enum type of UUID not set */
331 	}
332 	return 0;
333 }
334 
335 #ifdef SDP_DEBUG
336 /*
337  * Function prints the UUID in hex as per defined syntax -
338  *
339  * 4bytes-2bytes-2bytes-2bytes-6bytes
340  *
341  * There is some ugly code, including hardcoding, but
342  * that is just the way it is converting 16 and 32 bit
343  * UUIDs to 128 bit as defined in the SDP doc
344  */
sdp_uuid_print(const uuid_t * uuid)345 void sdp_uuid_print(const uuid_t *uuid)
346 {
347 	if (uuid == NULL) {
348 		SDPERR("Null passed to print UUID\n");
349 		return;
350 	}
351 	if (uuid->type == SDP_UUID16) {
352 		SDPDBG("  uint16_t : 0x%.4x\n", uuid->value.uuid16);
353 	} else if (uuid->type == SDP_UUID32) {
354 		SDPDBG("  uint32_t : 0x%.8x\n", uuid->value.uuid32);
355 	} else if (uuid->type == SDP_UUID128) {
356 		unsigned int data0;
357 		unsigned short data1;
358 		unsigned short data2;
359 		unsigned short data3;
360 		unsigned int data4;
361 		unsigned short data5;
362 
363 		memcpy(&data0, &uuid->value.uuid128.data[0], 4);
364 		memcpy(&data1, &uuid->value.uuid128.data[4], 2);
365 		memcpy(&data2, &uuid->value.uuid128.data[6], 2);
366 		memcpy(&data3, &uuid->value.uuid128.data[8], 2);
367 		memcpy(&data4, &uuid->value.uuid128.data[10], 4);
368 		memcpy(&data5, &uuid->value.uuid128.data[14], 2);
369 
370 		SDPDBG("  uint128_t : 0x%.8x-", ntohl(data0));
371 		SDPDBG("%.4x-", ntohs(data1));
372 		SDPDBG("%.4x-", ntohs(data2));
373 		SDPDBG("%.4x-", ntohs(data3));
374 		SDPDBG("%.8x", ntohl(data4));
375 		SDPDBG("%.4x\n", ntohs(data5));
376 	} else
377 		SDPERR("Enum type of UUID not set\n");
378 }
379 #endif
380 
sdp_data_alloc_with_length(uint8_t dtd,const void * value,uint32_t length)381 sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value,
382 							uint32_t length)
383 {
384 	sdp_data_t *seq;
385 	sdp_data_t *d = malloc(sizeof(sdp_data_t));
386 
387 	if (!d)
388 		return NULL;
389 
390 	memset(d, 0, sizeof(sdp_data_t));
391 	d->dtd = dtd;
392 	d->unitSize = sizeof(uint8_t);
393 
394 	switch (dtd) {
395 	case SDP_DATA_NIL:
396 		break;
397 	case SDP_UINT8:
398 		d->val.uint8 = *(uint8_t *) value;
399 		d->unitSize += sizeof(uint8_t);
400 		break;
401 	case SDP_INT8:
402 	case SDP_BOOL:
403 		d->val.int8 = *(int8_t *) value;
404 		d->unitSize += sizeof(int8_t);
405 		break;
406 	case SDP_UINT16:
407 		d->val.uint16 = bt_get_unaligned((uint16_t *) value);
408 		d->unitSize += sizeof(uint16_t);
409 		break;
410 	case SDP_INT16:
411 		d->val.int16 = bt_get_unaligned((int16_t *) value);
412 		d->unitSize += sizeof(int16_t);
413 		break;
414 	case SDP_UINT32:
415 		d->val.uint32 = bt_get_unaligned((uint32_t *) value);
416 		d->unitSize += sizeof(uint32_t);
417 		break;
418 	case SDP_INT32:
419 		d->val.int32 = bt_get_unaligned((int32_t *) value);
420 		d->unitSize += sizeof(int32_t);
421 		break;
422 	case SDP_INT64:
423 		d->val.int64 = bt_get_unaligned((int64_t *) value);
424 		d->unitSize += sizeof(int64_t);
425 		break;
426 	case SDP_UINT64:
427 		d->val.uint64 = bt_get_unaligned((uint64_t *) value);
428 		d->unitSize += sizeof(uint64_t);
429 		break;
430 	case SDP_UINT128:
431 		memcpy(&d->val.uint128.data, value, sizeof(uint128_t));
432 		d->unitSize += sizeof(uint128_t);
433 		break;
434 	case SDP_INT128:
435 		memcpy(&d->val.int128.data, value, sizeof(uint128_t));
436 		d->unitSize += sizeof(uint128_t);
437 		break;
438 	case SDP_UUID16:
439 		sdp_uuid16_create(&d->val.uuid, bt_get_unaligned((uint16_t *) value));
440 		d->unitSize += sizeof(uint16_t);
441 		break;
442 	case SDP_UUID32:
443 		sdp_uuid32_create(&d->val.uuid, bt_get_unaligned((uint32_t *) value));
444 		d->unitSize += sizeof(uint32_t);
445 		break;
446 	case SDP_UUID128:
447 		sdp_uuid128_create(&d->val.uuid, value);
448 		d->unitSize += sizeof(uint128_t);
449 		break;
450 	case SDP_URL_STR8:
451 	case SDP_URL_STR16:
452 	case SDP_TEXT_STR8:
453 	case SDP_TEXT_STR16:
454 		if (!value) {
455 			free(d);
456 			return NULL;
457 		}
458 
459 		d->unitSize += length;
460 		if (length <= USHRT_MAX) {
461 			d->val.str = malloc(length);
462 			if (!d->val.str) {
463 				free(d);
464 				return NULL;
465 			}
466 
467 			memcpy(d->val.str, value, length);
468 		} else {
469 			SDPERR("Strings of size > USHRT_MAX not supported\n");
470 			free(d);
471 			d = NULL;
472 		}
473 		break;
474 	case SDP_URL_STR32:
475 	case SDP_TEXT_STR32:
476 		SDPERR("Strings of size > USHRT_MAX not supported\n");
477 		break;
478 	case SDP_ALT8:
479 	case SDP_ALT16:
480 	case SDP_ALT32:
481 	case SDP_SEQ8:
482 	case SDP_SEQ16:
483 	case SDP_SEQ32:
484 		if (dtd == SDP_ALT8 || dtd == SDP_SEQ8)
485 			d->unitSize += sizeof(uint8_t);
486 		else if (dtd == SDP_ALT16 || dtd == SDP_SEQ16)
487 			d->unitSize += sizeof(uint16_t);
488 		else if (dtd == SDP_ALT32 || dtd == SDP_SEQ32)
489 			d->unitSize += sizeof(uint32_t);
490 		seq = (sdp_data_t *)value;
491 		d->val.dataseq = seq;
492 		for (; seq; seq = seq->next)
493 			d->unitSize += seq->unitSize;
494 		break;
495 	default:
496 		free(d);
497 		d = NULL;
498 	}
499 
500 	return d;
501 }
502 
sdp_data_alloc(uint8_t dtd,const void * value)503 sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value)
504 {
505 	uint32_t length;
506 
507 	switch (dtd) {
508 	case SDP_URL_STR8:
509 	case SDP_URL_STR16:
510 	case SDP_TEXT_STR8:
511 	case SDP_TEXT_STR16:
512 		if (!value)
513 			return NULL;
514 
515 		length = strlen((char *) value);
516 		break;
517 	default:
518 		length = 0;
519 		break;
520 	}
521 
522 	return sdp_data_alloc_with_length(dtd, value, length);
523 }
524 
sdp_seq_append(sdp_data_t * seq,sdp_data_t * d)525 sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *d)
526 {
527 	if (seq) {
528 		sdp_data_t *p;
529 		for (p = seq; p->next; p = p->next);
530 		p->next = d;
531 	} else
532 		seq = d;
533 	d->next = NULL;
534 	return seq;
535 }
536 
sdp_seq_alloc_with_length(void ** dtds,void ** values,int * length,int len)537 sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length,
538 								int len)
539 {
540 	sdp_data_t *curr = NULL, *seq = NULL;
541 	int i;
542 
543 	for (i = 0; i < len; i++) {
544 		sdp_data_t *data;
545 		int8_t dtd = *(uint8_t *) dtds[i];
546 
547 		if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32)
548 			data = (sdp_data_t *) values[i];
549 		else
550 			data = sdp_data_alloc_with_length(dtd, values[i], length[i]);
551 
552 		if (!data)
553 			return NULL;
554 
555 		if (curr)
556 			curr->next = data;
557 		else
558 			seq = data;
559 
560 		curr = data;
561 	}
562 
563 	return sdp_data_alloc_with_length(SDP_SEQ8, seq, length[i]);
564 }
565 
sdp_seq_alloc(void ** dtds,void ** values,int len)566 sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len)
567 {
568 	sdp_data_t *curr = NULL, *seq = NULL;
569 	int i;
570 
571 	for (i = 0; i < len; i++) {
572 		sdp_data_t *data;
573 		uint8_t dtd = *(uint8_t *) dtds[i];
574 
575 		if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32)
576 			data = (sdp_data_t *) values[i];
577 		else
578 			data = sdp_data_alloc(dtd, values[i]);
579 
580 		if (!data)
581 			return NULL;
582 
583 		if (curr)
584 			curr->next = data;
585 		else
586 			seq = data;
587 
588 		curr = data;
589 	}
590 
591 	return sdp_data_alloc(SDP_SEQ8, seq);
592 }
593 
extract_svclass_uuid(sdp_data_t * data,uuid_t * uuid)594 static void extract_svclass_uuid(sdp_data_t *data, uuid_t *uuid)
595 {
596 	sdp_data_t *d;
597 
598 	if (!data || data->dtd < SDP_SEQ8 || data->dtd > SDP_SEQ32)
599 		return;
600 
601 	d = data->val.dataseq;
602 	if (!d)
603 		return;
604 
605 	if (d->dtd < SDP_UUID16 || d->dtd > SDP_UUID128)
606 		return;
607 
608 	*uuid = d->val.uuid;
609 }
610 
sdp_attr_add(sdp_record_t * rec,uint16_t attr,sdp_data_t * d)611 int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d)
612 {
613 	sdp_data_t *p = sdp_data_get(rec, attr);
614 
615 	if (p)
616 		return -1;
617 
618 	d->attrId = attr;
619 	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func);
620 
621 	if (attr == SDP_ATTR_SVCLASS_ID_LIST)
622 		extract_svclass_uuid(d, &rec->svclass);
623 
624 	return 0;
625 }
626 
sdp_attr_remove(sdp_record_t * rec,uint16_t attr)627 void sdp_attr_remove(sdp_record_t *rec, uint16_t attr)
628 {
629 	sdp_data_t *d = sdp_data_get(rec, attr);
630 
631 	if (d)
632 		rec->attrlist = sdp_list_remove(rec->attrlist, d);
633 
634 	if (attr == SDP_ATTR_SVCLASS_ID_LIST)
635 		memset(&rec->svclass, 0, sizeof(rec->svclass));
636 }
637 
sdp_set_seq_len(uint8_t * ptr,uint32_t length)638 void sdp_set_seq_len(uint8_t *ptr, uint32_t length)
639 {
640 	uint8_t dtd = *ptr++;
641 
642 	switch (dtd) {
643 	case SDP_SEQ8:
644 	case SDP_ALT8:
645 	case SDP_TEXT_STR8:
646 	case SDP_URL_STR8:
647 		*ptr = (uint8_t) length;
648 		break;
649 	case SDP_SEQ16:
650 	case SDP_ALT16:
651 	case SDP_TEXT_STR16:
652 	case SDP_URL_STR16:
653 		bt_put_unaligned(htons(length), (uint16_t *) ptr);
654 		break;
655 	case SDP_SEQ32:
656 	case SDP_ALT32:
657 	case SDP_TEXT_STR32:
658 	case SDP_URL_STR32:
659 		bt_put_unaligned(htonl(length), (uint32_t *) ptr);
660 		break;
661 	}
662 }
663 
sdp_get_data_type(sdp_buf_t * buf,uint8_t dtd)664 static int sdp_get_data_type(sdp_buf_t *buf, uint8_t dtd)
665 {
666 	int data_type = 0;
667 
668 	data_type += sizeof(uint8_t);
669 
670 	switch (dtd) {
671 	case SDP_SEQ8:
672 	case SDP_TEXT_STR8:
673 	case SDP_URL_STR8:
674 	case SDP_ALT8:
675 		data_type += sizeof(uint8_t);
676 		break;
677 	case SDP_SEQ16:
678 	case SDP_TEXT_STR16:
679 	case SDP_URL_STR16:
680 	case SDP_ALT16:
681 		data_type += sizeof(uint16_t);
682 		break;
683 	case SDP_SEQ32:
684 	case SDP_TEXT_STR32:
685 	case SDP_URL_STR32:
686 	case SDP_ALT32:
687 		data_type += sizeof(uint32_t);
688 		break;
689 	}
690 
691 	if (!buf->data)
692 		buf->buf_size += data_type;
693 
694 	return data_type;
695 }
696 
sdp_set_data_type(sdp_buf_t * buf,uint8_t dtd)697 static int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd)
698 {
699 	int data_type = 0;
700 	uint8_t *p = buf->data + buf->data_size;
701 
702 	*p++ = dtd;
703 	data_type = sdp_get_data_type(buf, dtd);
704 	buf->data_size += data_type;
705 
706 	return data_type;
707 }
708 
sdp_set_attrid(sdp_buf_t * buf,uint16_t attr)709 void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr)
710 {
711 	uint8_t *p = buf->data;
712 
713 	/* data type for attr */
714 	*p++ = SDP_UINT16;
715 	buf->data_size = sizeof(uint8_t);
716 	bt_put_unaligned(htons(attr), (uint16_t *) p);
717 	p += sizeof(uint16_t);
718 	buf->data_size += sizeof(uint16_t);
719 }
720 
get_data_size(sdp_buf_t * buf,sdp_data_t * sdpdata)721 static int get_data_size(sdp_buf_t *buf, sdp_data_t *sdpdata)
722 {
723 	sdp_data_t *d;
724 	int n = 0;
725 
726 	for (d = sdpdata->val.dataseq; d; d = d->next) {
727 		if (buf->data)
728 			n += sdp_gen_pdu(buf, d);
729 		else
730 			n += sdp_gen_buffer(buf, d);
731 	}
732 
733 	return n;
734 }
735 
sdp_get_data_size(sdp_buf_t * buf,sdp_data_t * d)736 static int sdp_get_data_size(sdp_buf_t *buf, sdp_data_t *d)
737 {
738 	uint32_t data_size = 0;
739 	uint8_t dtd = d->dtd;
740 
741 	switch (dtd) {
742 	case SDP_DATA_NIL:
743 		break;
744 	case SDP_UINT8:
745 		data_size = sizeof(uint8_t);
746 		break;
747 	case SDP_UINT16:
748 		data_size = sizeof(uint16_t);
749 		break;
750 	case SDP_UINT32:
751 		data_size = sizeof(uint32_t);
752 		break;
753 	case SDP_UINT64:
754 		data_size = sizeof(uint64_t);
755 		break;
756 	case SDP_UINT128:
757 		data_size = sizeof(uint128_t);
758 		break;
759 	case SDP_INT8:
760 	case SDP_BOOL:
761 		data_size = sizeof(int8_t);
762 		break;
763 	case SDP_INT16:
764 		data_size = sizeof(int16_t);
765 		break;
766 	case SDP_INT32:
767 		data_size = sizeof(int32_t);
768 		break;
769 	case SDP_INT64:
770 		data_size = sizeof(int64_t);
771 		break;
772 	case SDP_INT128:
773 		data_size = sizeof(uint128_t);
774 		break;
775 	case SDP_TEXT_STR8:
776 	case SDP_TEXT_STR16:
777 	case SDP_TEXT_STR32:
778 	case SDP_URL_STR8:
779 	case SDP_URL_STR16:
780 	case SDP_URL_STR32:
781 		data_size = d->unitSize - sizeof(uint8_t);
782 		break;
783 	case SDP_SEQ8:
784 	case SDP_SEQ16:
785 	case SDP_SEQ32:
786 		data_size = get_data_size(buf, d);
787 		break;
788 	case SDP_ALT8:
789 	case SDP_ALT16:
790 	case SDP_ALT32:
791 		data_size = get_data_size(buf, d);
792 		break;
793 	case SDP_UUID16:
794 		data_size = sizeof(uint16_t);
795 		break;
796 	case SDP_UUID32:
797 		data_size = sizeof(uint32_t);
798 		break;
799 	case SDP_UUID128:
800 		data_size = sizeof(uint128_t);
801 		break;
802 	default:
803 		break;
804 	}
805 
806 	if (!buf->data)
807 		buf->buf_size += data_size;
808 
809 	return data_size;
810 }
811 
sdp_gen_buffer(sdp_buf_t * buf,sdp_data_t * d)812 static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d)
813 {
814 	int orig = buf->buf_size;
815 
816 	if (buf->buf_size == 0 && d->dtd == 0) {
817 		/* create initial sequence */
818 		buf->buf_size += sizeof(uint8_t);
819 
820 		/* reserve space for sequence size */
821 		buf->buf_size += sizeof(uint8_t);
822 	}
823 
824 	/* attribute length */
825 	buf->buf_size += sizeof(uint8_t) + sizeof(uint16_t);
826 
827 	sdp_get_data_type(buf, d->dtd);
828 	sdp_get_data_size(buf, d);
829 
830 	if (buf->buf_size > UCHAR_MAX && d->dtd == SDP_SEQ8)
831 		buf->buf_size += sizeof(uint8_t);
832 
833 	return buf->buf_size - orig;
834 }
835 
sdp_gen_pdu(sdp_buf_t * buf,sdp_data_t * d)836 int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
837 {
838 	uint32_t pdu_size = 0, data_size = 0;
839 	unsigned char *src = NULL, is_seq = 0, is_alt = 0;
840 	uint8_t dtd = d->dtd;
841 	uint16_t u16;
842 	uint32_t u32;
843 	uint64_t u64;
844 	uint128_t u128;
845 	uint8_t *seqp = buf->data + buf->data_size;
846 
847 	pdu_size = sdp_set_data_type(buf, dtd);
848 	data_size = sdp_get_data_size(buf, d);
849 
850 	switch (dtd) {
851 	case SDP_DATA_NIL:
852 		break;
853 	case SDP_UINT8:
854 		src = &d->val.uint8;
855 		break;
856 	case SDP_UINT16:
857 		u16 = htons(d->val.uint16);
858 		src = (unsigned char *) &u16;
859 		break;
860 	case SDP_UINT32:
861 		u32 = htonl(d->val.uint32);
862 		src = (unsigned char *) &u32;
863 		break;
864 	case SDP_UINT64:
865 		u64 = hton64(d->val.uint64);
866 		src = (unsigned char *) &u64;
867 		break;
868 	case SDP_UINT128:
869 		hton128(&d->val.uint128, &u128);
870 		src = (unsigned char *) &u128;
871 		break;
872 	case SDP_INT8:
873 	case SDP_BOOL:
874 		src = (unsigned char *) &d->val.int8;
875 		break;
876 	case SDP_INT16:
877 		u16 = htons(d->val.int16);
878 		src = (unsigned char *) &u16;
879 		break;
880 	case SDP_INT32:
881 		u32 = htonl(d->val.int32);
882 		src = (unsigned char *) &u32;
883 		break;
884 	case SDP_INT64:
885 		u64 = hton64(d->val.int64);
886 		src = (unsigned char *) &u64;
887 		break;
888 	case SDP_INT128:
889 		hton128(&d->val.int128, &u128);
890 		src = (unsigned char *) &u128;
891 		break;
892 	case SDP_TEXT_STR8:
893 	case SDP_TEXT_STR16:
894 	case SDP_TEXT_STR32:
895 	case SDP_URL_STR8:
896 	case SDP_URL_STR16:
897 	case SDP_URL_STR32:
898 		src = (unsigned char *) d->val.str;
899 		sdp_set_seq_len(seqp, data_size);
900 		break;
901 	case SDP_SEQ8:
902 	case SDP_SEQ16:
903 	case SDP_SEQ32:
904 		is_seq = 1;
905 		sdp_set_seq_len(seqp, data_size);
906 		break;
907 	case SDP_ALT8:
908 	case SDP_ALT16:
909 	case SDP_ALT32:
910 		is_alt = 1;
911 		sdp_set_seq_len(seqp, data_size);
912 		break;
913 	case SDP_UUID16:
914 		u16 = htons(d->val.uuid.value.uuid16);
915 		src = (unsigned char *) &u16;
916 		break;
917 	case SDP_UUID32:
918 		u32 = htonl(d->val.uuid.value.uuid32);
919 		src = (unsigned char *) &u32;
920 		break;
921 	case SDP_UUID128:
922 		src = (unsigned char *) &d->val.uuid.value.uuid128;
923 		break;
924 	default:
925 		break;
926 	}
927 
928 	if (!is_seq && !is_alt) {
929 		if (src && buf && buf->buf_size >= buf->data_size + data_size) {
930 			memcpy(buf->data + buf->data_size, src, data_size);
931 			buf->data_size += data_size;
932 		} else if (dtd != SDP_DATA_NIL) {
933 			SDPDBG("Gen PDU : Can't copy from invalid source or dest\n");
934 		}
935 	}
936 
937 	pdu_size += data_size;
938 
939 	return pdu_size;
940 }
941 
sdp_attr_pdu(void * value,void * udata)942 static void sdp_attr_pdu(void *value, void *udata)
943 {
944 	sdp_append_to_pdu((sdp_buf_t *)udata, (sdp_data_t *)value);
945 }
946 
sdp_attr_size(void * value,void * udata)947 static void sdp_attr_size(void *value, void *udata)
948 {
949 	sdp_gen_buffer((sdp_buf_t *)udata, (sdp_data_t *)value);
950 }
951 
sdp_gen_record_pdu(const sdp_record_t * rec,sdp_buf_t * buf)952 int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *buf)
953 {
954 	memset(buf, 0, sizeof(sdp_buf_t));
955 	sdp_list_foreach(rec->attrlist, sdp_attr_size, buf);
956 
957 	buf->data = malloc(buf->buf_size);
958 	if (!buf->data)
959 		return -ENOMEM;
960 	buf->data_size = 0;
961 	memset(buf->data, 0, buf->buf_size);
962 
963 	sdp_list_foreach(rec->attrlist, sdp_attr_pdu, buf);
964 
965 	return 0;
966 }
967 
sdp_attr_replace(sdp_record_t * rec,uint16_t attr,sdp_data_t * d)968 void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *d)
969 {
970 	sdp_data_t *p = sdp_data_get(rec, attr);
971 
972 	if (p) {
973 		rec->attrlist = sdp_list_remove(rec->attrlist, p);
974 		sdp_data_free(p);
975 	}
976 
977 	d->attrId = attr;
978 	rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func);
979 
980 	if (attr == SDP_ATTR_SVCLASS_ID_LIST)
981 		extract_svclass_uuid(d, &rec->svclass);
982 }
983 
sdp_attrid_comp_func(const void * key1,const void * key2)984 int sdp_attrid_comp_func(const void *key1, const void *key2)
985 {
986 	const sdp_data_t *d1 = (const sdp_data_t *)key1;
987 	const sdp_data_t *d2 = (const sdp_data_t *)key2;
988 
989 	if (d1 && d2)
990 		return d1->attrId - d2->attrId;
991 	return 0;
992 }
993 
data_seq_free(sdp_data_t * seq)994 static void data_seq_free(sdp_data_t *seq)
995 {
996 	sdp_data_t *d = seq->val.dataseq;
997 
998 	while (d) {
999 		sdp_data_t *next = d->next;
1000 		sdp_data_free(d);
1001 		d = next;
1002 	}
1003 }
1004 
sdp_data_free(sdp_data_t * d)1005 void sdp_data_free(sdp_data_t *d)
1006 {
1007 	switch (d->dtd) {
1008 	case SDP_SEQ8:
1009 	case SDP_SEQ16:
1010 	case SDP_SEQ32:
1011 		data_seq_free(d);
1012 		break;
1013 	case SDP_URL_STR8:
1014 	case SDP_URL_STR16:
1015 	case SDP_URL_STR32:
1016 	case SDP_TEXT_STR8:
1017 	case SDP_TEXT_STR16:
1018 	case SDP_TEXT_STR32:
1019 		free(d->val.str);
1020 		break;
1021 	}
1022 	free(d);
1023 }
1024 
sdp_uuid_extract(const uint8_t * p,int bufsize,uuid_t * uuid,int * scanned)1025 int sdp_uuid_extract(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned)
1026 {
1027 	uint8_t type;
1028 
1029 	if (bufsize < (int) sizeof(uint8_t)) {
1030 		SDPERR("Unexpected end of packet");
1031 		return -1;
1032 	}
1033 
1034 	type = *(const uint8_t *) p;
1035 
1036 	if (!SDP_IS_UUID(type)) {
1037 		SDPERR("Unknown data type : %d expecting a svc UUID\n", type);
1038 		return -1;
1039 	}
1040 	p += sizeof(uint8_t);
1041 	*scanned += sizeof(uint8_t);
1042 	bufsize -= sizeof(uint8_t);
1043 	if (type == SDP_UUID16) {
1044 		if (bufsize < (int) sizeof(uint16_t)) {
1045 			SDPERR("Not enough room for 16-bit UUID");
1046 			return -1;
1047 		}
1048 		sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p)));
1049 		*scanned += sizeof(uint16_t);
1050 		p += sizeof(uint16_t);
1051 	} else if (type == SDP_UUID32) {
1052 		if (bufsize < (int) sizeof(uint32_t)) {
1053 			SDPERR("Not enough room for 32-bit UUID");
1054 			return -1;
1055 		}
1056 		sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p)));
1057 		*scanned += sizeof(uint32_t);
1058 		p += sizeof(uint32_t);
1059 	} else {
1060 		if (bufsize < (int) sizeof(uint128_t)) {
1061 			SDPERR("Not enough room for 128-bit UUID");
1062 			return -1;
1063 		}
1064 		sdp_uuid128_create(uuid, p);
1065 		*scanned += sizeof(uint128_t);
1066 		p += sizeof(uint128_t);
1067 	}
1068 	return 0;
1069 }
1070 
extract_int(const void * p,int bufsize,int * len)1071 static sdp_data_t *extract_int(const void *p, int bufsize, int *len)
1072 {
1073 	sdp_data_t *d;
1074 
1075 	if (bufsize < (int) sizeof(uint8_t)) {
1076 		SDPERR("Unexpected end of packet");
1077 		return NULL;
1078 	}
1079 
1080 	d = malloc(sizeof(sdp_data_t));
1081 	if (!d)
1082 		return NULL;
1083 
1084 	SDPDBG("Extracting integer\n");
1085 	memset(d, 0, sizeof(sdp_data_t));
1086 	d->dtd = *(uint8_t *) p;
1087 	p += sizeof(uint8_t);
1088 	*len += sizeof(uint8_t);
1089 	bufsize -= sizeof(uint8_t);
1090 
1091 	switch (d->dtd) {
1092 	case SDP_DATA_NIL:
1093 		break;
1094 	case SDP_BOOL:
1095 	case SDP_INT8:
1096 	case SDP_UINT8:
1097 		if (bufsize < (int) sizeof(uint8_t)) {
1098 			SDPERR("Unexpected end of packet");
1099 			free(d);
1100 			return NULL;
1101 		}
1102 		*len += sizeof(uint8_t);
1103 		d->val.uint8 = *(uint8_t *) p;
1104 		break;
1105 	case SDP_INT16:
1106 	case SDP_UINT16:
1107 		if (bufsize < (int) sizeof(uint16_t)) {
1108 			SDPERR("Unexpected end of packet");
1109 			free(d);
1110 			return NULL;
1111 		}
1112 		*len += sizeof(uint16_t);
1113 		d->val.uint16 = ntohs(bt_get_unaligned((uint16_t *) p));
1114 		break;
1115 	case SDP_INT32:
1116 	case SDP_UINT32:
1117 		if (bufsize < (int) sizeof(uint32_t)) {
1118 			SDPERR("Unexpected end of packet");
1119 			free(d);
1120 			return NULL;
1121 		}
1122 		*len += sizeof(uint32_t);
1123 		d->val.uint32 = ntohl(bt_get_unaligned((uint32_t *) p));
1124 		break;
1125 	case SDP_INT64:
1126 	case SDP_UINT64:
1127 		if (bufsize < (int) sizeof(uint64_t)) {
1128 			SDPERR("Unexpected end of packet");
1129 			free(d);
1130 			return NULL;
1131 		}
1132 		*len += sizeof(uint64_t);
1133 		d->val.uint64 = ntoh64(bt_get_unaligned((uint64_t *) p));
1134 		break;
1135 	case SDP_INT128:
1136 	case SDP_UINT128:
1137 		if (bufsize < (int) sizeof(uint128_t)) {
1138 			SDPERR("Unexpected end of packet");
1139 			free(d);
1140 			return NULL;
1141 		}
1142 		*len += sizeof(uint128_t);
1143 		ntoh128((uint128_t *) p, &d->val.uint128);
1144 		break;
1145 	default:
1146 		free(d);
1147 		d = NULL;
1148 	}
1149 	return d;
1150 }
1151 
extract_uuid(const uint8_t * p,int bufsize,int * len,sdp_record_t * rec)1152 static sdp_data_t *extract_uuid(const uint8_t *p, int bufsize, int *len,
1153 							sdp_record_t *rec)
1154 {
1155 	sdp_data_t *d = malloc(sizeof(sdp_data_t));
1156 
1157 	if (!d)
1158 		return NULL;
1159 
1160 	SDPDBG("Extracting UUID");
1161 	memset(d, 0, sizeof(sdp_data_t));
1162 	if (sdp_uuid_extract(p, bufsize, &d->val.uuid, len) < 0) {
1163 		free(d);
1164 		return NULL;
1165 	}
1166 	d->dtd = *p;
1167 	if (rec)
1168 		sdp_pattern_add_uuid(rec, &d->val.uuid);
1169 	return d;
1170 }
1171 
1172 /*
1173  * Extract strings from the PDU (could be service description and similar info)
1174  */
extract_str(const void * p,int bufsize,int * len)1175 static sdp_data_t *extract_str(const void *p, int bufsize, int *len)
1176 {
1177 	char *s;
1178 	int n;
1179 	sdp_data_t *d;
1180 
1181 	if (bufsize < (int) sizeof(uint8_t)) {
1182 		SDPERR("Unexpected end of packet");
1183 		return NULL;
1184 	}
1185 
1186 	d = malloc(sizeof(sdp_data_t));
1187 	if (!d)
1188 		return NULL;
1189 
1190 	memset(d, 0, sizeof(sdp_data_t));
1191 	d->dtd = *(uint8_t *) p;
1192 	p += sizeof(uint8_t);
1193 	*len += sizeof(uint8_t);
1194 	bufsize -= sizeof(uint8_t);
1195 
1196 	switch (d->dtd) {
1197 	case SDP_TEXT_STR8:
1198 	case SDP_URL_STR8:
1199 		if (bufsize < (int) sizeof(uint8_t)) {
1200 			SDPERR("Unexpected end of packet");
1201 			free(d);
1202 			return NULL;
1203 		}
1204 		n = *(uint8_t *) p;
1205 		p += sizeof(uint8_t);
1206 		*len += sizeof(uint8_t);
1207 		bufsize -= sizeof(uint8_t);
1208 		break;
1209 	case SDP_TEXT_STR16:
1210 	case SDP_URL_STR16:
1211 		if (bufsize < (int) sizeof(uint16_t)) {
1212 			SDPERR("Unexpected end of packet");
1213 			free(d);
1214 			return NULL;
1215 		}
1216 		n = ntohs(bt_get_unaligned((uint16_t *) p));
1217 		p += sizeof(uint16_t);
1218 		*len += sizeof(uint16_t) + n;
1219 		bufsize -= sizeof(uint16_t);
1220 		break;
1221 	default:
1222 		SDPERR("Sizeof text string > UINT16_MAX\n");
1223 		free(d);
1224 		return NULL;
1225 	}
1226 
1227 	if (bufsize < n) {
1228 		SDPERR("String too long to fit in packet");
1229 		free(d);
1230 		return NULL;
1231 	}
1232 
1233 	s = malloc(n + 1);
1234 	if (!s) {
1235 		SDPERR("Not enough memory for incoming string");
1236 		free(d);
1237 		return NULL;
1238 	}
1239 	memset(s, 0, n + 1);
1240 	memcpy(s, p, n);
1241 
1242 	*len += n;
1243 
1244 	SDPDBG("Len : %d\n", n);
1245 	SDPDBG("Str : %s\n", s);
1246 
1247 	d->val.str = s;
1248 	d->unitSize = n + sizeof(uint8_t);
1249 	return d;
1250 }
1251 
1252 /*
1253  * Extract the sequence type and its length, and return offset into buf
1254  * or 0 on failure.
1255  */
sdp_extract_seqtype(const uint8_t * buf,int bufsize,uint8_t * dtdp,int * size)1256 int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size)
1257 {
1258 	uint8_t dtd;
1259 	int scanned = sizeof(uint8_t);
1260 
1261 	if (bufsize < (int) sizeof(uint8_t)) {
1262 		SDPERR("Unexpected end of packet");
1263 		return 0;
1264 	}
1265 
1266 	dtd = *(uint8_t *) buf;
1267 	buf += sizeof(uint8_t);
1268 	bufsize -= sizeof(uint8_t);
1269 	*dtdp = dtd;
1270 	switch (dtd) {
1271 	case SDP_SEQ8:
1272 	case SDP_ALT8:
1273 		if (bufsize < (int) sizeof(uint8_t)) {
1274 			SDPERR("Unexpected end of packet");
1275 			return 0;
1276 		}
1277 		*size = *(uint8_t *) buf;
1278 		scanned += sizeof(uint8_t);
1279 		break;
1280 	case SDP_SEQ16:
1281 	case SDP_ALT16:
1282 		if (bufsize < (int) sizeof(uint16_t)) {
1283 			SDPERR("Unexpected end of packet");
1284 			return 0;
1285 		}
1286 		*size = ntohs(bt_get_unaligned((uint16_t *) buf));
1287 		scanned += sizeof(uint16_t);
1288 		break;
1289 	case SDP_SEQ32:
1290 	case SDP_ALT32:
1291 		if (bufsize < (int) sizeof(uint32_t)) {
1292 			SDPERR("Unexpected end of packet");
1293 			return 0;
1294 		}
1295 		*size = ntohl(bt_get_unaligned((uint32_t *) buf));
1296 		scanned += sizeof(uint32_t);
1297 		break;
1298 	default:
1299 		SDPERR("Unknown sequence type, aborting\n");
1300 		return 0;
1301 	}
1302 	return scanned;
1303 }
1304 
extract_seq(const void * p,int bufsize,int * len,sdp_record_t * rec)1305 static sdp_data_t *extract_seq(const void *p, int bufsize, int *len,
1306 							sdp_record_t *rec)
1307 {
1308 	int seqlen, n = 0;
1309 	sdp_data_t *curr, *prev;
1310 	sdp_data_t *d = malloc(sizeof(sdp_data_t));
1311 
1312 	if (!d)
1313 		return NULL;
1314 
1315 	SDPDBG("Extracting SEQ");
1316 	memset(d, 0, sizeof(sdp_data_t));
1317 	*len = sdp_extract_seqtype(p, bufsize, &d->dtd, &seqlen);
1318 	SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen);
1319 
1320 	if (*len == 0)
1321 		return d;
1322 
1323 	if (*len > bufsize) {
1324 		SDPERR("Packet not big enough to hold sequence.");
1325 		free(d);
1326 		return NULL;
1327 	}
1328 
1329 	p += *len;
1330 	bufsize -= *len;
1331 	prev = NULL;
1332 	while (n < seqlen) {
1333 		int attrlen = 0;
1334 		curr = sdp_extract_attr(p, bufsize, &attrlen, rec);
1335 		if (curr == NULL)
1336 			break;
1337 
1338 		if (prev)
1339 			prev->next = curr;
1340 		else
1341 			d->val.dataseq = curr;
1342 		prev = curr;
1343 		p += attrlen;
1344 		n += attrlen;
1345 		bufsize -= attrlen;
1346 
1347 		SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen);
1348 	}
1349 
1350 	*len += n;
1351 	return d;
1352 }
1353 
sdp_extract_attr(const uint8_t * p,int bufsize,int * size,sdp_record_t * rec)1354 sdp_data_t *sdp_extract_attr(const uint8_t *p, int bufsize, int *size,
1355 							sdp_record_t *rec)
1356 {
1357 	sdp_data_t *elem;
1358 	int n = 0;
1359 	uint8_t dtd;
1360 
1361 	if (bufsize < (int) sizeof(uint8_t)) {
1362 		SDPERR("Unexpected end of packet");
1363 		return NULL;
1364 	}
1365 
1366 	dtd = *(const uint8_t *)p;
1367 
1368 	SDPDBG("extract_attr: dtd=0x%x", dtd);
1369 	switch (dtd) {
1370 	case SDP_DATA_NIL:
1371 	case SDP_BOOL:
1372 	case SDP_UINT8:
1373 	case SDP_UINT16:
1374 	case SDP_UINT32:
1375 	case SDP_UINT64:
1376 	case SDP_UINT128:
1377 	case SDP_INT8:
1378 	case SDP_INT16:
1379 	case SDP_INT32:
1380 	case SDP_INT64:
1381 	case SDP_INT128:
1382 		elem = extract_int(p, bufsize, &n);
1383 		break;
1384 	case SDP_UUID16:
1385 	case SDP_UUID32:
1386 	case SDP_UUID128:
1387 		elem = extract_uuid(p, bufsize, &n, rec);
1388 		break;
1389 	case SDP_TEXT_STR8:
1390 	case SDP_TEXT_STR16:
1391 	case SDP_TEXT_STR32:
1392 	case SDP_URL_STR8:
1393 	case SDP_URL_STR16:
1394 	case SDP_URL_STR32:
1395 		elem = extract_str(p, bufsize, &n);
1396 		break;
1397 	case SDP_SEQ8:
1398 	case SDP_SEQ16:
1399 	case SDP_SEQ32:
1400 	case SDP_ALT8:
1401 	case SDP_ALT16:
1402 	case SDP_ALT32:
1403 		elem = extract_seq(p, bufsize, &n, rec);
1404 		break;
1405 	default:
1406 		SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd);
1407 		return NULL;
1408 	}
1409 	*size += n;
1410 	return elem;
1411 }
1412 
1413 #ifdef SDP_DEBUG
attr_print_func(void * value,void * userData)1414 static void attr_print_func(void *value, void *userData)
1415 {
1416 	sdp_data_t *d = (sdp_data_t *)value;
1417 
1418 	SDPDBG("=====================================\n");
1419 	SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n",  d->attrId);
1420 	SDPDBG("ATTRIBUTE VALUE PTR : 0x%x\n", (uint32_t)value);
1421 	if (d)
1422 		sdp_data_print(d);
1423 	else
1424 		SDPDBG("NULL value\n");
1425 	SDPDBG("=====================================\n");
1426 }
1427 
sdp_print_service_attr(sdp_list_t * svcAttrList)1428 void sdp_print_service_attr(sdp_list_t *svcAttrList)
1429 {
1430 	SDPDBG("Printing service attr list %p\n", svcAttrList);
1431 	sdp_list_foreach(svcAttrList, attr_print_func, NULL);
1432 	SDPDBG("Printed service attr list %p\n", svcAttrList);
1433 }
1434 #endif
1435 
sdp_extract_pdu(const uint8_t * buf,int bufsize,int * scanned)1436 sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int bufsize, int *scanned)
1437 {
1438 	int extracted = 0, seqlen = 0;
1439 	uint8_t dtd;
1440 	uint16_t attr;
1441 	sdp_record_t *rec = sdp_record_alloc();
1442 	const uint8_t *p = buf;
1443 
1444 	*scanned = sdp_extract_seqtype(buf, bufsize, &dtd, &seqlen);
1445 	p += *scanned;
1446 	bufsize -= *scanned;
1447 	rec->attrlist = NULL;
1448 
1449 	while (extracted < seqlen && bufsize > 0) {
1450 		int n = sizeof(uint8_t), attrlen = 0;
1451 		sdp_data_t *data = NULL;
1452 
1453 		SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d",
1454 							seqlen, extracted);
1455 
1456 		if (bufsize < n + (int) sizeof(uint16_t)) {
1457 			SDPERR("Unexpected end of packet");
1458 			break;
1459 		}
1460 
1461 		dtd = *(uint8_t *) p;
1462 		attr = ntohs(bt_get_unaligned((uint16_t *) (p + n)));
1463 		n += sizeof(uint16_t);
1464 
1465 		SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr);
1466 
1467 		data = sdp_extract_attr(p + n, bufsize - n, &attrlen, rec);
1468 
1469 		SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen);
1470 
1471 		n += attrlen;
1472 		if (data == NULL) {
1473 			SDPDBG("Terminating extraction of attributes");
1474 			break;
1475 		}
1476 
1477 		if (attr == SDP_ATTR_RECORD_HANDLE)
1478 			rec->handle = data->val.uint32;
1479 
1480 		if (attr == SDP_ATTR_SVCLASS_ID_LIST)
1481 			extract_svclass_uuid(data, &rec->svclass);
1482 
1483 		extracted += n;
1484 		p += n;
1485 		bufsize -= n;
1486 		sdp_attr_replace(rec, attr, data);
1487 
1488 		SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d",
1489 							seqlen, extracted);
1490 	}
1491 #ifdef SDP_DEBUG
1492 	SDPDBG("Successful extracting of Svc Rec attributes\n");
1493 	sdp_print_service_attr(rec->attrlist);
1494 #endif
1495 	*scanned += seqlen;
1496 	return rec;
1497 }
1498 
sdp_copy_pattern(void * value,void * udata)1499 static void sdp_copy_pattern(void *value, void *udata)
1500 {
1501 	uuid_t *uuid = value;
1502 	sdp_record_t *rec = udata;
1503 
1504 	sdp_pattern_add_uuid(rec, uuid);
1505 }
1506 
sdp_data_value(sdp_data_t * data,uint32_t * len)1507 static void *sdp_data_value(sdp_data_t *data, uint32_t *len)
1508 {
1509 	void *val = NULL;
1510 
1511 	switch (data->dtd) {
1512 	case SDP_DATA_NIL:
1513 		break;
1514 	case SDP_UINT8:
1515 		val = &data->val.uint8;
1516 		break;
1517 	case SDP_INT8:
1518 	case SDP_BOOL:
1519 		val = &data->val.int8;
1520 		break;
1521 	case SDP_UINT16:
1522 		val = &data->val.uint16;
1523 		break;
1524 	case SDP_INT16:
1525 		val = &data->val.int16;
1526 		break;
1527 	case SDP_UINT32:
1528 		val = &data->val.uint32;
1529 		break;
1530 	case SDP_INT32:
1531 		val = &data->val.int32;
1532 		break;
1533 	case SDP_INT64:
1534 		val = &data->val.int64;
1535 		break;
1536 	case SDP_UINT64:
1537 		val = &data->val.uint64;
1538 		break;
1539 	case SDP_UINT128:
1540 		val = &data->val.uint128;
1541 		break;
1542 	case SDP_INT128:
1543 		val = &data->val.int128;
1544 		break;
1545 	case SDP_UUID16:
1546 		val = &data->val.uuid.value.uuid16;
1547 		break;
1548 	case SDP_UUID32:
1549 		val = &data->val.uuid.value.uuid32;
1550 		break;
1551 	case SDP_UUID128:
1552 		val = &data->val.uuid.value.uuid128;
1553 		break;
1554 	case SDP_URL_STR8:
1555 	case SDP_URL_STR16:
1556 	case SDP_TEXT_STR8:
1557 	case SDP_TEXT_STR16:
1558 	case SDP_URL_STR32:
1559 	case SDP_TEXT_STR32:
1560 		val = data->val.str;
1561 		if (len)
1562 			*len = data->unitSize - 1;
1563 		break;
1564 	case SDP_ALT8:
1565 	case SDP_ALT16:
1566 	case SDP_ALT32:
1567 	case SDP_SEQ8:
1568 	case SDP_SEQ16:
1569 	case SDP_SEQ32:
1570 		val = sdp_copy_seq(data->val.dataseq);
1571 		break;
1572 	}
1573 
1574 	return val;
1575 }
1576 
sdp_copy_seq(sdp_data_t * data)1577 static sdp_data_t *sdp_copy_seq(sdp_data_t *data)
1578 {
1579 	sdp_data_t *tmp, *seq = NULL, *cur = NULL;
1580 
1581 	for (tmp = data; tmp; tmp = tmp->next) {
1582 		sdp_data_t *datatmp;
1583 		void *value;
1584 
1585 		value = sdp_data_value(tmp, NULL);
1586 		datatmp = sdp_data_alloc_with_length(tmp->dtd, value,
1587 								tmp->unitSize);
1588 
1589 		if (cur)
1590 			cur->next = datatmp;
1591 		else
1592 			seq = datatmp;
1593 
1594 		cur = datatmp;
1595 	}
1596 
1597 	return seq;
1598 }
1599 
sdp_copy_attrlist(void * value,void * udata)1600 static void sdp_copy_attrlist(void *value, void *udata)
1601 {
1602 	sdp_data_t *data = value;
1603 	sdp_record_t *rec = udata;
1604 	void *val;
1605 	uint32_t len = 0;
1606 
1607 	val = sdp_data_value(data, &len);
1608 
1609 	if (!len)
1610 		sdp_attr_add_new(rec, data->attrId, data->dtd, val);
1611 	else
1612 		sdp_attr_add_new_with_length(rec, data->attrId,
1613 							data->dtd, val, len);
1614 }
1615 
sdp_copy_record(sdp_record_t * rec)1616 sdp_record_t *sdp_copy_record(sdp_record_t *rec)
1617 {
1618 	sdp_record_t *cpy;
1619 
1620 	cpy = sdp_record_alloc();
1621 
1622 	cpy->handle = rec->handle;
1623 
1624 	sdp_list_foreach(rec->pattern, sdp_copy_pattern, cpy);
1625 	sdp_list_foreach(rec->attrlist, sdp_copy_attrlist, cpy);
1626 
1627 	cpy->svclass = rec->svclass;
1628 
1629 	return cpy;
1630 }
1631 
1632 #ifdef SDP_DEBUG
print_dataseq(sdp_data_t * p)1633 static void print_dataseq(sdp_data_t *p)
1634 {
1635 	sdp_data_t *d;
1636 
1637 	for (d = p; d; d = d->next)
1638 		sdp_data_print(d);
1639 }
1640 #endif
1641 
sdp_record_print(const sdp_record_t * rec)1642 void sdp_record_print(const sdp_record_t *rec)
1643 {
1644 	sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY);
1645 	if (d)
1646 		printf("Service Name: %.*s\n", d->unitSize, d->val.str);
1647 	d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY);
1648 	if (d)
1649 		printf("Service Description: %.*s\n", d->unitSize, d->val.str);
1650 	d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY);
1651 	if (d)
1652 		printf("Service Provider: %.*s\n", d->unitSize, d->val.str);
1653 }
1654 
1655 #ifdef SDP_DEBUG
sdp_data_print(sdp_data_t * d)1656 void sdp_data_print(sdp_data_t *d)
1657 {
1658 	switch (d->dtd) {
1659 	case SDP_DATA_NIL:
1660 		SDPDBG("NIL\n");
1661 		break;
1662 	case SDP_BOOL:
1663 	case SDP_UINT8:
1664 	case SDP_UINT16:
1665 	case SDP_UINT32:
1666 	case SDP_UINT64:
1667 	case SDP_UINT128:
1668 	case SDP_INT8:
1669 	case SDP_INT16:
1670 	case SDP_INT32:
1671 	case SDP_INT64:
1672 	case SDP_INT128:
1673 		SDPDBG("Integer : 0x%x\n", d->val.uint32);
1674 		break;
1675 	case SDP_UUID16:
1676 	case SDP_UUID32:
1677 	case SDP_UUID128:
1678 		SDPDBG("UUID\n");
1679 		sdp_uuid_print(&d->val.uuid);
1680 		break;
1681 	case SDP_TEXT_STR8:
1682 	case SDP_TEXT_STR16:
1683 	case SDP_TEXT_STR32:
1684 		SDPDBG("Text : %s\n", d->val.str);
1685 		break;
1686 	case SDP_URL_STR8:
1687 	case SDP_URL_STR16:
1688 	case SDP_URL_STR32:
1689 		SDPDBG("URL : %s\n", d->val.str);
1690 		break;
1691 	case SDP_SEQ8:
1692 	case SDP_SEQ16:
1693 	case SDP_SEQ32:
1694 		print_dataseq(d->val.dataseq);
1695 		break;
1696 	case SDP_ALT8:
1697 	case SDP_ALT16:
1698 	case SDP_ALT32:
1699 		SDPDBG("Data Sequence Alternates\n");
1700 		print_dataseq(d->val.dataseq);
1701 		break;
1702 	}
1703 }
1704 #endif
1705 
sdp_data_get(const sdp_record_t * rec,uint16_t attrId)1706 sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId)
1707 {
1708 	if (rec->attrlist) {
1709 		sdp_data_t sdpTemplate;
1710 		sdp_list_t *p;
1711 
1712 		sdpTemplate.attrId = attrId;
1713 		p = sdp_list_find(rec->attrlist, &sdpTemplate, sdp_attrid_comp_func);
1714 		if (p)
1715 			return p->data;
1716 	}
1717 	return NULL;
1718 }
1719 
sdp_send_req(sdp_session_t * session,uint8_t * buf,uint32_t size)1720 static int sdp_send_req(sdp_session_t *session, uint8_t *buf, uint32_t size)
1721 {
1722 	uint32_t sent = 0;
1723 
1724 	while (sent < size) {
1725 		int n = send(session->sock, buf + sent, size - sent, 0);
1726 		if (n < 0)
1727 			return -1;
1728 		sent += n;
1729 	}
1730 	return 0;
1731 }
1732 
sdp_read_rsp(sdp_session_t * session,uint8_t * buf,uint32_t size)1733 static int sdp_read_rsp(sdp_session_t *session, uint8_t *buf, uint32_t size)
1734 {
1735 	fd_set readFds;
1736 	struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 };
1737 
1738 	FD_ZERO(&readFds);
1739 	FD_SET(session->sock, &readFds);
1740 	SDPDBG("Waiting for response\n");
1741 	if (select(session->sock + 1, &readFds, NULL, NULL, &timeout) == 0) {
1742 		SDPERR("Client timed out\n");
1743 		errno = ETIMEDOUT;
1744 		return -1;
1745 	}
1746 	return recv(session->sock, buf, size, 0);
1747 }
1748 
1749 /*
1750  * generic send request, wait for response method.
1751  */
sdp_send_req_w4_rsp(sdp_session_t * session,uint8_t * reqbuf,uint8_t * rspbuf,uint32_t reqsize,uint32_t * rspsize)1752 int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *reqbuf,
1753 			uint8_t *rspbuf, uint32_t reqsize, uint32_t *rspsize)
1754 {
1755 	int n;
1756 	sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *) reqbuf;
1757 	sdp_pdu_hdr_t *rsphdr = (sdp_pdu_hdr_t *) rspbuf;
1758 
1759 	SDPDBG("");
1760 	if (0 > sdp_send_req(session, reqbuf, reqsize)) {
1761 		SDPERR("Error sending data:%s", strerror(errno));
1762 		return -1;
1763 	}
1764 	n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE);
1765 	if (0 > n)
1766 		return -1;
1767 	SDPDBG("Read : %d\n", n);
1768 	if (n == 0 || reqhdr->tid != rsphdr->tid) {
1769 		errno = EPROTO;
1770 		return -1;
1771 	}
1772 	*rspsize = n;
1773 	return 0;
1774 }
1775 
1776 /*
1777  * singly-linked lists (after openobex implementation)
1778  */
sdp_list_append(sdp_list_t * p,void * d)1779 sdp_list_t *sdp_list_append(sdp_list_t *p, void *d)
1780 {
1781 	sdp_list_t *q, *n = malloc(sizeof(sdp_list_t));
1782 
1783 	if (!n)
1784 		return NULL;
1785 
1786 	n->data = d;
1787 	n->next = 0;
1788 
1789 	if (!p)
1790 		return n;
1791 
1792 	for (q = p; q->next; q = q->next);
1793 	q->next = n;
1794 
1795 	return p;
1796 }
1797 
sdp_list_remove(sdp_list_t * list,void * d)1798 sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d)
1799 {
1800 	sdp_list_t *p, *q;
1801 
1802 	for (q = 0, p = list; p; q = p, p = p->next)
1803 		if (p->data == d) {
1804 			if (q)
1805 				q->next = p->next;
1806 			else
1807 				list = p->next;
1808 			free(p);
1809 			break;
1810 		}
1811 
1812 	return list;
1813 }
1814 
sdp_list_insert_sorted(sdp_list_t * list,void * d,sdp_comp_func_t f)1815 sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *d,
1816 							sdp_comp_func_t f)
1817 {
1818 	sdp_list_t *q, *p, *n;
1819 
1820 	n = malloc(sizeof(sdp_list_t));
1821 	if (!n)
1822 		return NULL;
1823 	n->data = d;
1824 	for (q = 0, p = list; p; q = p, p = p->next)
1825 		if (f(p->data, d) >= 0)
1826 			break;
1827 	// insert between q and p; if !q insert at head
1828 	if (q)
1829 		q->next = n;
1830 	else
1831 		list = n;
1832 	n->next = p;
1833 	return list;
1834 }
1835 
1836 /*
1837  * Every element of the list points to things which need
1838  * to be free()'d. This method frees the list's contents
1839  */
sdp_list_free(sdp_list_t * list,sdp_free_func_t f)1840 void sdp_list_free(sdp_list_t *list, sdp_free_func_t f)
1841 {
1842 	sdp_list_t *next;
1843 	while (list) {
1844 		next = list->next;
1845 		if (f)
1846 			f(list->data);
1847 		free(list);
1848 		list = next;
1849 	}
1850 }
1851 
__find_port(sdp_data_t * seq,int proto)1852 static inline int __find_port(sdp_data_t *seq, int proto)
1853 {
1854 	if (!seq || !seq->next)
1855 		return 0;
1856 
1857 	if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) {
1858 		seq = seq->next;
1859 		switch (seq->dtd) {
1860 		case SDP_UINT8:
1861 			return seq->val.uint8;
1862 		case SDP_UINT16:
1863 			return seq->val.uint16;
1864 		}
1865 	}
1866 	return 0;
1867 }
1868 
sdp_get_proto_port(const sdp_list_t * list,int proto)1869 int sdp_get_proto_port(const sdp_list_t *list, int proto)
1870 {
1871 	if (proto != L2CAP_UUID && proto != RFCOMM_UUID) {
1872 		errno = EINVAL;
1873 		return -1;
1874 	}
1875 
1876 	for (; list; list = list->next) {
1877 		sdp_list_t *p;
1878 		for (p = list->data; p; p = p->next) {
1879 			sdp_data_t *seq = p->data;
1880 			int port = __find_port(seq, proto);
1881 			if (port)
1882 				return port;
1883 		}
1884 	}
1885 	return 0;
1886 }
1887 
sdp_get_proto_desc(sdp_list_t * list,int proto)1888 sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto)
1889 {
1890 	for (; list; list = list->next) {
1891 		sdp_list_t *p;
1892 		for (p = list->data; p; p = p->next) {
1893 			sdp_data_t *seq = p->data;
1894 			if (SDP_IS_UUID(seq->dtd) &&
1895 					sdp_uuid_to_proto(&seq->val.uuid) == proto)
1896 				return seq->next;
1897 		}
1898 	}
1899 	return NULL;
1900 }
1901 
sdp_get_access_protos(const sdp_record_t * rec,sdp_list_t ** pap)1902 int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
1903 {
1904 	sdp_data_t *pdlist, *curr;
1905 	sdp_list_t *ap = 0;
1906 
1907 	pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
1908 	if (pdlist == NULL) {
1909 		errno = ENODATA;
1910 		return -1;
1911 	}
1912 	SDPDBG("AP type : 0%x\n", pdlist->dtd);
1913 
1914 	for (; pdlist; pdlist = pdlist->next) {
1915 		sdp_list_t *pds = 0;
1916 		for (curr = pdlist->val.dataseq; curr; curr = curr->next)
1917 			pds = sdp_list_append(pds, curr->val.dataseq);
1918 		ap = sdp_list_append(ap, pds);
1919 	}
1920 	*pap = ap;
1921 	return 0;
1922 }
1923 
sdp_get_add_access_protos(const sdp_record_t * rec,sdp_list_t ** pap)1924 int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
1925 {
1926 	sdp_data_t *pdlist, *curr;
1927 	sdp_list_t *ap = 0;
1928 
1929 	pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
1930 	if (pdlist == NULL) {
1931 		errno = ENODATA;
1932 		return -1;
1933 	}
1934 	SDPDBG("AP type : 0%x\n", pdlist->dtd);
1935 
1936 	pdlist = pdlist->val.dataseq;
1937 
1938 	for (; pdlist; pdlist = pdlist->next) {
1939 		sdp_list_t *pds = 0;
1940 		for (curr = pdlist->val.dataseq; curr; curr = curr->next)
1941 			pds = sdp_list_append(pds, curr->val.dataseq);
1942 		ap = sdp_list_append(ap, pds);
1943 	}
1944 	*pap = ap;
1945 	return 0;
1946 }
1947 
sdp_get_uuidseq_attr(const sdp_record_t * rec,uint16_t attr,sdp_list_t ** seqp)1948 int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr,
1949 							sdp_list_t **seqp)
1950 {
1951 	sdp_data_t *sdpdata = sdp_data_get(rec, attr);
1952 
1953 	*seqp = NULL;
1954 	if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) {
1955 		sdp_data_t *d;
1956 		for (d = sdpdata->val.dataseq; d; d = d->next) {
1957 			uuid_t *u;
1958 			if (d->dtd < SDP_UUID16 || d->dtd > SDP_UUID128) {
1959 				errno = EINVAL;
1960 				goto fail;
1961 			}
1962 
1963 			u = malloc(sizeof(uuid_t));
1964 			if (!u)
1965 				goto fail;
1966 
1967 			memset(u, 0, sizeof(uuid_t));
1968 			*u = d->val.uuid;
1969 			*seqp = sdp_list_append(*seqp, u);
1970 		}
1971 		return 0;
1972 	}
1973 fail:
1974 	sdp_list_free(*seqp, free);
1975 	*seqp = NULL;
1976 	return -1;
1977 }
1978 
sdp_set_uuidseq_attr(sdp_record_t * rec,uint16_t aid,sdp_list_t * seq)1979 int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq)
1980 {
1981 	int status = 0, i, len;
1982 	void **dtds, **values;
1983 	uint8_t uuid16 = SDP_UUID16;
1984 	uint8_t uuid32 = SDP_UUID32;
1985 	uint8_t uuid128 = SDP_UUID128;
1986 	sdp_list_t *p;
1987 
1988 	len = sdp_list_len(seq);
1989 	if (!seq || len == 0)
1990 		return -1;
1991 	dtds = malloc(len * sizeof(void *));
1992 	if (!dtds)
1993 		return -1;
1994 
1995 	values = malloc(len * sizeof(void *));
1996 	if (!values) {
1997 		free(dtds);
1998 		return -1;
1999 	}
2000 
2001 	for (p = seq, i = 0; i < len; i++, p = p->next) {
2002 		uuid_t *uuid = p->data;
2003 		if (uuid)
2004 			switch (uuid->type) {
2005 			case SDP_UUID16:
2006 				dtds[i] = &uuid16;
2007 				values[i] = &uuid->value.uuid16;
2008 				break;
2009 			case SDP_UUID32:
2010 				dtds[i] = &uuid32;
2011 				values[i] = &uuid->value.uuid32;
2012 				break;
2013 			case SDP_UUID128:
2014 				dtds[i] = &uuid128;
2015 				values[i] = &uuid->value.uuid128;
2016 				break;
2017 			default:
2018 				status = -1;
2019 				break;
2020 			}
2021 		else {
2022 			status = -1;
2023 			break;
2024 		}
2025 	}
2026 	if (status == 0) {
2027 		sdp_data_t *data = sdp_seq_alloc(dtds, values, len);
2028 		sdp_attr_replace(rec, aid, data);
2029 		sdp_pattern_add_uuidseq(rec, seq);
2030 	}
2031 	free(dtds);
2032 	free(values);
2033 	return status;
2034 }
2035 
sdp_get_lang_attr(const sdp_record_t * rec,sdp_list_t ** langSeq)2036 int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq)
2037 {
2038 	sdp_lang_attr_t *lang;
2039 	sdp_data_t *sdpdata, *curr_data;
2040 
2041 	*langSeq = NULL;
2042 	sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST);
2043 	if (sdpdata == NULL) {
2044 		errno = ENODATA;
2045 		return -1;
2046 	}
2047 	curr_data = sdpdata->val.dataseq;
2048 	while (curr_data) {
2049 		sdp_data_t *pCode = curr_data;
2050 		sdp_data_t *pEncoding = pCode->next;
2051 		sdp_data_t *pOffset = pEncoding->next;
2052 		if (pEncoding && pOffset) {
2053 			lang = malloc(sizeof(sdp_lang_attr_t));
2054 			if (!lang) {
2055 				sdp_list_free(*langSeq, free);
2056 				*langSeq = NULL;
2057 				return -1;
2058 			}
2059 			lang->code_ISO639 = pCode->val.uint16;
2060 			lang->encoding = pEncoding->val.uint16;
2061 			lang->base_offset = pOffset->val.uint16;
2062 			SDPDBG("code_ISO639 :  0x%02x\n", lang->code_ISO639);
2063 			SDPDBG("encoding :     0x%02x\n", lang->encoding);
2064 			SDPDBG("base_offfset : 0x%02x\n", lang->base_offset);
2065 			*langSeq = sdp_list_append(*langSeq, lang);
2066 		}
2067 		curr_data = pOffset->next;
2068 	}
2069 	return 0;
2070 }
2071 
sdp_get_profile_descs(const sdp_record_t * rec,sdp_list_t ** profDescSeq)2072 int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
2073 {
2074 	sdp_profile_desc_t *profDesc;
2075 	sdp_data_t *sdpdata, *seq;
2076 
2077 	*profDescSeq = NULL;
2078 	sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST);
2079 	if (!sdpdata || !sdpdata->val.dataseq) {
2080 		errno = ENODATA;
2081 		return -1;
2082 	}
2083 	for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) {
2084 		uuid_t *uuid = NULL;
2085 		uint16_t version = 0x100;
2086 
2087 		if (SDP_IS_UUID(seq->dtd)) {
2088 			uuid = &seq->val.uuid;
2089 		} else {
2090 			sdp_data_t *puuid = seq->val.dataseq;
2091 			sdp_data_t *pVnum = seq->val.dataseq->next;
2092 			if (puuid && pVnum) {
2093 				uuid = &puuid->val.uuid;
2094 				version = pVnum->val.uint16;
2095 			}
2096 		}
2097 
2098 		if (uuid != NULL) {
2099 			profDesc = malloc(sizeof(sdp_profile_desc_t));
2100 			if (!profDesc) {
2101 				sdp_list_free(*profDescSeq, free);
2102 				*profDescSeq = NULL;
2103 				return -1;
2104 			}
2105 			profDesc->uuid = *uuid;
2106 			profDesc->version = version;
2107 #ifdef SDP_DEBUG
2108 			sdp_uuid_print(&profDesc->uuid);
2109 			SDPDBG("Vnum : 0x%04x\n", profDesc->version);
2110 #endif
2111 			*profDescSeq = sdp_list_append(*profDescSeq, profDesc);
2112 		}
2113 	}
2114 	return 0;
2115 }
2116 
sdp_get_server_ver(const sdp_record_t * rec,sdp_list_t ** u16)2117 int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16)
2118 {
2119 	sdp_data_t *d, *curr;
2120 
2121 	*u16 = NULL;
2122 	d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST);
2123 	if (d == NULL) {
2124 		errno = ENODATA;
2125 		return -1;
2126 	}
2127 	for (curr = d->val.dataseq; curr; curr = curr->next)
2128 		*u16 = sdp_list_append(*u16, &curr->val.uint16);
2129 	return 0;
2130 }
2131 
2132 /* flexible extraction of basic attributes - Jean II */
2133 /* How do we expect caller to extract predefined data sequences? */
sdp_get_int_attr(const sdp_record_t * rec,uint16_t attrid,int * value)2134 int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value)
2135 {
2136 	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);
2137 
2138 	if (sdpdata)
2139 		/* Verify that it is what the caller expects */
2140 		if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 ||
2141 		sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 ||
2142 		sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 ||
2143 		sdpdata->dtd == SDP_INT32) {
2144 			*value = sdpdata->val.uint32;
2145 			return 0;
2146 		}
2147 	errno = EINVAL;
2148 	return -1;
2149 }
2150 
sdp_get_string_attr(const sdp_record_t * rec,uint16_t attrid,char * value,int valuelen)2151 int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value,
2152 								int valuelen)
2153 {
2154 	sdp_data_t *sdpdata = sdp_data_get(rec, attrid);
2155 	if (sdpdata)
2156 		/* Verify that it is what the caller expects */
2157 		if (sdpdata->dtd == SDP_TEXT_STR8 ||
2158 				sdpdata->dtd == SDP_TEXT_STR16 ||
2159 				sdpdata->dtd == SDP_TEXT_STR32)
2160 			if ((int) strlen(sdpdata->val.str) < valuelen) {
2161 				strcpy(value, sdpdata->val.str);
2162 				return 0;
2163 			}
2164 	errno = EINVAL;
2165 	return -1;
2166 }
2167 
2168 #define get_basic_attr(attrID, pAttrValue, fieldName)		\
2169 	sdp_data_t *data = sdp_data_get(rec, attrID);		\
2170 	if (data) {						\
2171 		*pAttrValue = data->val.fieldName;		\
2172 		return 0;					\
2173 	}							\
2174 	errno = EINVAL;						\
2175 	return -1;
2176 
sdp_get_service_id(const sdp_record_t * rec,uuid_t * uuid)2177 int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid)
2178 {
2179 	get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid);
2180 }
2181 
sdp_get_group_id(const sdp_record_t * rec,uuid_t * uuid)2182 int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid)
2183 {
2184 	get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid);
2185 }
2186 
sdp_get_record_state(const sdp_record_t * rec,uint32_t * svcRecState)2187 int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState)
2188 {
2189 	get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32);
2190 }
2191 
sdp_get_service_avail(const sdp_record_t * rec,uint8_t * svcAvail)2192 int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail)
2193 {
2194 	get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8);
2195 }
2196 
sdp_get_service_ttl(const sdp_record_t * rec,uint32_t * svcTTLInfo)2197 int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo)
2198 {
2199 	get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32);
2200 }
2201 
sdp_get_database_state(const sdp_record_t * rec,uint32_t * svcDBState)2202 int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState)
2203 {
2204 	get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32);
2205 }
2206 
2207 /*
2208  * NOTE that none of the setXXX() functions below will
2209  * actually update the SDP server, unless the
2210  * {register, update}sdp_record_t() function is invoked.
2211  */
2212 
sdp_attr_add_new(sdp_record_t * rec,uint16_t attr,uint8_t dtd,const void * value)2213 int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd,
2214 							const void *value)
2215 {
2216 	sdp_data_t *d = sdp_data_alloc(dtd, value);
2217 	if (d) {
2218 		sdp_attr_replace(rec, attr, d);
2219 		return 0;
2220 	}
2221 	return -1;
2222 }
2223 
sdp_attr_add_new_with_length(sdp_record_t * rec,uint16_t attr,uint8_t dtd,const void * value,uint32_t len)2224 static int sdp_attr_add_new_with_length(sdp_record_t *rec,
2225 	uint16_t attr, uint8_t dtd, const void *value, uint32_t len)
2226 {
2227 	sdp_data_t *d;
2228 
2229 	d = sdp_data_alloc_with_length(dtd, value, len);
2230 	if (!d)
2231 		return -1;
2232 
2233 	sdp_attr_replace(rec, attr, d);
2234 
2235 	return 0;
2236 }
2237 
2238 /*
2239  * Set the information attributes of the service
2240  * pointed to by rec. The attributes are
2241  * service name, description and provider name
2242  */
sdp_set_info_attr(sdp_record_t * rec,const char * name,const char * prov,const char * desc)2243 void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov,
2244 							const char *desc)
2245 {
2246 	if (name)
2247 		sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY,
2248 							SDP_TEXT_STR8, name);
2249 	if (prov)
2250 		sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY,
2251 							SDP_TEXT_STR8, prov);
2252 	if (desc)
2253 		sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY,
2254 							SDP_TEXT_STR8, desc);
2255 }
2256 
access_proto_to_dataseq(sdp_record_t * rec,sdp_list_t * proto)2257 static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto)
2258 {
2259 	sdp_data_t *seq = NULL;
2260 	void *dtds[10], *values[10];
2261 	void **seqDTDs, **seqs;
2262 	int i, seqlen;
2263 	sdp_list_t *p;
2264 
2265 	seqlen = sdp_list_len(proto);
2266 	seqDTDs = malloc(seqlen * sizeof(void *));
2267 	if (!seqDTDs)
2268 		return NULL;
2269 
2270 	seqs = malloc(seqlen * sizeof(void *));
2271 	if (!seqs) {
2272 		free(seqDTDs);
2273 		return NULL;
2274 	}
2275 
2276 	for (i = 0, p = proto; p; p = p->next, i++) {
2277 		sdp_list_t *elt = p->data;
2278 		sdp_data_t *s;
2279 		uuid_t *uuid = NULL;
2280 		unsigned int pslen = 0;
2281 		for (; elt && pslen < ARRAY_SIZE(dtds); elt = elt->next, pslen++) {
2282 			sdp_data_t *d = elt->data;
2283 			dtds[pslen] = &d->dtd;
2284 			switch (d->dtd) {
2285 			case SDP_UUID16:
2286 				uuid = (uuid_t *) d;
2287 				values[pslen] = &uuid->value.uuid16;
2288 				break;
2289 			case SDP_UUID32:
2290 				uuid = (uuid_t *) d;
2291 				values[pslen] = &uuid->value.uuid32;
2292 				break;
2293 			case SDP_UUID128:
2294 				uuid = (uuid_t *) d;
2295 				values[pslen] = &uuid->value.uuid128;
2296 				break;
2297 			case SDP_UINT8:
2298 				values[pslen] = &d->val.uint8;
2299 				break;
2300 			case SDP_UINT16:
2301 				values[pslen] = &d->val.uint16;
2302 				break;
2303 			case SDP_SEQ8:
2304 			case SDP_SEQ16:
2305 			case SDP_SEQ32:
2306 				values[pslen] = d;
2307 				break;
2308 			/* FIXME: more */
2309 			}
2310 		}
2311 		s = sdp_seq_alloc(dtds, values, pslen);
2312 		if (s) {
2313 			seqDTDs[i] = &s->dtd;
2314 			seqs[i] = s;
2315 			if (uuid)
2316 				sdp_pattern_add_uuid(rec, uuid);
2317 		}
2318 	}
2319 	seq = sdp_seq_alloc(seqDTDs, seqs, seqlen);
2320 	free(seqDTDs);
2321 	free(seqs);
2322 	return seq;
2323 }
2324 
2325 /*
2326  * sets the access protocols of the service specified
2327  * to the value specified in "access_proto"
2328  *
2329  * Note that if there are alternate mechanisms by
2330  * which the service is accessed, then they should
2331  * be specified as sequences
2332  *
2333  * Using a value of NULL for accessProtocols has
2334  * effect of removing this attribute (if previously set)
2335  *
2336  * This function replaces the existing sdp_access_proto_t
2337  * structure (if any) with the new one specified.
2338  *
2339  * returns 0 if successful or -1 if there is a failure.
2340  */
sdp_set_access_protos(sdp_record_t * rec,const sdp_list_t * ap)2341 int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *ap)
2342 {
2343 	const sdp_list_t *p;
2344 	sdp_data_t *protos = NULL;
2345 
2346 	for (p = ap; p; p = p->next) {
2347 		sdp_data_t *seq = access_proto_to_dataseq(rec, p->data);
2348 		protos = sdp_seq_append(protos, seq);
2349 	}
2350 
2351 	sdp_attr_add(rec, SDP_ATTR_PROTO_DESC_LIST, protos);
2352 
2353 	return 0;
2354 }
2355 
sdp_set_add_access_protos(sdp_record_t * rec,const sdp_list_t * ap)2356 int sdp_set_add_access_protos(sdp_record_t *rec, const sdp_list_t *ap)
2357 {
2358 	const sdp_list_t *p;
2359 	sdp_data_t *protos = NULL;
2360 
2361 	for (p = ap; p; p = p->next) {
2362 		sdp_data_t *seq = access_proto_to_dataseq(rec, p->data);
2363 		protos = sdp_seq_append(protos, seq);
2364 	}
2365 
2366 	sdp_attr_add(rec, SDP_ATTR_ADD_PROTO_DESC_LIST,
2367 			protos ? sdp_data_alloc(SDP_SEQ8, protos) : NULL);
2368 
2369 	return 0;
2370 }
2371 
2372 /*
2373  * set the "LanguageBase" attributes of the service record
2374  * record to the value specified in "langAttrList".
2375  *
2376  * "langAttrList" is a linked list of "sdp_lang_attr_t"
2377  * objects, one for each language in which user visible
2378  * attributes are present in the service record.
2379  *
2380  * Using a value of NULL for langAttrList has
2381  * effect of removing this attribute (if previously set)
2382  *
2383  * This function replaces the exisiting sdp_lang_attr_t
2384  * structure (if any) with the new one specified.
2385  *
2386  * returns 0 if successful or -1 if there is a failure.
2387  */
sdp_set_lang_attr(sdp_record_t * rec,const sdp_list_t * seq)2388 int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *seq)
2389 {
2390 	uint8_t uint16 = SDP_UINT16;
2391 	int status = 0, i = 0, seqlen = sdp_list_len(seq);
2392 	void **dtds, **values;
2393 	const sdp_list_t *p;
2394 
2395 	dtds = malloc(3 * seqlen * sizeof(void *));
2396 	if (!dtds)
2397 		return -1;
2398 
2399 	values = malloc(3 * seqlen * sizeof(void *));
2400 	if (!values) {
2401 		free(dtds);
2402 		return -1;
2403 	}
2404 
2405 	for (p = seq; p; p = p->next) {
2406 		sdp_lang_attr_t *lang = p->data;
2407 		if (!lang) {
2408 			status = -1;
2409 			break;
2410 		}
2411 		dtds[i] = &uint16;
2412 		values[i] = &lang->code_ISO639;
2413 		i++;
2414 		dtds[i] = &uint16;
2415 		values[i] = &lang->encoding;
2416 		i++;
2417 		dtds[i] = &uint16;
2418 		values[i] = &lang->base_offset;
2419 		i++;
2420 	}
2421 	if (status == 0) {
2422 		sdp_data_t *seq = sdp_seq_alloc(dtds, values, 3 * seqlen);
2423 		sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, seq);
2424 	}
2425 	free(dtds);
2426 	free(values);
2427 	return status;
2428 }
2429 
2430 /*
2431  * set the "ServiceID" attribute of the service.
2432  *
2433  * This is the UUID of the service.
2434  *
2435  * returns 0 if successful or -1 if there is a failure.
2436  */
sdp_set_service_id(sdp_record_t * rec,uuid_t uuid)2437 void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid)
2438 {
2439 	switch (uuid.type) {
2440 	case SDP_UUID16:
2441 		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID16,
2442 							&uuid.value.uuid16);
2443 		break;
2444 	case SDP_UUID32:
2445 		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID32,
2446 							&uuid.value.uuid32);
2447 		break;
2448 	case SDP_UUID128:
2449 		sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID128,
2450 							&uuid.value.uuid128);
2451 		break;
2452 	}
2453 	sdp_pattern_add_uuid(rec, &uuid);
2454 }
2455 
2456 /*
2457  * set the GroupID attribute of the service record defining a group.
2458  *
2459  * This is the UUID of the group.
2460  *
2461  * returns 0 if successful or -1 if there is a failure.
2462  */
sdp_set_group_id(sdp_record_t * rec,uuid_t uuid)2463 void sdp_set_group_id(sdp_record_t *rec, uuid_t uuid)
2464 {
2465 	switch (uuid.type) {
2466 	case SDP_UUID16:
2467 		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID16,
2468 							&uuid.value.uuid16);
2469 		break;
2470 	case SDP_UUID32:
2471 		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID32,
2472 							&uuid.value.uuid32);
2473 		break;
2474 	case SDP_UUID128:
2475 		sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID128,
2476 							&uuid.value.uuid128);
2477 		break;
2478 	}
2479 	sdp_pattern_add_uuid(rec, &uuid);
2480 }
2481 
2482 /*
2483  * set the ProfileDescriptorList attribute of the service record
2484  * pointed to by record to the value specified in "profileDesc".
2485  *
2486  * Each element in the list is an object of type
2487  * sdp_profile_desc_t which is a definition of the
2488  * Bluetooth profile that this service conforms to.
2489  *
2490  * Using a value of NULL for profileDesc has
2491  * effect of removing this attribute (if previously set)
2492  *
2493  * This function replaces the exisiting ProfileDescriptorList
2494  * structure (if any) with the new one specified.
2495  *
2496  * returns 0 if successful or -1 if there is a failure.
2497  */
sdp_set_profile_descs(sdp_record_t * rec,const sdp_list_t * profiles)2498 int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles)
2499 {
2500 	int status = 0;
2501 	uint8_t uuid16 = SDP_UUID16;
2502 	uint8_t uuid32 = SDP_UUID32;
2503 	uint8_t uuid128 = SDP_UUID128;
2504 	uint8_t uint16 = SDP_UINT16;
2505 	int i = 0, seqlen = sdp_list_len(profiles);
2506 	void **seqDTDs, **seqs;
2507 	const sdp_list_t *p;
2508 
2509 	seqDTDs = malloc(seqlen * sizeof(void *));
2510 	if (!seqDTDs)
2511 		return -1;
2512 
2513 	seqs = malloc(seqlen * sizeof(void *));
2514 	if (!seqs) {
2515 		free(seqDTDs);
2516 		return -1;
2517 	}
2518 
2519 	for (p = profiles; p; p = p->next) {
2520 		sdp_data_t *seq;
2521 		void *dtds[2], *values[2];
2522 		sdp_profile_desc_t *profile = p->data;
2523 		if (!profile) {
2524 			status = -1;
2525 			break;
2526 		}
2527 		switch (profile->uuid.type) {
2528 		case SDP_UUID16:
2529 			dtds[0] = &uuid16;
2530 			values[0] = &profile->uuid.value.uuid16;
2531 			break;
2532 		case SDP_UUID32:
2533 			dtds[0] = &uuid32;
2534 			values[0] = &profile->uuid.value.uuid32;
2535 			break;
2536 		case SDP_UUID128:
2537 			dtds[0] = &uuid128;
2538 			values[0] = &profile->uuid.value.uuid128;
2539 			break;
2540 		default:
2541 			status = -1;
2542 			break;
2543 		}
2544 		dtds[1] = &uint16;
2545 		values[1] = &profile->version;
2546 		seq = sdp_seq_alloc(dtds, values, 2);
2547 		if (seq) {
2548 			seqDTDs[i] = &seq->dtd;
2549 			seqs[i] = seq;
2550 			sdp_pattern_add_uuid(rec, &profile->uuid);
2551 		}
2552 		i++;
2553 	}
2554 	if (status == 0) {
2555 		sdp_data_t *pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen);
2556 		sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq);
2557 	}
2558 	free(seqDTDs);
2559 	free(seqs);
2560 	return status;
2561 }
2562 
2563 /*
2564  * sets various URL attributes of the service
2565  * pointed to by record. The URL include
2566  *
2567  * client: a URL to the client's
2568  *   platform specific (WinCE, PalmOS) executable
2569  *   code that can be used to access this service.
2570  *
2571  * doc: a URL pointing to service documentation
2572  *
2573  * icon: a URL to an icon that can be used to represent
2574  *   this service.
2575  *
2576  * Note that you need to pass NULL for any URLs
2577  * that you don't want to set or remove
2578  */
sdp_set_url_attr(sdp_record_t * rec,const char * client,const char * doc,const char * icon)2579 void sdp_set_url_attr(sdp_record_t *rec, const char *client, const char *doc,
2580 							const char *icon)
2581 {
2582 	sdp_attr_add_new(rec, SDP_ATTR_CLNT_EXEC_URL, SDP_URL_STR8, client);
2583 	sdp_attr_add_new(rec, SDP_ATTR_DOC_URL, SDP_URL_STR8, doc);
2584 	sdp_attr_add_new(rec, SDP_ATTR_ICON_URL, SDP_URL_STR8, icon);
2585 }
2586 
sdp_uuid16_create(uuid_t * u,uint16_t val)2587 uuid_t *sdp_uuid16_create(uuid_t *u, uint16_t val)
2588 {
2589 	memset(u, 0, sizeof(uuid_t));
2590 	u->type = SDP_UUID16;
2591 	u->value.uuid16 = val;
2592 	return u;
2593 }
2594 
sdp_uuid32_create(uuid_t * u,uint32_t val)2595 uuid_t *sdp_uuid32_create(uuid_t *u, uint32_t val)
2596 {
2597 	memset(u, 0, sizeof(uuid_t));
2598 	u->type = SDP_UUID32;
2599 	u->value.uuid32 = val;
2600 	return u;
2601 }
2602 
sdp_uuid128_create(uuid_t * u,const void * val)2603 uuid_t *sdp_uuid128_create(uuid_t *u, const void *val)
2604 {
2605 	memset(u, 0, sizeof(uuid_t));
2606 	u->type = SDP_UUID128;
2607 	memcpy(&u->value.uuid128, val, sizeof(uint128_t));
2608 	return u;
2609 }
2610 
2611 /*
2612  * UUID comparison function
2613  * returns 0 if uuidValue1 == uuidValue2 else -1
2614  */
sdp_uuid_cmp(const void * p1,const void * p2)2615 int sdp_uuid_cmp(const void *p1, const void *p2)
2616 {
2617 	uuid_t *u1 = sdp_uuid_to_uuid128(p1);
2618 	uuid_t *u2 = sdp_uuid_to_uuid128(p2);
2619 	int ret;
2620 
2621 	ret = sdp_uuid128_cmp(u1, u2);
2622 
2623 	bt_free(u1);
2624 	bt_free(u2);
2625 
2626 	return ret;
2627 }
2628 
2629 /*
2630  * UUID comparison function
2631  * returns 0 if uuidValue1 == uuidValue2 else -1
2632  */
sdp_uuid16_cmp(const void * p1,const void * p2)2633 int sdp_uuid16_cmp(const void *p1, const void *p2)
2634 {
2635 	const uuid_t *u1 = p1;
2636 	const uuid_t *u2 = p2;
2637 	return memcmp(&u1->value.uuid16, &u2->value.uuid16, sizeof(uint16_t));
2638 }
2639 
2640 /*
2641  * UUID comparison function
2642  * returns 0 if uuidValue1 == uuidValue2 else -1
2643  */
sdp_uuid128_cmp(const void * p1,const void * p2)2644 int sdp_uuid128_cmp(const void *p1, const void *p2)
2645 {
2646 	const uuid_t *u1 = p1;
2647 	const uuid_t *u2 = p2;
2648 	return memcmp(&u1->value.uuid128, &u2->value.uuid128, sizeof(uint128_t));
2649 }
2650 
2651 /*
2652  * 128 to 16 bit and 32 to 16 bit UUID conversion functions
2653  * yet to be implemented. Note that the input is in NBO in
2654  * both 32 and 128 bit UUIDs and conversion is needed
2655  */
sdp_uuid16_to_uuid128(uuid_t * uuid128,const uuid_t * uuid16)2656 void sdp_uuid16_to_uuid128(uuid_t *uuid128, const uuid_t *uuid16)
2657 {
2658 	/*
2659 	 * We have a 16 bit value, which needs to be added to
2660 	 * bytes 3 and 4 (at indices 2 and 3) of the Bluetooth base
2661 	 */
2662 	unsigned short data1;
2663 
2664 	/* allocate a 128bit UUID and init to the Bluetooth base UUID */
2665 	uuid128->value.uuid128 = bluetooth_base_uuid;
2666 	uuid128->type = SDP_UUID128;
2667 
2668 	/* extract bytes 2 and 3 of 128bit BT base UUID */
2669 	memcpy(&data1, &bluetooth_base_uuid.data[2], 2);
2670 
2671 	/* add the given UUID (16 bits) */
2672 	data1 += htons(uuid16->value.uuid16);
2673 
2674 	/* set bytes 2 and 3 of the 128 bit value */
2675 	memcpy(&uuid128->value.uuid128.data[2], &data1, 2);
2676 }
2677 
sdp_uuid32_to_uuid128(uuid_t * uuid128,const uuid_t * uuid32)2678 void sdp_uuid32_to_uuid128(uuid_t *uuid128, const uuid_t *uuid32)
2679 {
2680 	/*
2681 	 * We have a 32 bit value, which needs to be added to
2682 	 * bytes 1->4 (at indices 0 thru 3) of the Bluetooth base
2683 	 */
2684 	unsigned int data0;
2685 
2686 	/* allocate a 128bit UUID and init to the Bluetooth base UUID */
2687 	uuid128->value.uuid128 = bluetooth_base_uuid;
2688 	uuid128->type = SDP_UUID128;
2689 
2690 	/* extract first 4 bytes */
2691 	memcpy(&data0, &bluetooth_base_uuid.data[0], 4);
2692 
2693 	/* add the given UUID (32bits) */
2694 	data0 += htonl(uuid32->value.uuid32);
2695 
2696 	/* set the 4 bytes of the 128 bit value */
2697 	memcpy(&uuid128->value.uuid128.data[0], &data0, 4);
2698 }
2699 
sdp_uuid_to_uuid128(const uuid_t * uuid)2700 uuid_t *sdp_uuid_to_uuid128(const uuid_t *uuid)
2701 {
2702 	uuid_t *uuid128 = bt_malloc(sizeof(uuid_t));
2703 
2704 	if (!uuid128)
2705 		return NULL;
2706 
2707 	memset(uuid128, 0, sizeof(uuid_t));
2708 	switch (uuid->type) {
2709 	case SDP_UUID128:
2710 		*uuid128 = *uuid;
2711 		break;
2712 	case SDP_UUID32:
2713 		sdp_uuid32_to_uuid128(uuid128, uuid);
2714 		break;
2715 	case SDP_UUID16:
2716 		sdp_uuid16_to_uuid128(uuid128, uuid);
2717 		break;
2718 	}
2719 	return uuid128;
2720 }
2721 
2722 /*
2723  * converts a 128-bit uuid to a 16/32-bit one if possible
2724  * returns true if uuid contains a 16/32-bit UUID at exit
2725  */
sdp_uuid128_to_uuid(uuid_t * uuid)2726 int sdp_uuid128_to_uuid(uuid_t *uuid)
2727 {
2728 	uint128_t *b = &bluetooth_base_uuid;
2729 	uint128_t *u = &uuid->value.uuid128;
2730 	uint32_t data;
2731 	unsigned int i;
2732 
2733 	if (uuid->type != SDP_UUID128)
2734 		return 1;
2735 
2736 	for (i = 4; i < sizeof(b->data); i++)
2737 		if (b->data[i] != u->data[i])
2738 			return 0;
2739 
2740 	memcpy(&data, u->data, 4);
2741 	data = htonl(data);
2742 	if (data <= 0xffff) {
2743 		uuid->type = SDP_UUID16;
2744 		uuid->value.uuid16 = (uint16_t) data;
2745 	} else {
2746 		uuid->type = SDP_UUID32;
2747 		uuid->value.uuid32 = data;
2748 	}
2749 	return 1;
2750 }
2751 
2752 /*
2753  * convert a UUID to the 16-bit short-form
2754  */
sdp_uuid_to_proto(uuid_t * uuid)2755 int sdp_uuid_to_proto(uuid_t *uuid)
2756 {
2757 	uuid_t u = *uuid;
2758 	if (sdp_uuid128_to_uuid(&u)) {
2759 		switch (u.type) {
2760 		case SDP_UUID16:
2761 			return u.value.uuid16;
2762 		case SDP_UUID32:
2763 			return u.value.uuid32;
2764 		}
2765 	}
2766 	return 0;
2767 }
2768 
2769 /*
2770  * This function appends data to the PDU buffer "dst" from source "src".
2771  * The data length is also computed and set.
2772  * Should the PDU length exceed 2^8, then sequence type is
2773  * set accordingly and the data is memmove()'d.
2774  */
sdp_append_to_buf(sdp_buf_t * dst,uint8_t * data,uint32_t len)2775 void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len)
2776 {
2777 	uint8_t *p = dst->data;
2778 	uint8_t dtd = *p;
2779 
2780 	SDPDBG("Append src size: %d\n", len);
2781 	SDPDBG("Append dst size: %d\n", dst->data_size);
2782 	SDPDBG("Dst buffer size: %d\n", dst->buf_size);
2783 	if (dst->data_size == 0 && dtd == 0) {
2784 		/* create initial sequence */
2785 		*p = SDP_SEQ8;
2786 		p += sizeof(uint8_t);
2787 		dst->data_size += sizeof(uint8_t);
2788 		/* reserve space for sequence size */
2789 		p += sizeof(uint8_t);
2790 		dst->data_size += sizeof(uint8_t);
2791 	}
2792 
2793 	memcpy(dst->data + dst->data_size, data, len);
2794 	dst->data_size += len;
2795 
2796 	dtd = *(uint8_t *) dst->data;
2797 	if (dst->data_size > UCHAR_MAX && dtd == SDP_SEQ8) {
2798 		short offset = sizeof(uint8_t) + sizeof(uint8_t);
2799 		memmove(dst->data + offset + 1, dst->data + offset,
2800 						dst->data_size - offset);
2801 		p = dst->data;
2802 		*p = SDP_SEQ16;
2803 		p += sizeof(uint8_t);
2804 		dst->data_size += 1;
2805 	}
2806 	p = dst->data;
2807 	dtd = *(uint8_t *) p;
2808 	p += sizeof(uint8_t);
2809 	switch (dtd) {
2810 	case SDP_SEQ8:
2811 		*(uint8_t *) p = dst->data_size - sizeof(uint8_t) - sizeof(uint8_t);
2812 		break;
2813 	case SDP_SEQ16:
2814 		bt_put_unaligned(htons(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t)), (uint16_t *) p);
2815 		break;
2816 	case SDP_SEQ32:
2817 		bt_put_unaligned(htonl(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t)), (uint32_t *) p);
2818 		break;
2819 	}
2820 }
2821 
sdp_append_to_pdu(sdp_buf_t * pdu,sdp_data_t * d)2822 void sdp_append_to_pdu(sdp_buf_t *pdu, sdp_data_t *d)
2823 {
2824 	sdp_buf_t append;
2825 
2826 	memset(&append, 0, sizeof(sdp_buf_t));
2827 	sdp_gen_buffer(&append, d);
2828 	append.data = malloc(append.buf_size);
2829 	if (!append.data)
2830 		return;
2831 
2832 	sdp_set_attrid(&append, d->attrId);
2833 	sdp_gen_pdu(&append, d);
2834 	sdp_append_to_buf(pdu, append.data, append.data_size);
2835 	free(append.data);
2836 }
2837 
2838 /*
2839  * Registers an sdp record.
2840  *
2841  * It is incorrect to call this method on a record that
2842  * has been already registered with the server.
2843  *
2844  * Returns zero on success, otherwise -1 (and sets errno).
2845  */
sdp_device_record_register_binary(sdp_session_t * session,bdaddr_t * device,uint8_t * data,uint32_t size,uint8_t flags,uint32_t * handle)2846 int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, uint8_t *data, uint32_t size, uint8_t flags, uint32_t *handle)
2847 {
2848 	uint8_t *req, *rsp, *p;
2849 	uint32_t reqsize, rspsize;
2850 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2851 	int status;
2852 
2853 	SDPDBG("");
2854 
2855 	if (!session->local) {
2856 		errno = EREMOTE;
2857 		return -1;
2858 	}
2859 	req = malloc(SDP_REQ_BUFFER_SIZE);
2860 	rsp = malloc(SDP_RSP_BUFFER_SIZE);
2861 	if (req == NULL || rsp == NULL) {
2862 		status = -1;
2863 		errno = ENOMEM;
2864 		goto end;
2865 	}
2866 
2867 	reqhdr = (sdp_pdu_hdr_t *)req;
2868 	reqhdr->pdu_id = SDP_SVC_REGISTER_REQ;
2869 	reqhdr->tid    = htons(sdp_gen_tid(session));
2870 	reqsize = sizeof(sdp_pdu_hdr_t) + 1;
2871 	p = req + sizeof(sdp_pdu_hdr_t);
2872 
2873 	if (bacmp(device, BDADDR_ANY)) {
2874 		*p++ = flags | SDP_DEVICE_RECORD;
2875 		bacpy((bdaddr_t *) p, device);
2876 		p += sizeof(bdaddr_t);
2877 		reqsize += sizeof(bdaddr_t);
2878 	} else
2879 		*p++ = flags;
2880 
2881 	memcpy(p, data, size);
2882 	reqsize += size;
2883 	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
2884 
2885 	status = sdp_send_req_w4_rsp(session, req, rsp, reqsize, &rspsize);
2886 	if (status < 0)
2887 		goto end;
2888 
2889 	if (rspsize < sizeof(sdp_pdu_hdr_t)) {
2890 		SDPERR("Unexpected end of packet");
2891 		errno = EPROTO;
2892 		status = -1;
2893 		goto end;
2894 	}
2895 
2896 	rsphdr = (sdp_pdu_hdr_t *) rsp;
2897 	p = rsp + sizeof(sdp_pdu_hdr_t);
2898 
2899 	if (rsphdr->pdu_id == SDP_ERROR_RSP) {
2900 		/* Invalid service record */
2901 		errno = EINVAL;
2902 		status = -1;
2903 	} else if (rsphdr->pdu_id != SDP_SVC_REGISTER_RSP) {
2904 		errno = EPROTO;
2905 		status = -1;
2906 	} else {
2907 		if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint32_t)) {
2908 			SDPERR("Unexpected end of packet");
2909 			errno = EPROTO;
2910 			status = -1;
2911 			goto end;
2912 		}
2913 		if (handle)
2914 			*handle  = ntohl(bt_get_unaligned((uint32_t *) p));
2915 	}
2916 
2917 end:
2918 	free(req);
2919 	free(rsp);
2920 
2921 	return status;
2922 }
2923 
sdp_device_record_register(sdp_session_t * session,bdaddr_t * device,sdp_record_t * rec,uint8_t flags)2924 int sdp_device_record_register(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec, uint8_t flags)
2925 {
2926 	sdp_buf_t pdu;
2927 	uint32_t handle;
2928 	int err;
2929 
2930 	SDPDBG("");
2931 
2932 	if (rec->handle && rec->handle != 0xffffffff) {
2933 		uint32_t handle = rec->handle;
2934 		sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle);
2935 		sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data);
2936 	}
2937 
2938 	if (sdp_gen_record_pdu(rec, &pdu) < 0) {
2939 		errno = ENOMEM;
2940 		return -1;
2941 	}
2942 
2943 	err = sdp_device_record_register_binary(session, device,
2944 				pdu.data, pdu.data_size, flags, &handle);
2945 
2946 	free(pdu.data);
2947 
2948 	if (err == 0) {
2949 		sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle);
2950 		rec->handle = handle;
2951 		sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data);
2952 	}
2953 
2954 	return err;
2955 }
2956 
sdp_record_register(sdp_session_t * session,sdp_record_t * rec,uint8_t flags)2957 int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags)
2958 {
2959 	return sdp_device_record_register(session, BDADDR_ANY, rec, flags);
2960 }
2961 
2962 /*
2963  * unregister a service record
2964  */
sdp_device_record_unregister_binary(sdp_session_t * session,bdaddr_t * device,uint32_t handle)2965 int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle)
2966 {
2967 	uint8_t *reqbuf, *rspbuf, *p;
2968 	uint32_t reqsize = 0, rspsize = 0;
2969 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
2970 	int status;
2971 
2972 	SDPDBG("");
2973 
2974 	if (handle == SDP_SERVER_RECORD_HANDLE) {
2975 		errno = EINVAL;
2976 		return -1;
2977 	}
2978 
2979 	if (!session->local) {
2980 		errno = EREMOTE;
2981 		return -1;
2982 	}
2983 
2984 	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
2985 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
2986 	if (!reqbuf || !rspbuf) {
2987 		errno = ENOMEM;
2988 		status = -1;
2989 		goto end;
2990 	}
2991 	reqhdr = (sdp_pdu_hdr_t *) reqbuf;
2992 	reqhdr->pdu_id = SDP_SVC_REMOVE_REQ;
2993 	reqhdr->tid    = htons(sdp_gen_tid(session));
2994 
2995 	p = reqbuf + sizeof(sdp_pdu_hdr_t);
2996 	reqsize = sizeof(sdp_pdu_hdr_t);
2997 	bt_put_unaligned(htonl(handle), (uint32_t *) p);
2998 	reqsize += sizeof(uint32_t);
2999 
3000 	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
3001 	status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
3002 	if (status < 0)
3003 		goto end;
3004 
3005 	if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) {
3006 		SDPERR("Unexpected end of packet");
3007 		errno = EPROTO;
3008 		status = -1;
3009 		goto end;
3010 	}
3011 
3012 	rsphdr = (sdp_pdu_hdr_t *) rspbuf;
3013 	p = rspbuf + sizeof(sdp_pdu_hdr_t);
3014 	status = bt_get_unaligned((uint16_t *) p);
3015 
3016 	if (rsphdr->pdu_id == SDP_ERROR_RSP) {
3017 		/* For this case the status always is invalid record handle */
3018 		errno = EINVAL;
3019 		status = -1;
3020 	} else if (rsphdr->pdu_id != SDP_SVC_REMOVE_RSP) {
3021 		errno = EPROTO;
3022 		status = -1;
3023 	}
3024 end:
3025 	free(reqbuf);
3026 	free(rspbuf);
3027 
3028 	return status;
3029 }
3030 
sdp_device_record_unregister(sdp_session_t * session,bdaddr_t * device,sdp_record_t * rec)3031 int sdp_device_record_unregister(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec)
3032 {
3033 	int err;
3034 
3035 	err = sdp_device_record_unregister_binary(session, device, rec->handle);
3036 	if (err == 0)
3037 		sdp_record_free(rec);
3038 
3039 	return err;
3040 }
3041 
sdp_record_unregister(sdp_session_t * session,sdp_record_t * rec)3042 int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec)
3043 {
3044 	return sdp_device_record_unregister(session, BDADDR_ANY, rec);
3045 }
3046 
3047 /*
3048  * modify an existing service record
3049  */
sdp_device_record_update_binary(sdp_session_t * session,bdaddr_t * device,uint32_t handle,uint8_t * data,uint32_t size)3050 int sdp_device_record_update_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle, uint8_t *data, uint32_t size)
3051 {
3052 	return -1;
3053 }
3054 
sdp_device_record_update(sdp_session_t * session,bdaddr_t * device,const sdp_record_t * rec)3055 int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp_record_t *rec)
3056 {
3057 	uint8_t *reqbuf, *rspbuf, *p;
3058 	uint32_t reqsize, rspsize;
3059 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
3060 	uint32_t handle;
3061 	sdp_buf_t pdu;
3062 	int status;
3063 
3064 	SDPDBG("");
3065 
3066 	handle = rec->handle;
3067 
3068 	if (handle == SDP_SERVER_RECORD_HANDLE) {
3069 		errno = EINVAL;
3070 		return -1;
3071 	}
3072 	if (!session->local) {
3073 		errno = EREMOTE;
3074 		return -1;
3075 	}
3076 	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3077 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
3078 	if (!reqbuf || !rspbuf) {
3079 		errno = ENOMEM;
3080 		status = -1;
3081 		goto end;
3082 	}
3083 	reqhdr = (sdp_pdu_hdr_t *) reqbuf;
3084 	reqhdr->pdu_id = SDP_SVC_UPDATE_REQ;
3085 	reqhdr->tid    = htons(sdp_gen_tid(session));
3086 
3087 	p = reqbuf + sizeof(sdp_pdu_hdr_t);
3088 	reqsize = sizeof(sdp_pdu_hdr_t);
3089 
3090 	bt_put_unaligned(htonl(handle), (uint32_t *) p);
3091 	reqsize += sizeof(uint32_t);
3092 	p += sizeof(uint32_t);
3093 
3094 	if (sdp_gen_record_pdu(rec, &pdu) < 0) {
3095 		errno = ENOMEM;
3096 		status = -1;
3097 		goto end;
3098 	}
3099 	memcpy(p, pdu.data, pdu.data_size);
3100 	reqsize += pdu.data_size;
3101 	free(pdu.data);
3102 
3103 	reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
3104 	status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
3105 	if (status < 0)
3106 		goto end;
3107 
3108 	if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) {
3109 		SDPERR("Unexpected end of packet");
3110 		errno = EPROTO;
3111 		status = -1;
3112 		goto end;
3113 	}
3114 
3115 	SDPDBG("Send req status : %d\n", status);
3116 
3117 	rsphdr = (sdp_pdu_hdr_t *) rspbuf;
3118 	p = rspbuf + sizeof(sdp_pdu_hdr_t);
3119 	status = bt_get_unaligned((uint16_t *) p);
3120 
3121 	if (rsphdr->pdu_id == SDP_ERROR_RSP) {
3122 		/* The status can be invalid sintax or invalid record handle */
3123 		errno = EINVAL;
3124 		status = -1;
3125 	} else if (rsphdr->pdu_id != SDP_SVC_UPDATE_RSP) {
3126 		errno = EPROTO;
3127 		status = -1;
3128 	}
3129 end:
3130 	free(reqbuf);
3131 	free(rspbuf);
3132 	return status;
3133 }
3134 
sdp_record_update(sdp_session_t * session,const sdp_record_t * rec)3135 int sdp_record_update(sdp_session_t *session, const sdp_record_t *rec)
3136 {
3137 	return sdp_device_record_update(session, BDADDR_ANY, rec);
3138 }
3139 
sdp_record_alloc()3140 sdp_record_t *sdp_record_alloc()
3141 {
3142 	sdp_record_t *rec = malloc(sizeof(sdp_record_t));
3143 
3144 	if (!rec)
3145 		return NULL;
3146 
3147 	memset(rec, 0, sizeof(sdp_record_t));
3148 	rec->handle = 0xffffffff;
3149 	return rec;
3150 }
3151 
3152 /*
3153  * Free the contents of a service record
3154  */
sdp_record_free(sdp_record_t * rec)3155 void sdp_record_free(sdp_record_t *rec)
3156 {
3157 	sdp_list_free(rec->attrlist, (sdp_free_func_t) sdp_data_free);
3158 	sdp_list_free(rec->pattern, free);
3159 	free(rec);
3160 }
3161 
sdp_pattern_add_uuid(sdp_record_t * rec,uuid_t * uuid)3162 void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid)
3163 {
3164 	uuid_t *uuid128 = sdp_uuid_to_uuid128(uuid);
3165 
3166 	SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern));
3167 	SDPDBG("Trying to add : 0x%lx\n", (unsigned long) uuid128);
3168 
3169 	if (sdp_list_find(rec->pattern, uuid128, sdp_uuid128_cmp) == NULL)
3170 		rec->pattern = sdp_list_insert_sorted(rec->pattern, uuid128, sdp_uuid128_cmp);
3171 	else
3172 		bt_free(uuid128);
3173 
3174 	SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern));
3175 }
3176 
sdp_pattern_add_uuidseq(sdp_record_t * rec,sdp_list_t * seq)3177 void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq)
3178 {
3179 	for (; seq; seq = seq->next) {
3180 		uuid_t *uuid = (uuid_t *)seq->data;
3181 		sdp_pattern_add_uuid(rec, uuid);
3182 	}
3183 }
3184 
3185 /*
3186  * Extract a sequence of service record handles from a PDU buffer
3187  * and add the entries to a sdp_list_t. Note that the service record
3188  * handles are not in "data element sequence" form, but just like
3189  * an array of service handles
3190  */
extract_record_handle_seq(uint8_t * pdu,int bufsize,sdp_list_t ** seq,int count,unsigned int * scanned)3191 static void extract_record_handle_seq(uint8_t *pdu, int bufsize, sdp_list_t **seq, int count, unsigned int *scanned)
3192 {
3193 	sdp_list_t *pSeq = *seq;
3194 	uint8_t *pdata = pdu;
3195 	int n;
3196 
3197 	for (n = 0; n < count; n++) {
3198 		uint32_t *pSvcRec;
3199 		if (bufsize < (int) sizeof(uint32_t)) {
3200 			SDPERR("Unexpected end of packet");
3201 			break;
3202 		}
3203 		pSvcRec = malloc(sizeof(uint32_t));
3204 		if (!pSvcRec)
3205 			break;
3206 		*pSvcRec = ntohl(bt_get_unaligned((uint32_t *) pdata));
3207 		pSeq = sdp_list_append(pSeq, pSvcRec);
3208 		pdata += sizeof(uint32_t);
3209 		*scanned += sizeof(uint32_t);
3210 		bufsize -= sizeof(uint32_t);
3211 	}
3212 	*seq = pSeq;
3213 }
3214 /*
3215  * Generate the attribute sequence pdu form
3216  * from sdp_list_t elements. Return length of attr seq
3217  */
gen_dataseq_pdu(uint8_t * dst,const sdp_list_t * seq,uint8_t dtd)3218 static int gen_dataseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dtd)
3219 {
3220 	sdp_data_t *dataseq;
3221 	void **types, **values;
3222 	sdp_buf_t buf;
3223 	int i, seqlen = sdp_list_len(seq);
3224 
3225 	// Fill up the value and the dtd arrays
3226 	SDPDBG("");
3227 
3228 	SDPDBG("Seq length : %d\n", seqlen);
3229 
3230 	types = malloc(seqlen * sizeof(void *));
3231 	if (!types)
3232 		return -ENOMEM;
3233 
3234 	values = malloc(seqlen * sizeof(void *));
3235 	if (!values) {
3236 		free(types);
3237 		return -ENOMEM;
3238 	}
3239 
3240 	for (i = 0; i < seqlen; i++) {
3241 		void *data = seq->data;
3242 		types[i] = &dtd;
3243 		if (SDP_IS_UUID(dtd))
3244 			data = &((uuid_t *)data)->value;
3245 		values[i] = data;
3246 		seq = seq->next;
3247 	}
3248 
3249 	dataseq = sdp_seq_alloc(types, values, seqlen);
3250 	if (!dataseq) {
3251 		free(types);
3252 		free(values);
3253 		return -ENOMEM;
3254 	}
3255 
3256 	memset(&buf, 0, sizeof(sdp_buf_t));
3257 	sdp_gen_buffer(&buf, dataseq);
3258 	buf.data = malloc(buf.buf_size);
3259 
3260 	if (!buf.data) {
3261 		sdp_data_free(dataseq);
3262 		free(types);
3263 		free(values);
3264 		return -ENOMEM;
3265 	}
3266 
3267 	SDPDBG("Data Seq : 0x%p\n", seq);
3268 	seqlen = sdp_gen_pdu(&buf, dataseq);
3269 	SDPDBG("Copying : %d\n", buf.data_size);
3270 	memcpy(dst, buf.data, buf.data_size);
3271 
3272 	sdp_data_free(dataseq);
3273 
3274 	free(types);
3275 	free(values);
3276 	free(buf.data);
3277 	return seqlen;
3278 }
3279 
gen_searchseq_pdu(uint8_t * dst,const sdp_list_t * seq)3280 static int gen_searchseq_pdu(uint8_t *dst, const sdp_list_t *seq)
3281 {
3282 	uuid_t *uuid = seq->data;
3283 	return gen_dataseq_pdu(dst, seq, uuid->type);
3284 }
3285 
gen_attridseq_pdu(uint8_t * dst,const sdp_list_t * seq,uint8_t dataType)3286 static int gen_attridseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dataType)
3287 {
3288 	return gen_dataseq_pdu(dst, seq, dataType);
3289 }
3290 
3291 typedef struct {
3292 	uint8_t length;
3293 	unsigned char data[16];
3294 } __attribute__ ((packed)) sdp_cstate_t;
3295 
copy_cstate(uint8_t * pdata,int pdata_len,const sdp_cstate_t * cstate)3296 static int copy_cstate(uint8_t *pdata, int pdata_len, const sdp_cstate_t *cstate)
3297 {
3298 	if (cstate) {
3299 		uint8_t len = cstate->length;
3300 		if (len >= pdata_len) {
3301 			SDPERR("Continuation state size exceeds internal buffer");
3302 			len = pdata_len - 1;
3303 		}
3304 		*pdata++ = len;
3305 		memcpy(pdata, cstate->data, len);
3306 		return len + 1;
3307 	}
3308 	*pdata = 0;
3309 	return 1;
3310 }
3311 
3312 /*
3313  * This is a service search request.
3314  *
3315  * INPUT :
3316  *
3317  *   sdp_list_t *search
3318  *     Singly linked list containing elements of the search
3319  *     pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16)
3320  *     of the service to be searched
3321  *
3322  *   uint16_t max_rec_num
3323  *      A 16 bit integer which tells the service, the maximum
3324  *      entries that the client can handle in the response. The
3325  *      server is obliged not to return > max_rec_num entries
3326  *
3327  * OUTPUT :
3328  *
3329  *   int return value
3330  *     0:
3331  *       The request completed successfully. This does not
3332  *       mean the requested services were found
3333  *     -1:
3334  *       On any failure and sets errno
3335  *
3336  *   sdp_list_t **rsp_list
3337  *     This variable is set on a successful return if there are
3338  *     non-zero service handles. It is a singly linked list of
3339  *     service record handles (uint16_t)
3340  */
sdp_service_search_req(sdp_session_t * session,const sdp_list_t * search,uint16_t max_rec_num,sdp_list_t ** rsp)3341 int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
3342 			uint16_t max_rec_num, sdp_list_t **rsp)
3343 {
3344 	int status = 0;
3345 	uint32_t reqsize = 0, _reqsize;
3346 	uint32_t rspsize = 0, rsplen;
3347 	int seqlen = 0;
3348 	int total_rec_count, rec_count;
3349 	unsigned scanned, pdata_len;
3350 	uint8_t *pdata, *_pdata;
3351 	uint8_t *reqbuf, *rspbuf;
3352 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
3353 	sdp_cstate_t *cstate = NULL;
3354 
3355 	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3356 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
3357 	if (!reqbuf || !rspbuf) {
3358 		errno = ENOMEM;
3359 		status = -1;
3360 		goto end;
3361 	}
3362 	reqhdr = (sdp_pdu_hdr_t *) reqbuf;
3363 	reqhdr->pdu_id = SDP_SVC_SEARCH_REQ;
3364 	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
3365 	reqsize = sizeof(sdp_pdu_hdr_t);
3366 
3367 	// add service class IDs for search
3368 	seqlen = gen_searchseq_pdu(pdata, search);
3369 
3370 	SDPDBG("Data seq added : %d\n", seqlen);
3371 
3372 	// set the length and increment the pointer
3373 	reqsize += seqlen;
3374 	pdata += seqlen;
3375 
3376 	// specify the maximum svc rec count that client expects
3377 	bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata);
3378 	reqsize += sizeof(uint16_t);
3379 	pdata += sizeof(uint16_t);
3380 
3381 	_reqsize = reqsize;
3382 	_pdata   = pdata;
3383 	*rsp = NULL;
3384 
3385 	do {
3386 		// Add continuation state or NULL (first time)
3387 		reqsize = _reqsize + copy_cstate(_pdata,
3388 					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
3389 
3390 		// Set the request header's param length
3391 		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
3392 
3393 		reqhdr->tid  = htons(sdp_gen_tid(session));
3394 		/*
3395 		 * Send the request, wait for response and if
3396 		 * no error, set the appropriate values and return
3397 		 */
3398 		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
3399 		if (status < 0)
3400 			goto end;
3401 
3402 		if (rspsize < sizeof(sdp_pdu_hdr_t)) {
3403 			SDPERR("Unexpected end of packet");
3404 			status = -1;
3405 			goto end;
3406 		}
3407 
3408 		rsphdr = (sdp_pdu_hdr_t *) rspbuf;
3409 		rsplen = ntohs(rsphdr->plen);
3410 
3411 		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
3412 			SDPDBG("Status : 0x%x\n", rsphdr->pdu_id);
3413 			status = -1;
3414 			goto end;
3415 		}
3416 		scanned = 0;
3417 		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
3418 		pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
3419 
3420 		if (pdata_len < sizeof(uint16_t) + sizeof(uint16_t)) {
3421 			SDPERR("Unexpected end of packet");
3422 			status = -1;
3423 			goto end;
3424 		}
3425 
3426 		// net service record match count
3427 		total_rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
3428 		pdata += sizeof(uint16_t);
3429 		scanned += sizeof(uint16_t);
3430 		pdata_len -= sizeof(uint16_t);
3431 		rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
3432 		pdata += sizeof(uint16_t);
3433 		scanned += sizeof(uint16_t);
3434 		pdata_len -= sizeof(uint16_t);
3435 
3436 		SDPDBG("Total svc count: %d\n", total_rec_count);
3437 		SDPDBG("Current svc count: %d\n", rec_count);
3438 		SDPDBG("ResponseLength: %d\n", rsplen);
3439 
3440 		if (!rec_count) {
3441 			status = -1;
3442 			goto end;
3443 		}
3444 		extract_record_handle_seq(pdata, pdata_len, rsp, rec_count, &scanned);
3445 		SDPDBG("BytesScanned : %d\n", scanned);
3446 
3447 		if (rsplen > scanned) {
3448 			uint8_t cstate_len;
3449 
3450 			if (rspsize < sizeof(sdp_pdu_hdr_t) + scanned + sizeof(uint8_t)) {
3451 				SDPERR("Unexpected end of packet: continuation state data missing");
3452 				status = -1;
3453 				goto end;
3454 			}
3455 
3456 			pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned;
3457 			cstate_len = *(uint8_t *) pdata;
3458 			if (cstate_len > 0) {
3459 				cstate = (sdp_cstate_t *)pdata;
3460 				SDPDBG("Cont state length: %d\n", cstate_len);
3461 			} else
3462 				cstate = NULL;
3463 		}
3464 	} while (cstate);
3465 
3466 end:
3467 	free(reqbuf);
3468 	free(rspbuf);
3469 
3470 	return status;
3471 }
3472 
3473 /*
3474  * This is a service attribute request.
3475  *
3476  * INPUT :
3477  *
3478  *   uint32_t handle
3479  *     The handle of the service for which the attribute(s) are
3480  *     requested
3481  *
3482  *   sdp_attrreq_type_t reqtype
3483  *     Attribute identifiers are 16 bit unsigned integers specified
3484  *     in one of 2 ways described below :
3485  *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
3486  *        They are the actual attribute identifiers in ascending order
3487  *
3488  *     SDP_ATTR_REQ_RANGE - 32bit identifier range
3489  *        The high-order 16bits is the start of range
3490  *        the low-order 16bits are the end of range
3491  *        0x0000 to 0xFFFF gets all attributes
3492  *
3493  *   sdp_list_t *attrid
3494  *     Singly linked list containing attribute identifiers desired.
3495  *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
3496  *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
3497  *
3498  * OUTPUT :
3499  *   return sdp_record_t *
3500  *     0:
3501  *       On any error and sets errno
3502  *     !0:
3503  *	 The service record
3504  */
sdp_service_attr_req(sdp_session_t * session,uint32_t handle,sdp_attrreq_type_t reqtype,const sdp_list_t * attrids)3505 sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
3506 			sdp_attrreq_type_t reqtype, const sdp_list_t *attrids)
3507 {
3508 	uint32_t reqsize = 0, _reqsize;
3509 	uint32_t rspsize = 0, rsp_count;
3510 	int attr_list_len = 0;
3511 	int seqlen = 0;
3512 	unsigned int pdata_len;
3513 	uint8_t *pdata, *_pdata;
3514 	uint8_t *reqbuf, *rspbuf;
3515 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
3516 	sdp_cstate_t *cstate = NULL;
3517 	uint8_t cstate_len = 0;
3518 	sdp_buf_t rsp_concat_buf;
3519 	sdp_record_t *rec = 0;
3520 
3521 	if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) {
3522 		errno = EINVAL;
3523 		return NULL;
3524 	}
3525 
3526 	memset(&rsp_concat_buf, 0, sizeof(sdp_buf_t));
3527 
3528 	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3529 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
3530 	if (!reqbuf || !rspbuf) {
3531 		errno = ENOMEM;
3532 		goto end;
3533 	}
3534 	reqhdr = (sdp_pdu_hdr_t *) reqbuf;
3535 	reqhdr->pdu_id = SDP_SVC_ATTR_REQ;
3536 
3537 	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
3538 	reqsize = sizeof(sdp_pdu_hdr_t);
3539 
3540 	// add the service record handle
3541 	bt_put_unaligned(htonl(handle), (uint32_t *) pdata);
3542 	reqsize += sizeof(uint32_t);
3543 	pdata += sizeof(uint32_t);
3544 
3545 	// specify the response limit
3546 	bt_put_unaligned(htons(65535), (uint16_t *) pdata);
3547 	reqsize += sizeof(uint16_t);
3548 	pdata += sizeof(uint16_t);
3549 
3550 	// get attr seq PDU form
3551 	seqlen = gen_attridseq_pdu(pdata, attrids,
3552 		reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32);
3553 	if (seqlen == -1) {
3554 		errno = EINVAL;
3555 		goto end;
3556 	}
3557 	pdata += seqlen;
3558 	reqsize += seqlen;
3559 	SDPDBG("Attr list length : %d\n", seqlen);
3560 
3561 	// save before Continuation State
3562 	_pdata = pdata;
3563 	_reqsize = reqsize;
3564 
3565 	do {
3566 		int status;
3567 
3568 		// add NULL continuation state
3569 		reqsize = _reqsize + copy_cstate(_pdata,
3570 					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
3571 
3572 		// set the request header's param length
3573 		reqhdr->tid  = htons(sdp_gen_tid(session));
3574 		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
3575 
3576 		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
3577 		if (status < 0)
3578 			goto end;
3579 
3580 		if (rspsize < sizeof(sdp_pdu_hdr_t)) {
3581 			SDPERR("Unexpected end of packet");
3582 			goto end;
3583 		}
3584 
3585 		rsphdr = (sdp_pdu_hdr_t *) rspbuf;
3586 		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
3587 			SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id);
3588 			goto end;
3589 		}
3590 		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
3591 		pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
3592 
3593 		if (pdata_len < sizeof(uint16_t)) {
3594 			SDPERR("Unexpected end of packet");
3595 			goto end;
3596 		}
3597 
3598 		rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
3599 		attr_list_len += rsp_count;
3600 		pdata += sizeof(uint16_t);
3601 		pdata_len -= sizeof(uint16_t);
3602 
3603 		// if continuation state set need to re-issue request before parsing
3604 		if (pdata_len < rsp_count + sizeof(uint8_t)) {
3605 			SDPERR("Unexpected end of packet: continuation state data missing");
3606 			goto end;
3607 		}
3608 		cstate_len = *(uint8_t *) (pdata + rsp_count);
3609 
3610 		SDPDBG("Response id : %d\n", rsphdr->pdu_id);
3611 		SDPDBG("Attrlist byte count : %d\n", rsp_count);
3612 		SDPDBG("sdp_cstate_t length : %d\n", cstate_len);
3613 
3614 		/*
3615 		 * a split response: concatenate intermediate responses
3616 		 * and the last one (which has cstate_len == 0)
3617 		 */
3618 		if (cstate_len > 0 || rsp_concat_buf.data_size != 0) {
3619 			uint8_t *targetPtr = NULL;
3620 
3621 			cstate = cstate_len > 0 ? (sdp_cstate_t *) (pdata + rsp_count) : 0;
3622 
3623 			// build concatenated response buffer
3624 			rsp_concat_buf.data = realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count);
3625 			rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count;
3626 			targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size;
3627 			memcpy(targetPtr, pdata, rsp_count);
3628 			rsp_concat_buf.data_size += rsp_count;
3629 		}
3630 	} while (cstate);
3631 
3632 	if (attr_list_len > 0) {
3633 		int scanned = 0;
3634 		if (rsp_concat_buf.data_size != 0) {
3635 			pdata = rsp_concat_buf.data;
3636 			pdata_len = rsp_concat_buf.data_size;
3637 		}
3638 		rec = sdp_extract_pdu(pdata, pdata_len, &scanned);
3639 	}
3640 
3641 end:
3642 	free(reqbuf);
3643 	free(rsp_concat_buf.data);
3644 	free(rspbuf);
3645 	return rec;
3646 }
3647 
3648 /*
3649  * SDP transaction structure for asynchronous search
3650  */
3651 struct sdp_transaction {
3652 	sdp_callback_t *cb;	/* called when the transaction finishes */
3653 	void *udata;		/* client user data */
3654 	uint8_t *reqbuf;	/* pointer to request PDU */
3655 	sdp_buf_t rsp_concat_buf;
3656 	uint32_t reqsize;	/* without cstate */
3657 	int err;		/* ZERO if success or the errno if failed */
3658 };
3659 
3660 /*
3661  * Creates a new sdp session for asynchronous search
3662  * INPUT:
3663  *  int sk
3664  *     non-blocking L2CAP socket
3665  *
3666  * RETURN:
3667  *  sdp_session_t *
3668  *  NULL - On memory allocation failure
3669  */
sdp_create(int sk,uint32_t flags)3670 sdp_session_t *sdp_create(int sk, uint32_t flags)
3671 {
3672 	sdp_session_t *session;
3673 	struct sdp_transaction *t;
3674 
3675 	session = malloc(sizeof(sdp_session_t));
3676 	if (!session) {
3677 		errno = ENOMEM;
3678 		return NULL;
3679 	}
3680 	memset(session, 0, sizeof(*session));
3681 
3682 	session->flags = flags;
3683 	session->sock = sk;
3684 
3685 	t = malloc(sizeof(struct sdp_transaction));
3686 	if (!t) {
3687 		errno = ENOMEM;
3688 		free(session);
3689 		return NULL;
3690 	}
3691 	memset(t, 0, sizeof(*t));
3692 
3693 	session->priv = t;
3694 
3695 	return session;
3696 }
3697 
3698 /*
3699  * Sets the callback function/user data used to notify the application
3700  * that the asynchronous transaction finished. This function must be
3701  * called before request an asynchronous search.
3702  *
3703  * INPUT:
3704  *  sdp_session_t *session
3705  *	Current sdp session to be handled
3706  *  sdp_callback_t *cb
3707  *      callback to be called when the transaction finishes
3708  *  void *udata
3709  *      user data passed to callback
3710  * RETURN:
3711  * 	 0 - Success
3712  * 	-1 - Failure
3713  */
sdp_set_notify(sdp_session_t * session,sdp_callback_t * func,void * udata)3714 int sdp_set_notify(sdp_session_t *session, sdp_callback_t *func, void *udata)
3715 {
3716 	struct sdp_transaction *t;
3717 
3718 	if (!session || !session->priv)
3719 		return -1;
3720 
3721 	t = session->priv;
3722 	t->cb = func;
3723 	t->udata = udata;
3724 
3725 	return 0;
3726 }
3727 
3728 /*
3729  * This function starts an asynchronous service search request.
3730  * The incomming and outgoing data are stored in the transaction structure
3731  * buffers. When there is incomming data the sdp_process function must be
3732  * called to get the data and handle the continuation state.
3733  *
3734  * INPUT :
3735  *  sdp_session_t *session
3736  *     Current sdp session to be handled
3737  *
3738  *   sdp_list_t *search
3739  *     Singly linked list containing elements of the search
3740  *     pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16)
3741  *     of the service to be searched
3742  *
3743  *   uint16_t max_rec_num
3744  *      A 16 bit integer which tells the service, the maximum
3745  *      entries that the client can handle in the response. The
3746  *      server is obliged not to return > max_rec_num entries
3747  *
3748  * OUTPUT :
3749  *
3750  *   int return value
3751  * 	0  - if the request has been sent properly
3752  * 	-1 - On any failure and sets errno
3753  */
3754 
sdp_service_search_async(sdp_session_t * session,const sdp_list_t * search,uint16_t max_rec_num)3755 int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num)
3756 {
3757 	struct sdp_transaction *t;
3758 	sdp_pdu_hdr_t *reqhdr;
3759 	uint8_t *pdata;
3760 	int cstate_len, seqlen = 0;
3761 
3762 	if (!session || !session->priv)
3763 		return -1;
3764 
3765 	t = session->priv;
3766 
3767 	/* clean possible allocated buffer */
3768 	free(t->rsp_concat_buf.data);
3769 	memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t));
3770 
3771 	if (!t->reqbuf) {
3772 		t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3773 		if (!t->reqbuf) {
3774 			t->err = ENOMEM;
3775 			goto end;
3776 		}
3777 	}
3778 	memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE);
3779 
3780 	reqhdr = (sdp_pdu_hdr_t *) t->reqbuf;
3781 	reqhdr->tid = htons(sdp_gen_tid(session));
3782 	reqhdr->pdu_id = SDP_SVC_SEARCH_REQ;
3783 
3784 	// generate PDU
3785 	pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t);
3786 	t->reqsize = sizeof(sdp_pdu_hdr_t);
3787 
3788 	// add service class IDs for search
3789 	seqlen = gen_searchseq_pdu(pdata, search);
3790 
3791 	SDPDBG("Data seq added : %d\n", seqlen);
3792 
3793 	// now set the length and increment the pointer
3794 	t->reqsize += seqlen;
3795 	pdata += seqlen;
3796 
3797 	bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata);
3798 	t->reqsize += sizeof(uint16_t);
3799 	pdata += sizeof(uint16_t);
3800 
3801 	// set the request header's param length
3802 	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
3803 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
3804 
3805 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
3806 		SDPERR("Error sendind data:%s", strerror(errno));
3807 		t->err = errno;
3808 		goto end;
3809 	}
3810 
3811 	return 0;
3812 end:
3813 
3814 	free(t->reqbuf);
3815 	t->reqbuf = NULL;
3816 
3817 	return -1;
3818 }
3819 
3820 /*
3821  * This function starts an asynchronous service attribute request.
3822  * The incomming and outgoing data are stored in the transaction structure
3823  * buffers. When there is incomming data the sdp_process function must be
3824  * called to get the data and handle the continuation state.
3825  *
3826  * INPUT :
3827  *  sdp_session_t *session
3828  *	Current sdp session to be handled
3829  *
3830  *   uint32_t handle
3831  *     The handle of the service for which the attribute(s) are
3832  *     requested
3833  *
3834  *   sdp_attrreq_type_t reqtype
3835  *     Attribute identifiers are 16 bit unsigned integers specified
3836  *     in one of 2 ways described below :
3837  *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
3838  *        They are the actual attribute identifiers in ascending order
3839  *
3840  *     SDP_ATTR_REQ_RANGE - 32bit identifier range
3841  *        The high-order 16bits is the start of range
3842  *        the low-order 16bits are the end of range
3843  *        0x0000 to 0xFFFF gets all attributes
3844  *
3845  *   sdp_list_t *attrid_list
3846  *     Singly linked list containing attribute identifiers desired.
3847  *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
3848  *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
3849  *
3850  * OUTPUT :
3851  *   int return value
3852  * 	 0 - if the request has been sent properly
3853  * 	-1 - On any failure and sets errno
3854  */
3855 
sdp_service_attr_async(sdp_session_t * session,uint32_t handle,sdp_attrreq_type_t reqtype,const sdp_list_t * attrid_list)3856 int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list)
3857 {
3858 	struct sdp_transaction *t;
3859 	sdp_pdu_hdr_t *reqhdr;
3860 	uint8_t *pdata;
3861 	int cstate_len, seqlen = 0;
3862 
3863 	if (!session || !session->priv)
3864 		return -1;
3865 
3866 	t = session->priv;
3867 
3868 	/* clean possible allocated buffer */
3869 	free(t->rsp_concat_buf.data);
3870 	memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t));
3871 
3872 	if (!t->reqbuf) {
3873 		t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3874 		if (!t->reqbuf) {
3875 			t->err = ENOMEM;
3876 			goto end;
3877 		}
3878 	}
3879 	memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE);
3880 
3881 	reqhdr = (sdp_pdu_hdr_t *) t->reqbuf;
3882 	reqhdr->tid = htons(sdp_gen_tid(session));
3883 	reqhdr->pdu_id = SDP_SVC_ATTR_REQ;
3884 
3885 	// generate PDU
3886 	pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t);
3887 	t->reqsize = sizeof(sdp_pdu_hdr_t);
3888 
3889 	// add the service record handle
3890 	bt_put_unaligned(htonl(handle), (uint32_t *) pdata);
3891 	t->reqsize += sizeof(uint32_t);
3892 	pdata += sizeof(uint32_t);
3893 
3894 	// specify the response limit
3895 	bt_put_unaligned(htons(65535), (uint16_t *) pdata);
3896 	t->reqsize += sizeof(uint16_t);
3897 	pdata += sizeof(uint16_t);
3898 
3899 	// get attr seq PDU form
3900 	seqlen = gen_attridseq_pdu(pdata, attrid_list,
3901 			reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32);
3902 	if (seqlen == -1) {
3903 		t->err = EINVAL;
3904 		goto end;
3905 	}
3906 
3907 	// now set the length and increment the pointer
3908 	t->reqsize += seqlen;
3909 	pdata += seqlen;
3910 	SDPDBG("Attr list length : %d\n", seqlen);
3911 
3912 	// set the request header's param length
3913 	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
3914 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
3915 
3916 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
3917 		SDPERR("Error sendind data:%s", strerror(errno));
3918 		t->err = errno;
3919 		goto end;
3920 	}
3921 
3922 	return 0;
3923 end:
3924 
3925 	free(t->reqbuf);
3926 	t->reqbuf = NULL;
3927 
3928 	return -1;
3929 }
3930 
3931 /*
3932  * This function starts an asynchronous service search attributes.
3933  * It is a service search request combined with attribute request. The incomming
3934  * and outgoing data are stored in the transaction structure buffers. When there
3935  * is incomming data the sdp_process function must be called to get the data
3936  * and handle the continuation state.
3937  *
3938  * INPUT:
3939  *  sdp_session_t *session
3940  *	Current sdp session to be handled
3941  *
3942  *   sdp_list_t *search
3943  *     Singly linked list containing elements of the search
3944  *     pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16)
3945  *     of the service to be searched
3946  *
3947  *   AttributeSpecification attrSpec
3948  *     Attribute identifiers are 16 bit unsigned integers specified
3949  *     in one of 2 ways described below :
3950  *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
3951  *        They are the actual attribute identifiers in ascending order
3952  *
3953  *     SDP_ATTR_REQ_RANGE - 32bit identifier range
3954  *        The high-order 16bits is the start of range
3955  *        the low-order 16bits are the end of range
3956  *        0x0000 to 0xFFFF gets all attributes
3957  *
3958  *   sdp_list_t *attrid_list
3959  *     Singly linked list containing attribute identifiers desired.
3960  *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
3961  *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
3962  *
3963 
3964  * RETURN:
3965  * 	 0 - if the request has been sent properly
3966  * 	-1 - On any failure
3967  */
sdp_service_search_attr_async(sdp_session_t * session,const sdp_list_t * search,sdp_attrreq_type_t reqtype,const sdp_list_t * attrid_list)3968 int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list)
3969 {
3970 	struct sdp_transaction *t;
3971 	sdp_pdu_hdr_t *reqhdr;
3972 	uint8_t *pdata;
3973 	int cstate_len, seqlen = 0;
3974 
3975 	if (!session || !session->priv)
3976 		return -1;
3977 
3978 	t = session->priv;
3979 
3980 	/* clean possible allocated buffer */
3981 	free(t->rsp_concat_buf.data);
3982 	memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t));
3983 
3984 	if (!t->reqbuf) {
3985 		t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
3986 		if (!t->reqbuf) {
3987 			t->err = ENOMEM;
3988 			goto end;
3989 		}
3990 	}
3991 	memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE);
3992 
3993 	reqhdr = (sdp_pdu_hdr_t *) t->reqbuf;
3994 	reqhdr->tid = htons(sdp_gen_tid(session));
3995 	reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ;
3996 
3997 	// generate PDU
3998 	pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t);
3999 	t->reqsize = sizeof(sdp_pdu_hdr_t);
4000 
4001 	// add service class IDs for search
4002 	seqlen = gen_searchseq_pdu(pdata, search);
4003 
4004 	SDPDBG("Data seq added : %d\n", seqlen);
4005 
4006 	// now set the length and increment the pointer
4007 	t->reqsize += seqlen;
4008 	pdata += seqlen;
4009 
4010 	bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata);
4011 	t->reqsize += sizeof(uint16_t);
4012 	pdata += sizeof(uint16_t);
4013 
4014 	SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN);
4015 
4016 	// get attr seq PDU form
4017 	seqlen = gen_attridseq_pdu(pdata, attrid_list,
4018 			reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32);
4019 	if (seqlen == -1) {
4020 		t->err = EINVAL;
4021 		goto end;
4022 	}
4023 
4024 	pdata += seqlen;
4025 	SDPDBG("Attr list length : %d\n", seqlen);
4026 	t->reqsize += seqlen;
4027 
4028 	// set the request header's param length
4029 	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
4030 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
4031 
4032 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
4033 		SDPERR("Error sendind data:%s", strerror(errno));
4034 		t->err = errno;
4035 		goto end;
4036 	}
4037 
4038 	return 0;
4039 end:
4040 
4041 	free(t->reqbuf);
4042 	t->reqbuf = NULL;
4043 
4044 	return -1;
4045 }
4046 
4047 /*
4048  * Function used to get the error reason after sdp_callback_t function has been called
4049  * and the status is 0xffff or if sdp_service_{search, attr, search_attr}_async returns -1.
4050  * It indicates that an error NOT related to SDP_ErrorResponse happened. Get errno directly
4051  * is not safe because multiple transactions can be triggered.
4052  * This function must be used with asynchronous sdp functions only.
4053  *
4054  * INPUT:
4055  *  sdp_session_t *session
4056  *	Current sdp session to be handled
4057  * RETURN:
4058  * 	 0 = No error in the current transaction
4059  * 	-1 - if the session is invalid
4060  * 	positive value - the errno value
4061  *
4062  */
sdp_get_error(sdp_session_t * session)4063 int sdp_get_error(sdp_session_t *session)
4064 {
4065 	struct sdp_transaction *t;
4066 
4067 	if (!session || !session->priv) {
4068 		SDPERR("Invalid session");
4069 		return -1;
4070 	}
4071 
4072 	t = session->priv;
4073 
4074 	return t->err;
4075 }
4076 
4077 /*
4078  * Receive the incomming SDP PDU. This function must be called when there is data
4079  * available to be read. On continuation state, the original request (with a new
4080  * transaction ID) and the continuation state data will be appended in the initial PDU.
4081  * If an error happens or the transaction finishes the callback function will be called.
4082  *
4083  * INPUT:
4084  *  sdp_session_t *session
4085  *	Current sdp session to be handled
4086  * RETURN:
4087  * 	0  - if the transaction is on continuation state
4088  * 	-1 - On any failure or the transaction finished
4089  */
sdp_process(sdp_session_t * session)4090 int sdp_process(sdp_session_t *session)
4091 {
4092 	struct sdp_transaction *t;
4093 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
4094 	sdp_cstate_t *pcstate;
4095 	uint8_t *pdata, *rspbuf, *targetPtr;
4096 	int rsp_count, err = -1;
4097 	size_t size = 0;
4098 	int n, plen;
4099 	uint16_t status = 0xffff;
4100 	uint8_t pdu_id = 0x00;
4101 
4102 	if (!session || !session->priv) {
4103 		SDPERR("Invalid session");
4104 		return -1;
4105 	}
4106 
4107 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
4108 	if (!rspbuf) {
4109 		SDPERR("Response buffer alloc failure:%s (%d)",
4110 				strerror(errno), errno);
4111 		return -1;
4112 	}
4113 
4114 	memset(rspbuf, 0, SDP_RSP_BUFFER_SIZE);
4115 
4116 	t = session->priv;
4117 	reqhdr = (sdp_pdu_hdr_t *)t->reqbuf;
4118 	rsphdr = (sdp_pdu_hdr_t *)rspbuf;
4119 
4120 	pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
4121 
4122 	n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE);
4123 	if (n < 0) {
4124 		SDPERR("Read response:%s (%d)", strerror(errno), errno);
4125 		t->err = errno;
4126 		goto end;
4127 	}
4128 
4129 	if (n == 0 || reqhdr->tid != rsphdr->tid ||
4130 		(n != (ntohs(rsphdr->plen) + (int) sizeof(sdp_pdu_hdr_t)))) {
4131 		t->err = EPROTO;
4132 		SDPERR("Protocol error.");
4133 		goto end;
4134 	}
4135 
4136 	pdu_id = rsphdr->pdu_id;
4137 	switch (rsphdr->pdu_id) {
4138 	uint8_t *ssr_pdata;
4139 	uint16_t tsrc, csrc;
4140 	case SDP_SVC_SEARCH_RSP:
4141 		/*
4142 		 * TSRC: Total Service Record Count (2 bytes)
4143 		 * CSRC: Current Service Record Count (2 bytes)
4144 		 */
4145 		ssr_pdata = pdata;
4146 		tsrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata));
4147 		ssr_pdata += sizeof(uint16_t);
4148 		csrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata));
4149 
4150 		/* csrc should never be larger than tsrc */
4151 		if (csrc > tsrc) {
4152 			t->err = EPROTO;
4153 			SDPERR("Protocol error: wrong current service record count value.");
4154 			goto end;
4155 		}
4156 
4157 		SDPDBG("Total svc count: %d\n", tsrc);
4158 		SDPDBG("Current svc count: %d\n", csrc);
4159 
4160 		/* parameter length without continuation state */
4161 		plen = sizeof(tsrc) + sizeof(csrc) + csrc * 4;
4162 
4163 		if (t->rsp_concat_buf.data_size == 0) {
4164 			/* first fragment */
4165 			rsp_count = sizeof(tsrc) + sizeof(csrc) + csrc * 4;
4166 		} else {
4167 			/* point to the first csrc */
4168 			uint16_t *pcsrc = (uint16_t *) (t->rsp_concat_buf.data + 2);
4169 
4170 			/* FIXME: update the interface later. csrc doesn't need be passed to clients */
4171 
4172 			pdata += sizeof(uint16_t); /* point to csrc */
4173 
4174 			/* the first csrc contains the sum of partial csrc responses */
4175 			*pcsrc += bt_get_unaligned((uint16_t *) pdata);
4176 
4177 			pdata += sizeof(uint16_t); /* point to the first handle */
4178 			rsp_count = csrc * 4;
4179 		}
4180 		status = 0x0000;
4181 		break;
4182 	case SDP_SVC_ATTR_RSP:
4183 	case SDP_SVC_SEARCH_ATTR_RSP:
4184 		rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
4185 		SDPDBG("Attrlist byte count : %d\n", rsp_count);
4186 
4187 		/*
4188 		 * Number of bytes in the AttributeLists parameter(without
4189 		 * continuation state) + AttributeListsByteCount field size.
4190 		 */
4191 		plen = sizeof(uint16_t) + rsp_count;
4192 
4193 		pdata += sizeof(uint16_t); // points to attribute list
4194 		status = 0x0000;
4195 		break;
4196 	case SDP_ERROR_RSP:
4197 		status = ntohs(bt_get_unaligned((uint16_t *) pdata));
4198 		size = ntohs(rsphdr->plen);
4199 
4200 		/* error code + error info */
4201 		plen = size;
4202 		goto end;
4203 	default:
4204 		t->err = EPROTO;
4205 		SDPERR("Illegal PDU ID: 0x%x", rsphdr->pdu_id);
4206 		goto end;
4207 	}
4208 
4209 	pcstate = (sdp_cstate_t *) (pdata + rsp_count);
4210 
4211 	SDPDBG("Cstate length : %d\n", pcstate->length);
4212 
4213 	/*
4214 	 * Check out of bound. Continuation state must have at least
4215 	 * 1 byte: ZERO to indicate that it is not a partial response.
4216 	 */
4217 	if ((n - (int) sizeof(sdp_pdu_hdr_t))  != (plen + pcstate->length + 1)) {
4218 		t->err = EPROTO;
4219 		SDPERR("Protocol error: wrong PDU size.");
4220 		status = 0xffff;
4221 		goto end;
4222 	}
4223 
4224 	/*
4225 	 * This is a split response, need to concatenate intermediate
4226 	 * responses and the last one which will have cstate length == 0
4227 	 */
4228 	t->rsp_concat_buf.data = realloc(t->rsp_concat_buf.data, t->rsp_concat_buf.data_size + rsp_count);
4229 	targetPtr = t->rsp_concat_buf.data + t->rsp_concat_buf.data_size;
4230 	t->rsp_concat_buf.buf_size = t->rsp_concat_buf.data_size + rsp_count;
4231 	memcpy(targetPtr, pdata, rsp_count);
4232 	t->rsp_concat_buf.data_size += rsp_count;
4233 
4234 	if (pcstate->length > 0) {
4235 		int reqsize, cstate_len;
4236 
4237 		reqhdr->tid = htons(sdp_gen_tid(session));
4238 
4239 		// add continuation state
4240 		cstate_len = copy_cstate(t->reqbuf + t->reqsize,
4241 				SDP_REQ_BUFFER_SIZE - t->reqsize, pcstate);
4242 
4243 		reqsize = t->reqsize + cstate_len;
4244 
4245 		// set the request header's param length
4246 		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
4247 
4248 		if (sdp_send_req(session, t->reqbuf, reqsize) < 0) {
4249 			SDPERR("Error sendind data:%s(%d)", strerror(errno), errno);
4250 			status = 0xffff;
4251 			t->err = errno;
4252 			goto end;
4253 		}
4254 		err = 0;
4255 	}
4256 
4257 end:
4258 	if (err) {
4259 		if (t->rsp_concat_buf.data_size != 0) {
4260 			pdata = t->rsp_concat_buf.data;
4261 			size = t->rsp_concat_buf.data_size;
4262 		}
4263 		if (t->cb)
4264 			t->cb(pdu_id, status, pdata, size, t->udata);
4265 	}
4266 
4267 	free(rspbuf);
4268 
4269 	return err;
4270 }
4271 
4272 /*
4273  * This is a service search request combined with the service
4274  * attribute request. First a service class match is done and
4275  * for matching service, requested attributes are extracted
4276  *
4277  * INPUT :
4278  *
4279  *   sdp_list_t *search
4280  *     Singly linked list containing elements of the search
4281  *     pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16)
4282  *     of the service to be searched
4283  *
4284  *   AttributeSpecification attrSpec
4285  *     Attribute identifiers are 16 bit unsigned integers specified
4286  *     in one of 2 ways described below :
4287  *     SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
4288  *        They are the actual attribute identifiers in ascending order
4289  *
4290  *     SDP_ATTR_REQ_RANGE - 32bit identifier range
4291  *        The high-order 16bits is the start of range
4292  *        the low-order 16bits are the end of range
4293  *        0x0000 to 0xFFFF gets all attributes
4294  *
4295  *   sdp_list_t *attrids
4296  *     Singly linked list containing attribute identifiers desired.
4297  *     Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
4298  *     or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
4299  *
4300  * OUTPUT :
4301  *   int return value
4302  *     0:
4303  *       The request completed successfully. This does not
4304  *       mean the requested services were found
4305  *     -1:
4306  *       On any error and sets errno
4307  *
4308  *   sdp_list_t **rsp
4309  *     This variable is set on a successful return to point to
4310  *     service(s) found. Each element of this list is of type
4311  *     sdp_record_t* (of the services which matched the search list)
4312  */
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)4313 int 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)
4314 {
4315 	int status = 0;
4316 	uint32_t reqsize = 0, _reqsize;
4317 	uint32_t rspsize = 0;
4318 	int seqlen = 0, attr_list_len = 0;
4319 	int rsp_count = 0, cstate_len = 0;
4320 	unsigned int pdata_len;
4321 	uint8_t *pdata, *_pdata;
4322 	uint8_t *reqbuf, *rspbuf;
4323 	sdp_pdu_hdr_t *reqhdr, *rsphdr;
4324 	uint8_t dataType;
4325 	sdp_list_t *rec_list = NULL;
4326 	sdp_buf_t rsp_concat_buf;
4327 	sdp_cstate_t *cstate = NULL;
4328 
4329 	if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) {
4330 		errno = EINVAL;
4331 		return -1;
4332 	}
4333 
4334 	memset(&rsp_concat_buf, 0, sizeof(sdp_buf_t));
4335 
4336 	reqbuf = malloc(SDP_REQ_BUFFER_SIZE);
4337 	rspbuf = malloc(SDP_RSP_BUFFER_SIZE);
4338 	if (!reqbuf || !rspbuf) {
4339 		errno = ENOMEM;
4340 		status = -1;
4341 		goto end;
4342 	}
4343 
4344 	reqhdr = (sdp_pdu_hdr_t *) reqbuf;
4345 	reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ;
4346 
4347 	// generate PDU
4348 	pdata = reqbuf + sizeof(sdp_pdu_hdr_t);
4349 	reqsize = sizeof(sdp_pdu_hdr_t);
4350 
4351 	// add service class IDs for search
4352 	seqlen = gen_searchseq_pdu(pdata, search);
4353 
4354 	SDPDBG("Data seq added : %d\n", seqlen);
4355 
4356 	/* now set the length and increment the pointer */
4357 	reqsize += seqlen;
4358 	pdata += seqlen;
4359 
4360 	bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata);
4361 	reqsize += sizeof(uint16_t);
4362 	pdata += sizeof(uint16_t);
4363 
4364 	SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN);
4365 
4366 	/* get attr seq PDU form */
4367 	seqlen = gen_attridseq_pdu(pdata, attrids,
4368 		reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32);
4369 	if (seqlen == -1) {
4370 		status = EINVAL;
4371 		goto end;
4372 	}
4373 	pdata += seqlen;
4374 	SDPDBG("Attr list length : %d\n", seqlen);
4375 	reqsize += seqlen;
4376 	*rsp = 0;
4377 
4378 	/* save before Continuation State */
4379 	_pdata = pdata;
4380 	_reqsize = reqsize;
4381 
4382 	do {
4383 		reqhdr->tid = htons(sdp_gen_tid(session));
4384 
4385 		/* add continuation state (can be null) */
4386 		reqsize = _reqsize + copy_cstate(_pdata,
4387 					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
4388 
4389 		/* set the request header's param length */
4390 		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
4391 		rsphdr = (sdp_pdu_hdr_t *) rspbuf;
4392 		status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
4393 		if (rspsize < sizeof(sdp_pdu_hdr_t)) {
4394 			SDPERR("Unexpected end of packet");
4395 			status = -1;
4396 			goto end;
4397 		}
4398 
4399 		if (status < 0) {
4400 			SDPDBG("Status : 0x%x\n", rsphdr->pdu_id);
4401 			goto end;
4402 		}
4403 
4404 		if (rsphdr->pdu_id == SDP_ERROR_RSP) {
4405 			status = -1;
4406 			goto end;
4407 		}
4408 
4409 		pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
4410 		pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
4411 
4412 		if (pdata_len < sizeof(uint16_t)) {
4413 			SDPERR("Unexpected end of packet");
4414 			status = -1;
4415 			goto end;
4416 		}
4417 
4418 		rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
4419 		attr_list_len += rsp_count;
4420 		pdata += sizeof(uint16_t);	// pdata points to attribute list
4421 		pdata_len -= sizeof(uint16_t);
4422 
4423 		if (pdata_len < rsp_count + sizeof(uint8_t)) {
4424 			SDPERR("Unexpected end of packet: continuation state data missing");
4425 			status = -1;
4426 			goto end;
4427 		}
4428 
4429 		cstate_len = *(uint8_t *) (pdata + rsp_count);
4430 
4431 		SDPDBG("Attrlist byte count : %d\n", attr_list_len);
4432 		SDPDBG("Response byte count : %d\n", rsp_count);
4433 		SDPDBG("Cstate length : %d\n", cstate_len);
4434 		/*
4435 		 * This is a split response, need to concatenate intermediate
4436 		 * responses and the last one which will have cstate_len == 0
4437 		 */
4438 		if (cstate_len > 0 || rsp_concat_buf.data_size != 0) {
4439 			uint8_t *targetPtr = NULL;
4440 
4441 			cstate = cstate_len > 0 ? (sdp_cstate_t *) (pdata + rsp_count) : 0;
4442 
4443 			/* build concatenated response buffer */
4444 			rsp_concat_buf.data = realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count);
4445 			targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size;
4446 			rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count;
4447 			memcpy(targetPtr, pdata, rsp_count);
4448 			rsp_concat_buf.data_size += rsp_count;
4449 		}
4450 	} while (cstate);
4451 
4452 	if (attr_list_len > 0) {
4453 		int scanned = 0;
4454 
4455 		if (rsp_concat_buf.data_size != 0) {
4456 			pdata = rsp_concat_buf.data;
4457 			pdata_len = rsp_concat_buf.data_size;
4458 		}
4459 
4460 		/*
4461 		 * Response is a sequence of sequence(s) for one or
4462 		 * more data element sequence(s) representing services
4463 		 * for which attributes are returned
4464 		 */
4465 		scanned = sdp_extract_seqtype(pdata, pdata_len, &dataType, &seqlen);
4466 
4467 		SDPDBG("Bytes scanned : %d\n", scanned);
4468 		SDPDBG("Seq length : %d\n", seqlen);
4469 
4470 		if (scanned && seqlen) {
4471 			pdata += scanned;
4472 			pdata_len -= scanned;
4473 			do {
4474 				int recsize = 0;
4475 				sdp_record_t *rec = sdp_extract_pdu(pdata, pdata_len, &recsize);
4476 				if (rec == NULL) {
4477 					SDPERR("SVC REC is null\n");
4478 					status = -1;
4479 					goto end;
4480 				}
4481 				if (!recsize) {
4482 					sdp_record_free(rec);
4483 					break;
4484 				}
4485 				scanned += recsize;
4486 				pdata += recsize;
4487 				pdata_len -= recsize;
4488 
4489 				SDPDBG("Loc seq length : %d\n", recsize);
4490 				SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle);
4491 				SDPDBG("Bytes scanned : %d\n", scanned);
4492 				SDPDBG("Attrlist byte count : %d\n", attr_list_len);
4493 				rec_list = sdp_list_append(rec_list, rec);
4494 			} while (scanned < attr_list_len && pdata_len > 0);
4495 
4496 			SDPDBG("Successful scan of service attr lists\n");
4497 			*rsp = rec_list;
4498 		}
4499 	}
4500 end:
4501 	free(rsp_concat_buf.data);
4502 	free(reqbuf);
4503 	free(rspbuf);
4504 	return status;
4505 }
4506 
4507 /*
4508  * Find devices in the piconet.
4509  */
sdp_general_inquiry(inquiry_info * ii,int num_dev,int duration,uint8_t * found)4510 int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *found)
4511 {
4512 	int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0);
4513 	if (n < 0) {
4514 		SDPERR("Inquiry failed:%s", strerror(errno));
4515 		return -1;
4516 	}
4517 	*found = n;
4518 	return 0;
4519 }
4520 
sdp_close(sdp_session_t * session)4521 int sdp_close(sdp_session_t *session)
4522 {
4523 	struct sdp_transaction *t;
4524 	int ret;
4525 
4526 	if (!session)
4527 		return -1;
4528 
4529 	ret = close(session->sock);
4530 
4531 	t = session->priv;
4532 
4533 	if (t) {
4534 		free(t->reqbuf);
4535 
4536 		free(t->rsp_concat_buf.data);
4537 
4538 		free(t);
4539 	}
4540 	free(session);
4541 	return ret;
4542 }
4543 
sdp_is_local(const bdaddr_t * device)4544 static inline int sdp_is_local(const bdaddr_t *device)
4545 {
4546 	return memcmp(device, BDADDR_LOCAL, sizeof(bdaddr_t)) == 0;
4547 }
4548 
sdp_connect_local(sdp_session_t * session)4549 static int sdp_connect_local(sdp_session_t *session)
4550 {
4551 	struct sockaddr_un sa;
4552 
4553 	session->sock = socket(PF_UNIX, SOCK_STREAM, 0);
4554 	if (session->sock < 0)
4555 		return -1;
4556 	session->local = 1;
4557 
4558 	sa.sun_family = AF_UNIX;
4559 	strcpy(sa.sun_path, SDP_UNIX_PATH);
4560 
4561 	return connect(session->sock, (struct sockaddr *) &sa, sizeof(sa));
4562 }
4563 
sdp_connect_l2cap(const bdaddr_t * src,const bdaddr_t * dst,sdp_session_t * session)4564 static int sdp_connect_l2cap(const bdaddr_t *src,
4565 		const bdaddr_t *dst, sdp_session_t *session)
4566 {
4567 	uint32_t flags = session->flags;
4568 	struct sockaddr_l2 sa;
4569 	int sk;
4570 
4571 	session->sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
4572 	if (session->sock < 0)
4573 		return -1;
4574 	session->local = 0;
4575 
4576 	sk = session->sock;
4577 
4578 	if (flags & SDP_NON_BLOCKING) {
4579 		long arg = fcntl(sk, F_GETFL, 0);
4580 		fcntl(sk, F_SETFL, arg | O_NONBLOCK);
4581 	}
4582 
4583 	memset(&sa, 0, sizeof(sa));
4584 
4585 	sa.l2_family = AF_BLUETOOTH;
4586 	sa.l2_psm = 0;
4587 
4588 	if (bacmp(src, BDADDR_ANY)) {
4589 		sa.l2_bdaddr = *src;
4590 		if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0)
4591 			return -1;
4592 	}
4593 
4594 	if (flags & SDP_WAIT_ON_CLOSE) {
4595 		struct linger l = { .l_onoff = 1, .l_linger = 1 };
4596 		setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
4597 	}
4598 
4599 	sa.l2_psm = htobs(SDP_PSM);
4600 	sa.l2_bdaddr = *dst;
4601 
4602 	do {
4603 		int ret = connect(sk, (struct sockaddr *) &sa, sizeof(sa));
4604 		if (!ret)
4605 			return 0;
4606 		if (ret < 0 && (flags & SDP_NON_BLOCKING) &&
4607 				(errno == EAGAIN || errno == EINPROGRESS))
4608 			return 0;
4609 	} while (errno == EBUSY && (flags & SDP_RETRY_IF_BUSY));
4610 
4611 	return -1;
4612 }
4613 
sdp_connect(const bdaddr_t * src,const bdaddr_t * dst,uint32_t flags)4614 sdp_session_t *sdp_connect(const bdaddr_t *src,
4615 		const bdaddr_t *dst, uint32_t flags)
4616 {
4617 	sdp_session_t *session;
4618 	int err;
4619 
4620 	if ((flags & SDP_RETRY_IF_BUSY) && (flags & SDP_NON_BLOCKING)) {
4621 		errno = EINVAL;
4622 		return NULL;
4623 	}
4624 
4625 	session = sdp_create(-1, flags);
4626 	if (!session)
4627 		return NULL;
4628 
4629 	if (sdp_is_local(dst)) {
4630 		if (sdp_connect_local(session) < 0)
4631 			goto fail;
4632 	} else {
4633 		if (sdp_connect_l2cap(src, dst, session) < 0)
4634 			goto fail;
4635 	}
4636 
4637 	return session;
4638 
4639 fail:
4640 	err = errno;
4641 	if (session->sock >= 0)
4642 		close(session->sock);
4643 	free(session->priv);
4644 	free(session);
4645 	errno = err;
4646 
4647 	return NULL;
4648 }
4649 
sdp_get_socket(const sdp_session_t * session)4650 int sdp_get_socket(const sdp_session_t *session)
4651 {
4652 	return session->sock;
4653 }
4654 
sdp_gen_tid(sdp_session_t * session)4655 uint16_t sdp_gen_tid(sdp_session_t *session)
4656 {
4657 	return session->tid++;
4658 }
4659 
4660 /*
4661  * Set the supported features
4662  */
sdp_set_supp_feat(sdp_record_t * rec,const sdp_list_t * sf)4663 int sdp_set_supp_feat(sdp_record_t *rec, const sdp_list_t *sf)
4664 {
4665 	const sdp_list_t *p, *r;
4666 	sdp_data_t *feat, *seq_feat;
4667 	int seqlen, i;
4668 	void **seqDTDs, **seqVals;
4669 
4670 	seqlen = sdp_list_len(sf);
4671 	seqDTDs = malloc(seqlen * sizeof(void *));
4672 	if (!seqDTDs)
4673 		return -1;
4674 	seqVals = malloc(seqlen * sizeof(void *));
4675 	if (!seqVals) {
4676 		free(seqDTDs);
4677 		return -1;
4678 	}
4679 
4680 	for (p = sf, i = 0; p; p = p->next, i++) {
4681 		int plen, j;
4682 		void **dtds, **vals;
4683 		int *lengths;
4684 
4685 		plen = sdp_list_len(p->data);
4686 		dtds = malloc(plen * sizeof(void *));
4687 		if (!dtds)
4688 			goto fail;
4689 		vals = malloc(plen * sizeof(void *));
4690 		if (!vals) {
4691 			free(dtds);
4692 			goto fail;
4693 		}
4694 		lengths = malloc(plen * sizeof(int *));
4695 		if (!lengths) {
4696 			free(dtds);
4697 			free(vals);
4698 			goto fail;
4699 		}
4700 		for (r = p->data, j = 0; r; r = r->next, j++) {
4701 			sdp_data_t *data = (sdp_data_t*)r->data;
4702 			dtds[j] = &data->dtd;
4703 			switch (data->dtd) {
4704 			case SDP_URL_STR8:
4705 			case SDP_URL_STR16:
4706 			case SDP_TEXT_STR8:
4707 			case SDP_TEXT_STR16:
4708 				vals[j] = data->val.str;
4709 				lengths[j] = data->unitSize - sizeof(uint8_t);
4710 				break;
4711 			case SDP_ALT8:
4712 			case SDP_ALT16:
4713 			case SDP_ALT32:
4714 			case SDP_SEQ8:
4715 			case SDP_SEQ16:
4716 			case SDP_SEQ32:
4717 				vals[j] = data->val.dataseq;
4718 				lengths[j] = 0;
4719 				break;
4720 			default:
4721 				vals[j] = &data->val;
4722 				lengths[j] = 0;
4723 				break;
4724 			}
4725 		}
4726 		feat = sdp_seq_alloc_with_length(dtds, vals, lengths, plen);
4727 		free(dtds);
4728 		free(vals);
4729 		free(lengths);
4730 		if (!feat)
4731 			goto fail;
4732 		seqDTDs[i] = &feat->dtd;
4733 		seqVals[i] = feat;
4734 	}
4735 	seq_feat = sdp_seq_alloc(seqDTDs, seqVals, seqlen);
4736 	if (!seq_feat)
4737 		goto fail;
4738 	sdp_attr_replace(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST, seq_feat);
4739 
4740 	free(seqVals);
4741 	free(seqDTDs);
4742 	return 0;
4743 
4744 fail:
4745 	free(seqVals);
4746 	free(seqDTDs);
4747 	return -1;
4748 }
4749 
4750 /*
4751  * Get the supported features
4752  * If an error occurred -1 is returned and errno is set
4753  */
sdp_get_supp_feat(const sdp_record_t * rec,sdp_list_t ** seqp)4754 int sdp_get_supp_feat(const sdp_record_t *rec, sdp_list_t **seqp)
4755 {
4756 	sdp_data_t *sdpdata, *d;
4757 	sdp_list_t *tseq;
4758 	tseq = NULL;
4759 
4760 	sdpdata = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST);
4761 
4762 	if (!sdpdata || sdpdata->dtd < SDP_SEQ8 || sdpdata->dtd > SDP_SEQ32)
4763 		return sdp_get_uuidseq_attr(rec,
4764 					SDP_ATTR_SUPPORTED_FEATURES_LIST, seqp);
4765 
4766 	for (d = sdpdata->val.dataseq; d; d = d->next) {
4767 		sdp_data_t *dd;
4768 		sdp_list_t *subseq;
4769 
4770 		if (d->dtd < SDP_SEQ8 || d->dtd > SDP_SEQ32)
4771 			goto fail;
4772 
4773 		subseq = NULL;
4774 
4775 		for (dd = d->val.dataseq; dd; dd = dd->next) {
4776 			sdp_data_t *data;
4777 			void *val;
4778 			int length;
4779 
4780 			switch (dd->dtd) {
4781 			case SDP_URL_STR8:
4782 			case SDP_URL_STR16:
4783 			case SDP_TEXT_STR8:
4784 			case SDP_TEXT_STR16:
4785 				val = dd->val.str;
4786 				length = dd->unitSize - sizeof(uint8_t);
4787 				break;
4788 			case SDP_UINT8:
4789 			case SDP_UINT16:
4790 				val = &dd->val;
4791 				length = 0;
4792 				break;
4793 			default:
4794 				goto fail;
4795 			}
4796 
4797 			data = sdp_data_alloc_with_length(dd->dtd, val, length);
4798 			if (data)
4799 				subseq = sdp_list_append(subseq, data);
4800 		}
4801 		tseq = sdp_list_append(tseq, subseq);
4802 	}
4803 	*seqp = tseq;
4804 	return 0;
4805 
4806 fail:
4807 	while (tseq) {
4808 		sdp_list_t * next;
4809 
4810 		next = tseq->next;
4811 		sdp_list_free(tseq, free);
4812 		tseq = next;
4813 	}
4814 	errno = EINVAL;
4815 	return -1;
4816 }
4817 
4818