No empty .Rs/.Re
[netbsd-mini2440.git] / usr.sbin / sdpd / compat.c
bloba967204eb32e5fa14d8000e38ba634e575548a52
1 /* $NetBSD: compat.c$ */
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Iain Hibbert.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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>
40 #include <errno.h>
41 #include <sdp.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
46 #include "sdpd.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.
56 static bool
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)
65 return false;
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);
71 sdp_put_seq(buf, 3);
72 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_DIALUP_NETWORKING);
74 sdp_put_uint16(buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
75 sdp_put_seq(buf, 12);
76 sdp_put_seq(buf, 3);
77 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
78 sdp_put_seq(buf, 5);
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);
83 sdp_put_seq(buf, 3);
84 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
86 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
87 sdp_put_seq(buf, 9);
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);
93 sdp_put_seq(buf, 8);
94 sdp_put_seq(buf, 6);
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;
105 buf->next = first;
106 return true;
109 static bool
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)
118 return false;
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);
124 sdp_put_seq(buf, 3);
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);
129 sdp_put_seq(buf, 3);
130 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
131 sdp_put_seq(buf, 5);
132 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
133 sdp_put_uint8(buf, data->server_channel);
134 sdp_put_seq(buf, 3);
135 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
137 sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
138 sdp_put_seq(buf, 3);
139 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
141 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
142 sdp_put_seq(buf, 9);
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);
148 sdp_put_seq(buf, 8);
149 sdp_put_seq(buf, 6);
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;
157 buf->next = first;
158 return true;
161 static bool
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)
170 return false;
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);
176 sdp_put_seq(buf, 6);
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);
182 sdp_put_seq(buf, 3);
183 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
184 sdp_put_seq(buf, 5);
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);
189 sdp_put_seq(buf, 3);
190 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
192 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
193 sdp_put_seq(buf, 9);
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);
199 sdp_put_seq(buf, 8);
200 sdp_put_seq(buf, 6);
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;
208 buf->next = first;
209 return true;
212 static bool
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))
222 return false;
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);
228 sdp_put_seq(buf, 6);
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);
234 sdp_put_seq(buf, 3);
235 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
236 sdp_put_seq(buf, 5);
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);
241 sdp_put_seq(buf, 3);
242 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
244 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
245 sdp_put_seq(buf, 9);
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);
251 sdp_put_seq(buf, 8);
252 sdp_put_seq(buf, 6);
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;
263 buf->next = first;
264 return true;
267 static bool
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;
272 int i;
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))
279 return false;
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);
285 sdp_put_seq(buf, 3);
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);
290 sdp_put_seq(buf, 3);
291 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
292 sdp_put_seq(buf, 5);
293 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
294 sdp_put_uint8(buf, data->server_channel);
295 sdp_put_seq(buf, 3);
296 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
298 sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
299 sdp_put_seq(buf, 3);
300 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
302 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
303 sdp_put_seq(buf, 9);
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);
309 sdp_put_seq(buf, 8);
310 sdp_put_seq(buf, 6);
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;
323 buf->next = first;
324 return true;
327 static bool
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)
336 return false;
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);
342 sdp_put_seq(buf, 3);
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);
347 sdp_put_seq(buf, 3);
348 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
349 sdp_put_seq(buf, 5);
350 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
351 sdp_put_uint8(buf, data->server_channel);
352 sdp_put_seq(buf, 3);
353 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
355 sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
356 sdp_put_seq(buf, 3);
357 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
359 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
360 sdp_put_seq(buf, 9);
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);
366 sdp_put_seq(buf, 8);
367 sdp_put_seq(buf, 6);
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;
375 buf->next = first;
376 return true;
379 static bool
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;
384 struct in_addr in;
385 char str[32];
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)
391 return false;
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);
397 sdp_put_seq(buf, 3);
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);
402 sdp_put_seq(buf, 3);
403 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
404 sdp_put_seq(buf, 5);
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);
409 sdp_put_seq(buf, 3);
410 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
412 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
413 sdp_put_seq(buf, 9);
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);
422 sdp_put_seq(buf, 8);
423 sdp_put_seq(buf, 6);
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;
436 buf->next = first;
437 return true;
440 static bool
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;
445 int i;
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))
452 return false;
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);
458 sdp_put_seq(buf, 3);
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);
463 sdp_put_seq(buf, 3);
464 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
465 sdp_put_seq(buf, 5);
466 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_RFCOMM);
467 sdp_put_uint8(buf, data->server_channel);
468 sdp_put_seq(buf, 3);
469 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_OBEX);
471 sdp_put_uint16(buf, SDP_ATTR_BROWSE_GROUP_LIST);
472 sdp_put_seq(buf, 3);
473 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
475 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
476 sdp_put_seq(buf, 9);
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);
482 sdp_put_seq(buf, 8);
483 sdp_put_seq(buf, 6);
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;
496 buf->next = first;
497 return true;
500 static bool
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)
509 return false;
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);
515 sdp_put_seq(buf, 3);
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);
520 sdp_put_seq(buf, 3);
521 sdp_put_uuid16(buf, SDP_UUID_PROTOCOL_L2CAP);
522 sdp_put_seq(buf, 5);
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);
527 sdp_put_seq(buf, 3);
528 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
530 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
531 sdp_put_seq(buf, 9);
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);
537 sdp_put_seq(buf, 8);
538 sdp_put_seq(buf, 6);
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;
546 buf->next = first;
547 return true;
550 /* list of protocols used by PAN profiles. */
551 static const uint16_t proto[] = {
552 0x0800, /* IPv4 */
553 0x0806, /* ARP */
554 #ifdef INET6
555 0x86dd, /* IPv6 */
556 #endif
559 static bool
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;
564 size_t i;
566 if (len != sizeof(*data)
567 || L2CAP_PSM_INVALID(data->psm)
568 || data->security_description > 0x0002)
569 return false;
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);
575 sdp_put_seq(buf, 3);
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));
580 sdp_put_seq(buf, 6);
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);
591 sdp_put_seq(buf, 3);
592 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
594 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
595 sdp_put_seq(buf, 9);
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);
604 sdp_put_seq(buf, 8);
605 sdp_put_seq(buf, 6);
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;
625 buf->next = first;
626 return true;
629 static bool
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;
634 size_t i;
636 if (len != sizeof(*data)
637 || L2CAP_PSM_INVALID(data->psm)
638 || data->security_description > 0x0002)
639 return false;
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);
645 sdp_put_seq(buf, 3);
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));
650 sdp_put_seq(buf, 6);
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);
661 sdp_put_seq(buf, 3);
662 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
664 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
665 sdp_put_seq(buf, 9);
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);
674 sdp_put_seq(buf, 8);
675 sdp_put_seq(buf, 6);
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;
689 buf->next = first;
690 return true;
693 static bool
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;
698 size_t i;
700 if (len != sizeof(*data)
701 || L2CAP_PSM_INVALID(data->psm)
702 || data->security_description > 0x0002)
703 return false;
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);
709 sdp_put_seq(buf, 3);
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));
714 sdp_put_seq(buf, 6);
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);
725 sdp_put_seq(buf, 3);
726 sdp_put_uuid16(buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
728 sdp_put_uint16(buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
729 sdp_put_seq(buf, 9);
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);
738 sdp_put_seq(buf, 8);
739 sdp_put_seq(buf, 6);
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;
753 buf->next = first;
754 return true;
757 static const struct {
758 uint16_t class;
759 bool (*create)(sdp_data_t *, void *, ssize_t);
760 } known[] = {
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 },
775 uint16_t
776 compat_register_request(server_t *srv, int fd)
778 sdp_data_t d, r;
779 bdaddr_t bdaddr;
780 uint16_t class;
781 int i;
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);
789 d.next = srv->ibuf;
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);
801 for (i = 0;; i++) {
802 if (i == __arraycount(known))
803 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
805 if (known[i].class == class)
806 break;
809 r.next = srv->obuf;
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);
822 return 0;
825 uint16_t
826 compat_change_request(server_t *srv, int fd)
828 record_t *rec;
829 sdp_data_t d, r;
830 int i;
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);
838 d.next = srv->ibuf;
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);
847 rec = NULL;
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.
858 r = rec->data;
859 r.next += 3; /* uint16 ServiceRecordHandle */
860 r.next += 5; /* uint32 %handle% */
861 r.next += 3; /* uint16 ServiceClassIDList */
862 r.next += 2; /* seq8 */
863 for (i = 0;; i++) {
864 if (i == __arraycount(known))
865 return SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
867 if (sdp_match_uuid16(&r, known[i].class))
868 break;
871 r.next = srv->obuf;
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);
885 return 0;