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