~bluetooth/bluez/vivid-phone-overlay

« back to all changes in this revision

Viewing changes to lib/sdp.c

  • Committer: Simon Fels
  • Date: 2015-09-11 09:01:46 UTC
  • Revision ID: morphis@gravedo.de-20150911090146-4c0ln9s7ec3xf0nx
Import package bluez_4.101-0ubuntu25.1~overlay4 from stable phone overlay PPA

Show diffs side-by-side

added added

removed removed

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