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