1187938Semax/*	$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $	*/
2187938Semax
3187938Semax/*-
4187938Semax * Copyright (c) 2008 Iain Hibbert
5187938Semax * All rights reserved.
6187938Semax *
7187938Semax * Redistribution and use in source and binary forms, with or without
8187938Semax * modification, are permitted provided that the following conditions
9187938Semax * are met:
10187938Semax * 1. Redistributions of source code must retain the above copyright
11187938Semax *    notice, this list of conditions and the following disclaimer.
12187938Semax * 2. Redistributions in binary form must reproduce the above copyright
13187938Semax *    notice, this list of conditions and the following disclaimer in the
14187938Semax *    documentation and/or other materials provided with the distribution.
15187938Semax *
16187938Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17187938Semax * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18187938Semax * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19187938Semax * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20187938Semax * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21187938Semax * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22187938Semax * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23187938Semax * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24187938Semax * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25187938Semax * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26187938Semax */
27187938Semax
28187938Semax/* $FreeBSD$ */
29187938Semax
30187938Semax#include <sys/cdefs.h>
31187938Semax__RCSID("$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $");
32187938Semax
33187938Semax#include <string.h>
34187938Semax
35187938Semax#include "sdp.h"
36187938Semax
37187938Semax/*
38187938Semax * SDP data stream manipulation routines
39187938Semax */
40187938Semax
41187938Semax/* Bluetooth Base UUID */
42187938Semaxstatic const uuid_t BASE_UUID = {
43187938Semax	0x00000000,
44187938Semax	0x0000,
45187938Semax	0x1000,
46187938Semax	0x80,
47187938Semax	0x00,
48187938Semax	{ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb }
49187938Semax};
50187938Semax
51187938Semax/*
52187938Semax * _sdp_match_uuid16(ptr, limit, uuid)
53187938Semax *
54187938Semax *	examine SDP data stream at ptr for a UUID, and return
55187938Semax *	true if it matches the supplied short alias bluetooth UUID.
56187938Semax *	limit is the first address past the end of valid data.
57187938Semax */
58187938Semaxbool
59187938Semax_sdp_match_uuid16(uint8_t **ptr, uint8_t *limit, uint16_t uuid)
60187938Semax{
61187938Semax	uint8_t *p = *ptr;
62187938Semax	uuid_t u1, u2;
63187938Semax
64187938Semax	memcpy(&u1, &BASE_UUID, sizeof(uuid_t));
65187938Semax	u1.time_low = uuid;
66187938Semax
67187938Semax	if (!_sdp_get_uuid(&p, limit, &u2)
68187938Semax	    || !uuid_equal(&u1, &u2, NULL))
69187938Semax		return false;
70187938Semax
71187938Semax	*ptr = p;
72187938Semax	return true;
73187938Semax}
74187938Semax
75187938Semax/*
76187938Semax * _sdp_get_uuid(ptr, limit, uuid)
77187938Semax *
78187938Semax *	examine SDP data stream at ptr for a UUID, and extract
79187938Semax *	to given storage, advancing ptr.
80187938Semax *	limit is the first address past the end of valid data.
81187938Semax */
82187938Semaxbool
83187938Semax_sdp_get_uuid(uint8_t **ptr, uint8_t *limit, uuid_t *uuid)
84187938Semax{
85187938Semax	uint8_t *p = *ptr;
86187938Semax
87187938Semax	if (p + 1 > limit)
88187938Semax		return false;
89187938Semax
90187938Semax	switch (*p++) {
91187938Semax	case SDP_DATA_UUID16:
92187938Semax		if (p + 2 > limit)
93187938Semax			return false;
94187938Semax
95187938Semax		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
96187938Semax		uuid->time_low = be16dec(p);
97187938Semax		p += 2;
98187938Semax		break;
99187938Semax
100187938Semax	case SDP_DATA_UUID32:
101187938Semax		if (p + 4 > limit)
102187938Semax			return false;
103187938Semax
104187938Semax		memcpy(uuid, &BASE_UUID, sizeof(uuid_t));
105187938Semax		uuid->time_low = be32dec(p);
106187938Semax		p += 4;
107187938Semax		break;
108187938Semax
109187938Semax	case SDP_DATA_UUID128:
110187938Semax		if (p + 16 > limit)
111187938Semax			return false;
112187938Semax
113187938Semax		uuid_dec_be(p, uuid);
114187938Semax		p += 16;
115187938Semax		break;
116187938Semax
117187938Semax	default:
118187938Semax		return false;
119187938Semax	}
120187938Semax
121187938Semax	*ptr = p;
122187938Semax	return true;
123187938Semax}
124187938Semax
125187938Semax/*
126187938Semax * _sdp_get_seq(ptr, limit, seq)
127187938Semax *
128187938Semax *	examine SDP data stream at ptr for a sequence. return
129187938Semax *	seq pointer if found and advance ptr to next object.
130187938Semax *	limit is the first address past the end of valid data.
131187938Semax */
132187938Semaxbool
133187938Semax_sdp_get_seq(uint8_t **ptr, uint8_t *limit, uint8_t **seq)
134187938Semax{
135187938Semax	uint8_t *p = *ptr;
136187938Semax	int32_t l;
137187938Semax
138187938Semax	if (p + 1 > limit)
139187938Semax		return false;
140187938Semax
141187938Semax	switch (*p++) {
142187938Semax	case SDP_DATA_SEQ8:
143187938Semax		if (p + 1 > limit)
144187938Semax			return false;
145187938Semax
146187938Semax		l = *p;
147187938Semax		p += 1;
148187938Semax		break;
149187938Semax
150187938Semax	case SDP_DATA_SEQ16:
151187938Semax		if (p + 2 > limit)
152187938Semax			return false;
153187938Semax
154187938Semax		l = be16dec(p);
155187938Semax		p += 2;
156187938Semax		break;
157187938Semax
158187938Semax	case SDP_DATA_SEQ32:
159187938Semax		if (p + 4 > limit)
160187938Semax			return false;
161187938Semax
162187938Semax		l = be32dec(p);
163187938Semax		p += 4;
164187938Semax		break;
165187938Semax
166187938Semax	default:
167187938Semax		return false;
168187938Semax	}
169187938Semax	if (p + l > limit)
170187938Semax		return false;
171187938Semax
172187938Semax	*seq = p;
173187938Semax	*ptr = p + l;
174187938Semax	return true;
175187938Semax}
176187938Semax
177187938Semax/*
178187938Semax * _sdp_get_uint16(ptr, limit, value)
179187938Semax *
180187938Semax *	examine SDP data stream at ptr for a uint16_t, and
181187938Semax *	extract to given storage, advancing ptr.
182187938Semax *	limit is the first address past the end of valid data.
183187938Semax */
184187938Semaxbool
185187938Semax_sdp_get_uint16(uint8_t **ptr, uint8_t *limit, uint16_t *value)
186187938Semax{
187187938Semax	uint8_t *p = *ptr;
188187938Semax	uint16_t v;
189187938Semax
190187938Semax	if (p + 1 > limit)
191187938Semax		return false;
192187938Semax
193187938Semax	switch (*p++) {
194187938Semax	case SDP_DATA_UINT16:
195187938Semax		if (p + 2 > limit)
196187938Semax			return false;
197187938Semax
198187938Semax		v = be16dec(p);
199187938Semax		p += 2;
200187938Semax		break;
201187938Semax
202187938Semax	default:
203187938Semax		return false;
204187938Semax	}
205187938Semax
206187938Semax	*value = v;
207187938Semax	*ptr = p;
208187938Semax	return true;
209187938Semax}
210