xref: /freebsd/usr.sbin/bluetooth/btpand/sdp.c (revision 4e8d558c)
1 /*	$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
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$ */
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 */
45 static 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  */
61 bool
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  */
85 bool
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  */
135 bool
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  */
187 bool
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