1 /* $NetBSD: sdp_session.c,v 1.1 2009/05/12 10:05:06 plunky Exp $ */
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: sdp_session.c,v 1.1 2009/05/12 10:05:06 plunky Exp $");
35 #include <sys/socket.h>
47 * open session with remote Bluetooth SDP server
50 _sdp_open(const bdaddr_t
*laddr
, const bdaddr_t
*raddr
)
52 struct sdp_session
* ss
;
53 struct sockaddr_bt sa
;
57 ss
= calloc(1, sizeof(struct sdp_session
));
61 ss
->s
= socket(PF_BLUETOOTH
, SOCK_SEQPACKET
, BTPROTO_L2CAP
);
65 memset(&li
, 0, sizeof(li
));
68 if (setsockopt(ss
->s
, SOL_SOCKET
, SO_LINGER
, &li
, sizeof(li
)) == -1)
74 memset(&sa
, 0, sizeof(sa
));
75 sa
.bt_len
= sizeof(sa
);
76 sa
.bt_family
= AF_BLUETOOTH
;
77 bdaddr_copy(&sa
.bt_bdaddr
, laddr
);
78 if (bind(ss
->s
, (struct sockaddr
*)&sa
, sizeof(sa
)) == -1)
81 sa
.bt_psm
= L2CAP_PSM_SDP
;
82 bdaddr_copy(&sa
.bt_bdaddr
, raddr
);
83 if (connect(ss
->s
, (struct sockaddr
*)&sa
, sizeof(sa
)) == -1)
86 len
= sizeof(ss
->imtu
);
87 if (getsockopt(ss
->s
, BTPROTO_L2CAP
, SO_L2CAP_IMTU
, &ss
->imtu
, &len
) == -1)
90 ss
->ibuf
= malloc(ss
->imtu
);
102 * open session with local SDP server
105 _sdp_open_local(const char *control
)
107 struct sdp_session
* ss
;
108 struct sockaddr_un sa
;
110 ss
= calloc(1, sizeof(struct sdp_session
));
114 ss
->s
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
119 control
= SDP_LOCAL_PATH
;
121 memset(&sa
, 0, sizeof(sa
));
122 sa
.sun_len
= sizeof(sa
);
123 sa
.sun_family
= AF_LOCAL
;
124 strlcpy(sa
.sun_path
, control
, sizeof(sa
.sun_path
));
125 if (connect(ss
->s
, (struct sockaddr
*)&sa
, sizeof(sa
)) == -1)
128 ss
->imtu
= L2CAP_MTU_DEFAULT
;
130 ss
->ibuf
= malloc(ss
->imtu
);
131 if (ss
->ibuf
== NULL
)
142 * close session and release all resources
145 _sdp_close(struct sdp_session
*ss
)
154 if (ss
->ibuf
!= NULL
)
157 if (ss
->rbuf
!= NULL
)
164 * internal function; send a PDU on session
166 * caller provides an iovec array with an empty slot at the beginning for
167 * PDU header, num is total iovec count.
170 _sdp_send_pdu(struct sdp_session
*ss
, uint8_t pid
, struct iovec
*iov
, int num
)
176 for (len
= 0, i
= 1; i
< num
; i
++)
177 len
+= iov
[i
].iov_len
;
179 if (len
> UINT16_MAX
) {
187 pdu
.tid
= htobe16(ss
->tid
);
188 pdu
.len
= htobe16(len
);
190 iov
[0].iov_base
= &pdu
;
191 iov
[0].iov_len
= sizeof(pdu
);
194 nw
= writev(ss
->s
, iov
, num
);
195 } while (nw
== -1 && errno
== EINTR
);
197 if ((size_t)nw
!= sizeof(pdu
) + len
) {
206 * internal function; receive a PDU on session
208 * validate the PDU and transaction IDs and data length, stores
209 * received data in the session incoming buffer.
212 _sdp_recv_pdu(struct sdp_session
*ss
, uint8_t pid
)
218 iov
[0].iov_base
= &pdu
;
219 iov
[0].iov_len
= sizeof(pdu
);
221 iov
[1].iov_base
= ss
->ibuf
;
222 iov
[1].iov_len
= ss
->imtu
;
225 nr
= readv(ss
->s
, iov
, __arraycount(iov
));
226 } while (nr
== -1 && errno
== EINTR
);
231 if ((size_t)nr
< sizeof(pdu
)) {
236 pdu
.tid
= be16toh(pdu
.tid
);
237 pdu
.len
= be16toh(pdu
.len
);
240 || ss
->tid
!= pdu
.tid
241 || (size_t)nr
!= sizeof(pdu
) + pdu
.len
) {
242 if (pdu
.pid
== SDP_PDU_ERROR_RESPONSE
243 && pdu
.len
== sizeof(uint16_t))
244 errno
= _sdp_errno(be16dec(ss
->ibuf
));
255 * translate ErrorCode to errno
258 _sdp_errno(uint16_t ec
)
262 case SDP_ERROR_CODE_INVALID_SERVICE_RECORD_HANDLE
:
265 case SDP_ERROR_CODE_INVALID_SDP_VERSION
:
266 case SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
:
267 case SDP_ERROR_CODE_INVALID_PDU_SIZE
:
268 case SDP_ERROR_CODE_INVALID_CONTINUATION_STATE
:
269 case SDP_ERROR_CODE_INSUFFICIENT_RESOURCES
: