xref: /freebsd/usr.sbin/bluetooth/btpand/sdp.c (revision a0ee8cc6)
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 #define L2CAP_SOCKET_CHECKED
36 #include "sdp.h"
37 
38 /*
39  * SDP data stream manipulation routines
40  */
41 
42 /* Bluetooth Base UUID */
43 static const uuid_t BASE_UUID = {
44 	0x00000000,
45 	0x0000,
46 	0x1000,
47 	0x80,
48 	0x00,
49 	{ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb }
50 };
51 
52 /*
53  * _sdp_match_uuid16(ptr, limit, uuid)
54  *
55  *	examine SDP data stream at ptr for a UUID, and return
56  *	true if it matches the supplied short alias bluetooth UUID.
57  *	limit is the first address past the end of valid data.
58  */
59 bool
60 _sdp_match_uuid16(uint8_t **ptr, uint8_t *limit, uint16_t uuid)
61 {
62 	uint8_t *p = *ptr;
63 	uuid_t u1, u2;
64 
65 	memcpy(&u1, &BASE_UUID, sizeof(uuid_t));
66 	u1.time_low = uuid;
67 
68 	if (!_sdp_get_uuid(&p, limit, &u2)
69 	    || !uuid_equal(&u1, &u2, NULL))
70 		return false;
71 
72 	*ptr = p;
73 	return true;
74 }
75 
76 /*
77  * _sdp_get_uuid(ptr, limit, uuid)
78  *
79  *	examine SDP data stream at ptr for a UUID, and extract
80  *	to given storage, advancing ptr.
81  *	limit is the first address past the end of valid data.
82  */
83 bool
84 _sdp_get_uuid(uint8_t **ptr, uint8_t *limit, uuid_t *uuid)
85 {
86 	uint8_t *p = *ptr;
87 
88 	if (p + 1 > limit)
89 		return false;
90 
91 	switch (*p++) {
92 	case SDP_DATA_UUID16:
93 		if (p + 2 > limit)
94 			return false;
95 
96 		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
97 		uuid->time_low = be16dec(p);
98 		p += 2;
99 		break;
100 
101 	case SDP_DATA_UUID32:
102 		if (p + 4 > limit)
103 			return false;
104 
105 		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
106 		uuid->time_low = be32dec(p);
107 		p += 4;
108 		break;
109 
110 	case SDP_DATA_UUID128:
111 		if (p + 16 > limit)
112 			return false;
113 
114 		uuid_dec_be(p, uuid);
115 		p += 16;
116 		break;
117 
118 	default:
119 		return false;
120 	}
121 
122 	*ptr = p;
123 	return true;
124 }
125 
126 /*
127  * _sdp_get_seq(ptr, limit, seq)
128  *
129  *	examine SDP data stream at ptr for a sequence. return
130  *	seq pointer if found and advance ptr to next object.
131  *	limit is the first address past the end of valid data.
132  */
133 bool
134 _sdp_get_seq(uint8_t **ptr, uint8_t *limit, uint8_t **seq)
135 {
136 	uint8_t *p = *ptr;
137 	int32_t l;
138 
139 	if (p + 1 > limit)
140 		return false;
141 
142 	switch (*p++) {
143 	case SDP_DATA_SEQ8:
144 		if (p + 1 > limit)
145 			return false;
146 
147 		l = *p;
148 		p += 1;
149 		break;
150 
151 	case SDP_DATA_SEQ16:
152 		if (p + 2 > limit)
153 			return false;
154 
155 		l = be16dec(p);
156 		p += 2;
157 		break;
158 
159 	case SDP_DATA_SEQ32:
160 		if (p + 4 > limit)
161 			return false;
162 
163 		l = be32dec(p);
164 		p += 4;
165 		break;
166 
167 	default:
168 		return false;
169 	}
170 	if (p + l > limit)
171 		return false;
172 
173 	*seq = p;
174 	*ptr = p + l;
175 	return true;
176 }
177 
178 /*
179  * _sdp_get_uint16(ptr, limit, value)
180  *
181  *	examine SDP data stream at ptr for a uint16_t, and
182  *	extract to given storage, advancing ptr.
183  *	limit is the first address past the end of valid data.
184  */
185 bool
186 _sdp_get_uint16(uint8_t **ptr, uint8_t *limit, uint16_t *value)
187 {
188 	uint8_t *p = *ptr;
189 	uint16_t v;
190 
191 	if (p + 1 > limit)
192 		return false;
193 
194 	switch (*p++) {
195 	case SDP_DATA_UINT16:
196 		if (p + 2 > limit)
197 			return false;
198 
199 		v = be16dec(p);
200 		p += 2;
201 		break;
202 
203 	default:
204 		return false;
205 	}
206 
207 	*value = v;
208 	*ptr = p;
209 	return true;
210 }
211