Coverage Report

Created: 2024-05-20 06:10

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