xref: /netbsd/lib/libbluetooth/sdp_record.c (revision dfbf818a)
1*dfbf818aSplunky /*	$NetBSD: sdp_record.c,v 1.1 2009/05/12 10:05:06 plunky Exp $	*/
2*dfbf818aSplunky 
3*dfbf818aSplunky /*-
4*dfbf818aSplunky  * Copyright (c) 2009 The NetBSD Foundation, Inc.
5*dfbf818aSplunky  * All rights reserved.
6*dfbf818aSplunky  *
7*dfbf818aSplunky  * This code is derived from software contributed to The NetBSD Foundation
8*dfbf818aSplunky  * by Iain Hibbert.
9*dfbf818aSplunky  *
10*dfbf818aSplunky  * Redistribution and use in source and binary forms, with or without
11*dfbf818aSplunky  * modification, are permitted provided that the following conditions
12*dfbf818aSplunky  * are met:
13*dfbf818aSplunky  * 1. Redistributions of source code must retain the above copyright
14*dfbf818aSplunky  *    notice, this list of conditions and the following disclaimer.
15*dfbf818aSplunky  * 2. Redistributions in binary form must reproduce the above copyright
16*dfbf818aSplunky  *    notice, this list of conditions and the following disclaimer in the
17*dfbf818aSplunky  *    documentation and/or other materials provided with the distribution.
18*dfbf818aSplunky  *
19*dfbf818aSplunky  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*dfbf818aSplunky  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*dfbf818aSplunky  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*dfbf818aSplunky  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*dfbf818aSplunky  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*dfbf818aSplunky  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*dfbf818aSplunky  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*dfbf818aSplunky  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*dfbf818aSplunky  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*dfbf818aSplunky  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*dfbf818aSplunky  * POSSIBILITY OF SUCH DAMAGE.
30*dfbf818aSplunky  */
31*dfbf818aSplunky 
32*dfbf818aSplunky #include <sys/cdefs.h>
33*dfbf818aSplunky __RCSID("$NetBSD: sdp_record.c,v 1.1 2009/05/12 10:05:06 plunky Exp $");
34*dfbf818aSplunky 
35*dfbf818aSplunky #include <errno.h>
36*dfbf818aSplunky #include <sdp.h>
37*dfbf818aSplunky #include <stdlib.h>
38*dfbf818aSplunky #include <string.h>
39*dfbf818aSplunky #include <unistd.h>
40*dfbf818aSplunky 
41*dfbf818aSplunky #include "sdp-int.h"
42*dfbf818aSplunky 
43*dfbf818aSplunky /*
44*dfbf818aSplunky  * This is the interface to sdpd(8); These PDU IDs are NOT part
45*dfbf818aSplunky  * of the Bluetooth specification.
46*dfbf818aSplunky  */
47*dfbf818aSplunky 
48*dfbf818aSplunky bool
sdp_record_insert(struct sdp_session * ss,bdaddr_t * bdaddr,uint32_t * handle,const sdp_data_t * rec)49*dfbf818aSplunky sdp_record_insert(struct sdp_session *ss, bdaddr_t *bdaddr,
50*dfbf818aSplunky     uint32_t *handle, const sdp_data_t *rec)
51*dfbf818aSplunky {
52*dfbf818aSplunky 	struct iovec	req[4];
53*dfbf818aSplunky 	sdp_data_t	hdr;
54*dfbf818aSplunky 	uint8_t		data[5];
55*dfbf818aSplunky 	ssize_t		len;
56*dfbf818aSplunky 	bdaddr_t	ba;
57*dfbf818aSplunky 	uint16_t	ec;
58*dfbf818aSplunky 
59*dfbf818aSplunky 	/*
60*dfbf818aSplunky 	 * setup BluetoothDeviceAddress
61*dfbf818aSplunky 	 */
62*dfbf818aSplunky 	bdaddr_copy(&ba, (bdaddr == NULL) ? BDADDR_ANY : bdaddr);
63*dfbf818aSplunky 	req[1].iov_base = &ba;
64*dfbf818aSplunky 	req[1].iov_len = sizeof(bdaddr_t);
65*dfbf818aSplunky 
66*dfbf818aSplunky 	/*
67*dfbf818aSplunky 	 * setup ServiceRecord
68*dfbf818aSplunky 	 */
69*dfbf818aSplunky 	len = rec->end - rec->next;
70*dfbf818aSplunky 	if (len < 0 || len > UINT16_MAX) {
71*dfbf818aSplunky 		errno = EINVAL;
72*dfbf818aSplunky 		return false;
73*dfbf818aSplunky 	}
74*dfbf818aSplunky 
75*dfbf818aSplunky 	hdr.next = data;
76*dfbf818aSplunky 	hdr.end = data + sizeof(data) + len;
77*dfbf818aSplunky 	sdp_put_seq(&hdr, len);
78*dfbf818aSplunky 	req[2].iov_base = data;
79*dfbf818aSplunky 	req[2].iov_len = hdr.next - data;
80*dfbf818aSplunky 
81*dfbf818aSplunky 	req[3].iov_base = rec->next;
82*dfbf818aSplunky 	req[3].iov_len = len;
83*dfbf818aSplunky 
84*dfbf818aSplunky 	/*
85*dfbf818aSplunky 	 * InsertRecord Transaction
86*dfbf818aSplunky 	 */
87*dfbf818aSplunky 	if (!_sdp_send_pdu(ss, SDP_PDU_RECORD_INSERT_REQUEST,
88*dfbf818aSplunky 	    req, __arraycount(req)))
89*dfbf818aSplunky 		return false;
90*dfbf818aSplunky 
91*dfbf818aSplunky 	len = _sdp_recv_pdu(ss, SDP_PDU_ERROR_RESPONSE);
92*dfbf818aSplunky 	if (len == -1)
93*dfbf818aSplunky 		return false;
94*dfbf818aSplunky 
95*dfbf818aSplunky 	if (len != sizeof(uint16_t) + sizeof(uint32_t)) {
96*dfbf818aSplunky 		errno = EIO;
97*dfbf818aSplunky 		return false;
98*dfbf818aSplunky 	}
99*dfbf818aSplunky 
100*dfbf818aSplunky 	/*
101*dfbf818aSplunky 	 * extract and check ErrorCode (success == 0)
102*dfbf818aSplunky 	 */
103*dfbf818aSplunky 	ec = be16dec(ss->ibuf);
104*dfbf818aSplunky 	if (ec != 0) {
105*dfbf818aSplunky 		errno = _sdp_errno(ec);
106*dfbf818aSplunky 		return false;
107*dfbf818aSplunky 	}
108*dfbf818aSplunky 
109*dfbf818aSplunky 	/*
110*dfbf818aSplunky 	 * extract ServiceRecordHandle if required
111*dfbf818aSplunky 	 */
112*dfbf818aSplunky 	if (handle != NULL)
113*dfbf818aSplunky 		*handle = be32dec(ss->ibuf + sizeof(uint16_t));
114*dfbf818aSplunky 
115*dfbf818aSplunky 	return true;
116*dfbf818aSplunky }
117*dfbf818aSplunky 
118*dfbf818aSplunky bool
sdp_record_update(struct sdp_session * ss,uint32_t handle,const sdp_data_t * rec)119*dfbf818aSplunky sdp_record_update(struct sdp_session *ss, uint32_t handle,
120*dfbf818aSplunky     const sdp_data_t *rec)
121*dfbf818aSplunky {
122*dfbf818aSplunky 	struct iovec	req[4];
123*dfbf818aSplunky 	sdp_data_t	hdr;
124*dfbf818aSplunky 	uint8_t		data[5];
125*dfbf818aSplunky 	ssize_t		len;
126*dfbf818aSplunky 	uint16_t	ec;
127*dfbf818aSplunky 
128*dfbf818aSplunky 	/*
129*dfbf818aSplunky 	 * setup ServiceRecordHandle
130*dfbf818aSplunky 	 */
131*dfbf818aSplunky 	handle = htobe32(handle);
132*dfbf818aSplunky 	req[1].iov_base = &handle;
133*dfbf818aSplunky 	req[1].iov_len = sizeof(handle);
134*dfbf818aSplunky 
135*dfbf818aSplunky 	/*
136*dfbf818aSplunky 	 * setup ServiceRecord
137*dfbf818aSplunky 	 */
138*dfbf818aSplunky 	len = rec->end - rec->next;
139*dfbf818aSplunky 	if (len < 0 || len > UINT16_MAX) {
140*dfbf818aSplunky 		errno = EINVAL;
141*dfbf818aSplunky 		return false;
142*dfbf818aSplunky 	}
143*dfbf818aSplunky 
144*dfbf818aSplunky 	hdr.next = data;
145*dfbf818aSplunky 	hdr.end = data + sizeof(data) + len;
146*dfbf818aSplunky 	sdp_put_seq(&hdr, len);
147*dfbf818aSplunky 	req[2].iov_base = data;
148*dfbf818aSplunky 	req[2].iov_len = hdr.next - data;
149*dfbf818aSplunky 
150*dfbf818aSplunky 	req[3].iov_base = rec->next;
151*dfbf818aSplunky 	req[3].iov_len = len;
152*dfbf818aSplunky 
153*dfbf818aSplunky 	/*
154*dfbf818aSplunky 	 * UpdateRecord Transaction
155*dfbf818aSplunky 	 */
156*dfbf818aSplunky 	if (!_sdp_send_pdu(ss, SDP_PDU_RECORD_UPDATE_REQUEST,
157*dfbf818aSplunky 	    req, __arraycount(req)))
158*dfbf818aSplunky 		return false;
159*dfbf818aSplunky 
160*dfbf818aSplunky 	len = _sdp_recv_pdu(ss, SDP_PDU_ERROR_RESPONSE);
161*dfbf818aSplunky 	if (len == -1)
162*dfbf818aSplunky 		return false;
163*dfbf818aSplunky 
164*dfbf818aSplunky 	if (len != sizeof(uint16_t)) {
165*dfbf818aSplunky 		errno = EIO;
166*dfbf818aSplunky 		return false;
167*dfbf818aSplunky 	}
168*dfbf818aSplunky 
169*dfbf818aSplunky 	/*
170*dfbf818aSplunky 	 * extract and check ErrorCode (success == 0)
171*dfbf818aSplunky 	 */
172*dfbf818aSplunky 	if ((ec = be16dec(ss->ibuf)) != 0) {
173*dfbf818aSplunky 		errno = _sdp_errno(ec);
174*dfbf818aSplunky 		return false;
175*dfbf818aSplunky 	}
176*dfbf818aSplunky 
177*dfbf818aSplunky 	return true;
178*dfbf818aSplunky }
179*dfbf818aSplunky 
180*dfbf818aSplunky bool
sdp_record_remove(struct sdp_session * ss,uint32_t handle)181*dfbf818aSplunky sdp_record_remove(struct sdp_session *ss, uint32_t handle)
182*dfbf818aSplunky {
183*dfbf818aSplunky 	struct iovec	req[2];
184*dfbf818aSplunky 	ssize_t		len;
185*dfbf818aSplunky 	uint16_t	ec;
186*dfbf818aSplunky 
187*dfbf818aSplunky 	/*
188*dfbf818aSplunky 	 * setup ServiceRecordHandle
189*dfbf818aSplunky 	 */
190*dfbf818aSplunky 	handle = htobe32(handle);
191*dfbf818aSplunky 	req[1].iov_base = &handle;
192*dfbf818aSplunky 	req[1].iov_len = sizeof(handle);
193*dfbf818aSplunky 
194*dfbf818aSplunky 	/*
195*dfbf818aSplunky 	 * RemoveRecord Transaction
196*dfbf818aSplunky 	 */
197*dfbf818aSplunky 	if (!_sdp_send_pdu(ss, SDP_PDU_RECORD_REMOVE_REQUEST,
198*dfbf818aSplunky 	    req, __arraycount(req)))
199*dfbf818aSplunky 		return false;
200*dfbf818aSplunky 
201*dfbf818aSplunky 	len = _sdp_recv_pdu(ss, SDP_PDU_ERROR_RESPONSE);
202*dfbf818aSplunky 	if (len == -1)
203*dfbf818aSplunky 		return false;
204*dfbf818aSplunky 
205*dfbf818aSplunky 	if (len != sizeof(uint16_t)) {
206*dfbf818aSplunky 		errno = EIO;
207*dfbf818aSplunky 		return false;
208*dfbf818aSplunky 	}
209*dfbf818aSplunky 
210*dfbf818aSplunky 	/*
211*dfbf818aSplunky 	 * extract and check ErrorCode (success == 0)
212*dfbf818aSplunky 	 */
213*dfbf818aSplunky 	ec = be16dec(ss->ibuf);
214*dfbf818aSplunky 	if (ec != 0) {
215*dfbf818aSplunky 		errno = _sdp_errno(ec);
216*dfbf818aSplunky 		return false;
217*dfbf818aSplunky 	}
218*dfbf818aSplunky 
219*dfbf818aSplunky 	return true;
220*dfbf818aSplunky }
221