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