1 /* $NetBSD: compat.c$ */
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: compat.c$");
35 #include <arpa/inet.h>
37 #include <netbt/rfcomm.h>
39 #include <bluetooth.h>
49 * This file provides for compatibility with the old ABI. Clients send
50 * a data structure and we generate a record based from that using the
51 * server output buffer as temporary storage. The sdp_put functions will
52 * not write invalid data or overflow the buffer which is big enough to
53 * contain all these records, no need to worry about that.
57 dun_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
59 sdp_dun_profile_t
*data
= arg
;
60 uint8_t *first
= buf
->next
;
62 if (len
!= sizeof(*data
)
63 || data
->server_channel
< RFCOMM_CHANNEL_MIN
64 || data
->server_channel
> RFCOMM_CHANNEL_MAX
)
67 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
68 sdp_put_uint32(buf
, 0x00000000);
70 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
72 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_DIALUP_NETWORKING
);
74 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
77 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
79 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
80 sdp_put_uint8(buf
, data
->server_channel
);
82 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
84 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
86 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
88 sdp_put_uint16(buf
, 0x656e); /* "en" */
89 sdp_put_uint16(buf
, 106); /* UTF-8 */
90 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
92 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
95 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_DIALUP_NETWORKING
);
96 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
98 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
99 sdp_put_str(buf
, "Dialup Networking", -1);
101 sdp_put_uint16(buf
, SDP_ATTR_AUDIO_FEEDBACK_SUPPORT
);
102 sdp_put_bool(buf
, data
->audio_feedback_support
);
104 buf
->end
= buf
->next
;
110 ftrn_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
112 sdp_ftrn_profile_t
*data
= arg
;
113 uint8_t *first
= buf
->next
;
115 if (len
!= sizeof(*data
)
116 || data
->server_channel
< RFCOMM_CHANNEL_MIN
117 || data
->server_channel
> RFCOMM_CHANNEL_MAX
)
120 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
121 sdp_put_uint32(buf
, 0x00000000);
123 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
125 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER
);
127 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
128 sdp_put_seq(buf
, 17);
130 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
132 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
133 sdp_put_uint8(buf
, data
->server_channel
);
135 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_OBEX
);
137 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
139 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
141 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
143 sdp_put_uint16(buf
, 0x656e); /* "en" */
144 sdp_put_uint16(buf
, 106); /* UTF-8 */
145 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
147 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
150 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER
);
151 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
153 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
154 sdp_put_str(buf
, "OBEX File Transfer", -1);
156 buf
->end
= buf
->next
;
162 hset_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
164 sdp_hset_profile_t
*data
= arg
;
165 uint8_t *first
= buf
->next
;
167 if (len
!= sizeof(*data
)
168 || data
->server_channel
< RFCOMM_CHANNEL_MIN
169 || data
->server_channel
> RFCOMM_CHANNEL_MAX
)
172 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
173 sdp_put_uint32(buf
, 0x00000000);
175 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
177 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY
);
178 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_GENERIC_AUDIO
);
180 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
181 sdp_put_seq(buf
, 12);
183 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
185 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
186 sdp_put_uint8(buf
, data
->server_channel
);
188 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
190 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
192 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
194 sdp_put_uint16(buf
, 0x656e); /* "en" */
195 sdp_put_uint16(buf
, 106); /* UTF-8 */
196 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
198 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
201 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_HEADSET
);
202 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
204 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
205 sdp_put_str(buf
, "Voice Gateway", -1);
207 buf
->end
= buf
->next
;
213 hf_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
215 sdp_hf_profile_t
*data
= arg
;
216 uint8_t *first
= buf
->next
;
218 if (len
!= sizeof(*data
)
219 || data
->server_channel
< RFCOMM_CHANNEL_MIN
220 || data
->server_channel
> RFCOMM_CHANNEL_MAX
221 || (data
->supported_features
& ~0x001f))
224 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
225 sdp_put_uint32(buf
, 0x00000000);
227 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
229 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_HANDSFREE
);
230 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_GENERIC_AUDIO
);
232 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
233 sdp_put_seq(buf
, 12);
235 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
237 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
238 sdp_put_uint8(buf
, data
->server_channel
);
240 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
242 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
244 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
246 sdp_put_uint16(buf
, 0x656e); /* "en" */
247 sdp_put_uint16(buf
, 106); /* UTF-8 */
248 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
250 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
253 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_HANDSFREE
);
254 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
256 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
257 sdp_put_str(buf
, "Hands-Free unit", -1);
259 sdp_put_uint16(buf
, SDP_ATTR_SUPPORTED_FEATURES
);
260 sdp_put_uint16(buf
, data
->supported_features
);
262 buf
->end
= buf
->next
;
268 irmc_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
270 sdp_irmc_profile_t
*data
= arg
;
271 uint8_t *first
= buf
->next
;
274 if (len
!= sizeof(*data
)
275 || data
->server_channel
< RFCOMM_CHANNEL_MIN
276 || data
->server_channel
> RFCOMM_CHANNEL_MAX
277 || data
->supported_formats_size
== 0
278 || data
->supported_formats_size
> sizeof(data
->supported_formats
))
281 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
282 sdp_put_uint32(buf
, 0x00000000);
284 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
286 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_IR_MC_SYNC
);
288 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
289 sdp_put_seq(buf
, 17);
291 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
293 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
294 sdp_put_uint8(buf
, data
->server_channel
);
296 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_OBEX
);
298 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
300 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
302 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
304 sdp_put_uint16(buf
, 0x656e); /* "en" */
305 sdp_put_uint16(buf
, 106); /* UTF-8 */
306 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
308 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
311 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_IR_MC_SYNC
);
312 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
314 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
315 sdp_put_str(buf
, "IrMC Syncrhonization", -1);
317 sdp_put_uint16(buf
, SDP_ATTR_SUPPORTED_DATA_STORES_LIST
);
318 sdp_put_seq(buf
, data
->supported_formats_size
* 2);
319 for (i
= 0; i
< data
->supported_formats_size
; i
++)
320 sdp_put_uint8(buf
, data
->supported_formats
[i
]);
322 buf
->end
= buf
->next
;
328 irmc_cmd_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
330 sdp_irmc_command_profile_t
*data
= arg
;
331 uint8_t *first
= buf
->next
;
333 if (len
!= sizeof(*data
)
334 || data
->server_channel
< RFCOMM_CHANNEL_MIN
335 || data
->server_channel
> RFCOMM_CHANNEL_MAX
)
338 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
339 sdp_put_uint32(buf
, 0x00000000);
341 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
343 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND
);
345 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
346 sdp_put_seq(buf
, 17);
348 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
350 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
351 sdp_put_uint8(buf
, data
->server_channel
);
353 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_OBEX
);
355 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
357 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
359 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
361 sdp_put_uint16(buf
, 0x656e); /* "en" */
362 sdp_put_uint16(buf
, 106); /* UTF-8 */
363 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
365 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
368 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND
);
369 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
371 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
372 sdp_put_str(buf
, "Sync Command Service", -1);
374 buf
->end
= buf
->next
;
380 lan_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
382 sdp_lan_profile_t
*data
= arg
;
383 uint8_t *first
= buf
->next
;
387 if (len
!= sizeof(*data
)
388 || data
->server_channel
< RFCOMM_CHANNEL_MIN
389 || data
->server_channel
> RFCOMM_CHANNEL_MAX
390 || data
->ip_subnet_radius
> 32)
393 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
394 sdp_put_uint32(buf
, 0x00000000);
396 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
398 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP
);
400 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
401 sdp_put_seq(buf
, 12);
403 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
405 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
406 sdp_put_uint8(buf
, data
->server_channel
);
408 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
410 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
412 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
414 sdp_put_uint16(buf
, 0x656e); /* "en" */
415 sdp_put_uint16(buf
, 106); /* UTF-8 */
416 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
418 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_AVAILABILITY
);
419 sdp_put_uint8(buf
, data
->load_factor
);
421 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
424 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP
);
425 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
427 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
428 sdp_put_str(buf
, "LAN Access using PPP", -1);
430 in
.s_addr
= data
->ip_subnet
;
431 sprintf(str
, "%s/%d", inet_ntoa(in
), data
->ip_subnet_radius
);
432 sdp_put_uint16(buf
, SDP_ATTR_IP_SUBNET
);
433 sdp_put_str(buf
, str
, -1);
435 buf
->end
= buf
->next
;
441 opush_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
443 sdp_opush_profile_t
*data
= arg
;
444 uint8_t *first
= buf
->next
;
447 if (len
!= sizeof(*data
)
448 || data
->server_channel
< RFCOMM_CHANNEL_MIN
449 || data
->server_channel
> RFCOMM_CHANNEL_MAX
450 || data
->supported_formats_size
== 0
451 || data
->supported_formats_size
> sizeof(data
->supported_formats
))
454 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
455 sdp_put_uint32(buf
, 0x00000000);
457 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
459 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH
);
461 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
462 sdp_put_seq(buf
, 17);
464 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
466 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
467 sdp_put_uint8(buf
, data
->server_channel
);
469 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_OBEX
);
471 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
473 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
475 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
477 sdp_put_uint16(buf
, 0x656e); /* "en" */
478 sdp_put_uint16(buf
, 106); /* UTF-8 */
479 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
481 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
484 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH
);
485 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
487 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
488 sdp_put_str(buf
, "OBEX Object Push", -1);
490 sdp_put_uint16(buf
, SDP_ATTR_SUPPORTED_FORMATS_LIST
);
491 sdp_put_seq(buf
, data
->supported_formats_size
* 2);
492 for (i
= 0; i
< data
->supported_formats_size
; i
++)
493 sdp_put_uint8(buf
, data
->supported_formats
[i
]);
495 buf
->end
= buf
->next
;
501 sp_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
503 sdp_sp_profile_t
*data
= arg
;
504 uint8_t *first
= buf
->next
;
506 if (len
!= sizeof(*data
)
507 || data
->server_channel
< RFCOMM_CHANNEL_MIN
508 || data
->server_channel
> RFCOMM_CHANNEL_MAX
)
511 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
512 sdp_put_uint32(buf
, 0x00000000);
514 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
516 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_SERIAL_PORT
);
518 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
519 sdp_put_seq(buf
, 12);
521 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
523 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_RFCOMM
);
524 sdp_put_uint8(buf
, data
->server_channel
);
526 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
528 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
530 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
532 sdp_put_uint16(buf
, 0x656e); /* "en" */
533 sdp_put_uint16(buf
, 106); /* UTF-8 */
534 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
536 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
539 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_SERIAL_PORT
);
540 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
542 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
543 sdp_put_str(buf
, "Serial Port", -1);
545 buf
->end
= buf
->next
;
550 /* list of protocols used by PAN profiles. */
551 static const uint16_t proto
[] = {
560 nap_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
562 sdp_nap_profile_t
*data
= arg
;
563 uint8_t *first
= buf
->next
;
566 if (len
!= sizeof(*data
)
567 || L2CAP_PSM_INVALID(data
->psm
)
568 || data
->security_description
> 0x0002)
571 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
572 sdp_put_uint32(buf
, 0x00000000);
574 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
576 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_NAP
);
578 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
579 sdp_put_seq(buf
, 18 + 3 * __arraycount(proto
));
581 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
582 sdp_put_uint16(buf
, data
->psm
);
583 sdp_put_seq(buf
, 8 + 3 * __arraycount(proto
));
584 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_BNEP
);
585 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
586 sdp_put_seq(buf
, 3 * __arraycount(proto
));
587 for (i
= 0; i
< __arraycount(proto
); i
++)
588 sdp_put_uint16(buf
, proto
[i
]);
590 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
592 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
594 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
596 sdp_put_uint16(buf
, 0x656e); /* "en" */
597 sdp_put_uint16(buf
, 106); /* UTF-8 */
598 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
600 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_AVAILABILITY
);
601 sdp_put_uint8(buf
, data
->load_factor
);
603 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
606 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_NAP
);
607 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
609 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
610 sdp_put_str(buf
, "Network Access Point", -1);
612 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_DESCRIPTION_OFFSET
);
613 sdp_put_str(buf
, "Personal Ad-hoc Network Service", -1);
615 sdp_put_uint16(buf
, SDP_ATTR_SECURITY_DESCRIPTION
);
616 sdp_put_uint16(buf
, data
->security_description
);
618 sdp_put_uint16(buf
, SDP_ATTR_NET_ACCESS_TYPE
);
619 sdp_put_uint16(buf
, data
->net_access_type
);
621 sdp_put_uint16(buf
, SDP_ATTR_MAX_NET_ACCESS_RATE
);
622 sdp_put_uint32(buf
, data
->max_net_access_rate
);
624 buf
->end
= buf
->next
;
630 gn_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
632 sdp_gn_profile_t
*data
= arg
;
633 uint8_t *first
= buf
->next
;
636 if (len
!= sizeof(*data
)
637 || L2CAP_PSM_INVALID(data
->psm
)
638 || data
->security_description
> 0x0002)
641 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
642 sdp_put_uint32(buf
, 0x00000000);
644 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
646 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_GN
);
648 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
649 sdp_put_seq(buf
, 18 + 3 * __arraycount(proto
));
651 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
652 sdp_put_uint16(buf
, data
->psm
);
653 sdp_put_seq(buf
, 8 + 3 * __arraycount(proto
));
654 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_BNEP
);
655 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
656 sdp_put_seq(buf
, 3 * __arraycount(proto
));
657 for (i
= 0; i
< __arraycount(proto
); i
++)
658 sdp_put_uint16(buf
, proto
[i
]);
660 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
662 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
664 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
666 sdp_put_uint16(buf
, 0x656e); /* "en" */
667 sdp_put_uint16(buf
, 106); /* UTF-8 */
668 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
670 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_AVAILABILITY
);
671 sdp_put_uint8(buf
, data
->load_factor
);
673 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
676 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_GN
);
677 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
679 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
680 sdp_put_str(buf
, "Group Ad-hoc Network", -1);
682 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_DESCRIPTION_OFFSET
);
683 sdp_put_str(buf
, "Personal Group Ad-hoc Network Service", -1);
685 sdp_put_uint16(buf
, SDP_ATTR_SECURITY_DESCRIPTION
);
686 sdp_put_uint16(buf
, data
->security_description
);
688 buf
->end
= buf
->next
;
694 panu_profile(sdp_data_t
*buf
, void *arg
, ssize_t len
)
696 sdp_panu_profile_t
*data
= arg
;
697 uint8_t *first
= buf
->next
;
700 if (len
!= sizeof(*data
)
701 || L2CAP_PSM_INVALID(data
->psm
)
702 || data
->security_description
> 0x0002)
705 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
706 sdp_put_uint32(buf
, 0x00000000);
708 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
710 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PANU
);
712 sdp_put_uint16(buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
713 sdp_put_seq(buf
, 18 + 3 * __arraycount(proto
));
715 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_L2CAP
);
716 sdp_put_uint16(buf
, data
->psm
);
717 sdp_put_seq(buf
, 8 + 3 * __arraycount(proto
));
718 sdp_put_uuid16(buf
, SDP_UUID_PROTOCOL_BNEP
);
719 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
720 sdp_put_seq(buf
, 3 * __arraycount(proto
));
721 for (i
= 0; i
< __arraycount(proto
); i
++)
722 sdp_put_uint16(buf
, proto
[i
]);
724 sdp_put_uint16(buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
726 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
728 sdp_put_uint16(buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
730 sdp_put_uint16(buf
, 0x656e); /* "en" */
731 sdp_put_uint16(buf
, 106); /* UTF-8 */
732 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
734 sdp_put_uint16(buf
, SDP_ATTR_SERVICE_AVAILABILITY
);
735 sdp_put_uint8(buf
, data
->load_factor
);
737 sdp_put_uint16(buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
740 sdp_put_uuid16(buf
, SDP_SERVICE_CLASS_PANU
);
741 sdp_put_uint16(buf
, 0x0100); /* v1.0 */
743 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_NAME_OFFSET
);
744 sdp_put_str(buf
, "Personal Ad-hoc User Service", -1);
746 sdp_put_uint16(buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ SDP_ATTR_SERVICE_DESCRIPTION_OFFSET
);
747 sdp_put_str(buf
, "Personal Ad-hoc User Service", -1);
749 sdp_put_uint16(buf
, SDP_ATTR_SECURITY_DESCRIPTION
);
750 sdp_put_uint16(buf
, data
->security_description
);
752 buf
->end
= buf
->next
;
757 static const struct {
759 bool (*create
)(sdp_data_t
*, void *, ssize_t
);
761 { SDP_SERVICE_CLASS_DIALUP_NETWORKING
, dun_profile
},
762 { SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER
, ftrn_profile
},
763 { SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY
, hset_profile
},
764 { SDP_SERVICE_CLASS_HANDSFREE
, hf_profile
},
765 { SDP_SERVICE_CLASS_IR_MC_SYNC
, irmc_profile
},
766 { SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND
, irmc_cmd_profile
},
767 { SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP
, lan_profile
},
768 { SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH
, opush_profile
},
769 { SDP_SERVICE_CLASS_SERIAL_PORT
, sp_profile
},
770 { SDP_SERVICE_CLASS_NAP
, nap_profile
},
771 { SDP_SERVICE_CLASS_GN
, gn_profile
},
772 { SDP_SERVICE_CLASS_PANU
, panu_profile
},
776 compat_register_request(server_t
*srv
, int fd
)
783 if (!srv
->fdidx
[fd
].control
784 || !srv
->fdidx
[fd
].priv
)
785 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
787 srv
->fdidx
[fd
].offset
= 0;
788 db_unselect(srv
, fd
);
790 d
.end
= srv
->ibuf
+ srv
->pdu
.len
;
792 if (d
.next
+ sizeof(uint16_t) + sizeof(bdaddr_t
) > d
.end
)
793 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
795 class = be16dec(d
.next
);
796 d
.next
+= sizeof(uint16_t);
798 memcpy(&bdaddr
, d
.next
, sizeof(bdaddr_t
));
799 d
.next
+= sizeof(bdaddr_t
);
802 if (i
== __arraycount(known
))
803 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
805 if (known
[i
].class == class)
810 r
.end
= srv
->obuf
+ srv
->omtu
;
811 if (!(known
[i
].create(&r
, d
.next
, d
.end
- d
.next
)))
812 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
814 if (!db_create(srv
, fd
, &bdaddr
, srv
->handle
, &r
))
815 return SDP_ERROR_CODE_INSUFFICIENT_RESOURCES
;
817 /* successful return */
818 be16enc(srv
->obuf
, 0x0000);
819 be32enc(srv
->obuf
+ sizeof(uint16_t), srv
->handle
++);
820 srv
->pdu
.pid
= SDP_PDU_ERROR_RESPONSE
;
821 srv
->pdu
.len
= sizeof(uint16_t) + sizeof(uint32_t);
826 compat_change_request(server_t
*srv
, int fd
)
832 if (!srv
->fdidx
[fd
].control
833 || !srv
->fdidx
[fd
].priv
)
834 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
836 srv
->fdidx
[fd
].offset
= 0;
837 db_unselect(srv
, fd
);
839 d
.end
= srv
->ibuf
+ srv
->pdu
.len
;
841 if (d
.next
+ sizeof(uint32_t) > d
.end
)
842 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
844 db_select_handle(srv
, fd
, be32dec(d
.next
));
845 d
.next
+= sizeof(uint32_t);
848 db_next(srv
, fd
, &rec
);
849 if (rec
== NULL
|| rec
->fd
!= fd
)
850 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
853 * This is rather simplistic but it works. We don't keep a
854 * record of the ServiceClass but we do know the format of
855 * of the stored record and where it should be. If we dont
856 * find it there, just give up.
859 r
.next
+= 3; /* uint16 ServiceRecordHandle */
860 r
.next
+= 5; /* uint32 %handle% */
861 r
.next
+= 3; /* uint16 ServiceClassIDList */
862 r
.next
+= 2; /* seq8 */
864 if (i
== __arraycount(known
))
865 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
867 if (sdp_match_uuid16(&r
, known
[i
].class))
872 r
.end
= srv
->obuf
+ srv
->omtu
;
873 if (!(known
[i
].create(&r
, d
.next
, d
.end
- d
.next
)))
874 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
;
876 if (!db_create(srv
, fd
, &rec
->bdaddr
, rec
->handle
, &r
))
877 return SDP_ERROR_CODE_INSUFFICIENT_RESOURCES
;
879 db_unselect(srv
, fd
);
881 /* successful return */
882 be16enc(srv
->obuf
, 0x0000);
883 srv
->pdu
.pid
= SDP_PDU_ERROR_RESPONSE
;
884 srv
->pdu
.len
= sizeof(uint16_t);