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