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