1/*	$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5 *
6 * Copyright (c) 2008 Iain Hibbert
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/* $FreeBSD: stable/11/usr.sbin/bluetooth/btpand/sdp.c 330449 2018-03-05 07:26:05Z eadler $ */
31
32#include <sys/cdefs.h>
33__RCSID("$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $");
34
35#include <string.h>
36
37#define L2CAP_SOCKET_CHECKED
38#include "sdp.h"
39
40/*
41 * SDP data stream manipulation routines
42 */
43
44/* Bluetooth Base UUID */
45static const uuid_t BASE_UUID = {
46	0x00000000,
47	0x0000,
48	0x1000,
49	0x80,
50	0x00,
51	{ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb }
52};
53
54/*
55 * _sdp_match_uuid16(ptr, limit, uuid)
56 *
57 *	examine SDP data stream at ptr for a UUID, and return
58 *	true if it matches the supplied short alias bluetooth UUID.
59 *	limit is the first address past the end of valid data.
60 */
61bool
62_sdp_match_uuid16(uint8_t **ptr, uint8_t *limit, uint16_t uuid)
63{
64	uint8_t *p = *ptr;
65	uuid_t u1, u2;
66
67	memcpy(&u1, &BASE_UUID, sizeof(uuid_t));
68	u1.time_low = uuid;
69
70	if (!_sdp_get_uuid(&p, limit, &u2)
71	    || !uuid_equal(&u1, &u2, NULL))
72		return false;
73
74	*ptr = p;
75	return true;
76}
77
78/*
79 * _sdp_get_uuid(ptr, limit, uuid)
80 *
81 *	examine SDP data stream at ptr for a UUID, and extract
82 *	to given storage, advancing ptr.
83 *	limit is the first address past the end of valid data.
84 */
85bool
86_sdp_get_uuid(uint8_t **ptr, uint8_t *limit, uuid_t *uuid)
87{
88	uint8_t *p = *ptr;
89
90	if (p + 1 > limit)
91		return false;
92
93	switch (*p++) {
94	case SDP_DATA_UUID16:
95		if (p + 2 > limit)
96			return false;
97
98		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
99		uuid->time_low = be16dec(p);
100		p += 2;
101		break;
102
103	case SDP_DATA_UUID32:
104		if (p + 4 > limit)
105			return false;
106
107		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
108		uuid->time_low = be32dec(p);
109		p += 4;
110		break;
111
112	case SDP_DATA_UUID128:
113		if (p + 16 > limit)
114			return false;
115
116		uuid_dec_be(p, uuid);
117		p += 16;
118		break;
119
120	default:
121		return false;
122	}
123
124	*ptr = p;
125	return true;
126}
127
128/*
129 * _sdp_get_seq(ptr, limit, seq)
130 *
131 *	examine SDP data stream at ptr for a sequence. return
132 *	seq pointer if found and advance ptr to next object.
133 *	limit is the first address past the end of valid data.
134 */
135bool
136_sdp_get_seq(uint8_t **ptr, uint8_t *limit, uint8_t **seq)
137{
138	uint8_t *p = *ptr;
139	int32_t l;
140
141	if (p + 1 > limit)
142		return false;
143
144	switch (*p++) {
145	case SDP_DATA_SEQ8:
146		if (p + 1 > limit)
147			return false;
148
149		l = *p;
150		p += 1;
151		break;
152
153	case SDP_DATA_SEQ16:
154		if (p + 2 > limit)
155			return false;
156
157		l = be16dec(p);
158		p += 2;
159		break;
160
161	case SDP_DATA_SEQ32:
162		if (p + 4 > limit)
163			return false;
164
165		l = be32dec(p);
166		p += 4;
167		break;
168
169	default:
170		return false;
171	}
172	if (p + l > limit)
173		return false;
174
175	*seq = p;
176	*ptr = p + l;
177	return true;
178}
179
180/*
181 * _sdp_get_uint16(ptr, limit, value)
182 *
183 *	examine SDP data stream at ptr for a uint16_t, and
184 *	extract to given storage, advancing ptr.
185 *	limit is the first address past the end of valid data.
186 */
187bool
188_sdp_get_uint16(uint8_t **ptr, uint8_t *limit, uint16_t *value)
189{
190	uint8_t *p = *ptr;
191	uint16_t v;
192
193	if (p + 1 > limit)
194		return false;
195
196	switch (*p++) {
197	case SDP_DATA_UINT16:
198		if (p + 2 > limit)
199			return false;
200
201		v = be16dec(p);
202		p += 2;
203		break;
204
205	default:
206		return false;
207	}
208
209	*value = v;
210	*ptr = p;
211	return true;
212}
213