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