1 /*- 2 * session.c 3 * 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5 * 6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: session.c,v 1.2 2003/09/04 22:12:13 max Exp $ 31 * $FreeBSD$ 32 */ 33 #define L2CAP_SOCKET_CHECKED 34 #include <bluetooth.h> 35 #include <errno.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 40 #include <sdp-int.h> 41 #include <sdp.h> 42 43 void * 44 sdp_open(bdaddr_t const *l, bdaddr_t const *r) 45 { 46 sdp_session_p ss = NULL; 47 struct sockaddr_l2cap sa; 48 socklen_t size; 49 50 if ((ss = calloc(1, sizeof(*ss))) == NULL) 51 goto fail; 52 53 if (l == NULL || r == NULL) { 54 ss->error = EINVAL; 55 goto fail; 56 } 57 58 ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 59 if (ss->s < 0) { 60 ss->error = errno; 61 goto fail; 62 } 63 64 sa.l2cap_len = sizeof(sa); 65 sa.l2cap_family = AF_BLUETOOTH; 66 sa.l2cap_psm = 0; 67 sa.l2cap_cid = 0; 68 sa.l2cap_bdaddr_type = BDADDR_BREDR; 69 70 memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr)); 71 if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 72 ss->error = errno; 73 goto fail; 74 } 75 76 sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP); 77 memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr)); 78 if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 79 ss->error = errno; 80 goto fail; 81 } 82 83 size = sizeof(ss->omtu); 84 if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) { 85 ss->error = errno; 86 goto fail; 87 } 88 if ((ss->req = malloc(ss->omtu)) == NULL) { 89 ss->error = ENOMEM; 90 goto fail; 91 } 92 ss->req_e = ss->req + ss->omtu; 93 94 size = sizeof(ss->imtu); 95 if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) { 96 ss->error = errno; 97 goto fail; 98 } 99 if ((ss->rsp = malloc(ss->imtu)) == NULL) { 100 ss->error = ENOMEM; 101 goto fail; 102 } 103 ss->rsp_e = ss->rsp + ss->imtu; 104 ss->error = 0; 105 fail: 106 return ((void *) ss); 107 } 108 109 void * 110 sdp_open_local(char const *control) 111 { 112 sdp_session_p ss = NULL; 113 struct sockaddr_un sa; 114 115 if ((ss = calloc(1, sizeof(*ss))) == NULL) 116 goto fail; 117 118 ss->s = socket(PF_UNIX, SOCK_STREAM, 0); 119 if (ss->s < 0) { 120 ss->error = errno; 121 goto fail; 122 } 123 124 if (control == NULL) 125 control = SDP_LOCAL_PATH; 126 127 sa.sun_len = sizeof(sa); 128 sa.sun_family = AF_UNIX; 129 strlcpy(sa.sun_path, control, sizeof(sa.sun_path)); 130 131 if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 132 ss->error = errno; 133 goto fail; 134 } 135 136 ss->flags |= SDP_SESSION_LOCAL; 137 ss->imtu = ss->omtu = SDP_LOCAL_MTU; 138 139 if ((ss->req = malloc(ss->omtu)) == NULL) { 140 ss->error = ENOMEM; 141 goto fail; 142 } 143 ss->req_e = ss->req + ss->omtu; 144 145 if ((ss->rsp = malloc(ss->imtu)) == NULL) { 146 ss->error = ENOMEM; 147 goto fail; 148 } 149 ss->rsp_e = ss->rsp + ss->imtu; 150 ss->error = 0; 151 fail: 152 return ((void *) ss); 153 } 154 155 int32_t 156 sdp_close(void *xss) 157 { 158 sdp_session_p ss = (sdp_session_p) xss; 159 160 if (ss != NULL) { 161 if (ss->s >= 0) 162 close(ss->s); 163 164 if (ss->req != NULL) 165 free(ss->req); 166 if (ss->rsp != NULL) 167 free(ss->rsp); 168 169 memset(ss, 0, sizeof(*ss)); 170 free(ss); 171 } 172 173 return (0); 174 } 175 176 int32_t 177 sdp_error(void *xss) 178 { 179 sdp_session_p ss = (sdp_session_p) xss; 180 181 return ((ss != NULL)? ss->error : EINVAL); 182 } 183 184 int32_t 185 sdp_get_lcaddr(void *xss, bdaddr_t *l) 186 { 187 sdp_session_p ss = (sdp_session_p) xss; 188 struct sockaddr_l2cap sa; 189 socklen_t size; 190 191 if (l == NULL || ss == NULL || ss->flags & SDP_SESSION_LOCAL) { 192 ss->error = EINVAL; 193 goto fail; 194 } 195 196 size = sizeof(sa); 197 if (getsockname(ss->s, (struct sockaddr *)&sa, &size) == 0) { 198 bdaddr_copy(l, &sa.l2cap_bdaddr); 199 ss->error = 0; 200 } else 201 ss->error = errno; 202 fail: 203 return ((ss->error == 0) ? 0 : -1); 204 } 205