CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

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