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