Coverage Report

Created: 2025-01-28 06:43

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