1 /*- 2 * session.c 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 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 */ 32 #define L2CAP_SOCKET_CHECKED 33 #include <bluetooth.h> 34 #include <errno.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <sdp-int.h> 40 #include <sdp.h> 41 42 void * 43 sdp_open(bdaddr_t const *l, bdaddr_t const *r) 44 { 45 sdp_session_p ss = NULL; 46 struct sockaddr_l2cap sa; 47 socklen_t size; 48 49 if ((ss = calloc(1, sizeof(*ss))) == NULL) 50 goto fail; 51 52 if (l == NULL || r == NULL) { 53 ss->error = EINVAL; 54 goto fail; 55 } 56 57 ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 58 if (ss->s < 0) { 59 ss->error = errno; 60 goto fail; 61 } 62 63 sa.l2cap_len = sizeof(sa); 64 sa.l2cap_family = AF_BLUETOOTH; 65 sa.l2cap_psm = 0; 66 sa.l2cap_cid = 0; 67 sa.l2cap_bdaddr_type = BDADDR_BREDR; 68 69 memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr)); 70 if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 71 ss->error = errno; 72 goto fail; 73 } 74 75 sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP); 76 memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr)); 77 if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 78 ss->error = errno; 79 goto fail; 80 } 81 82 size = sizeof(ss->omtu); 83 if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) { 84 ss->error = errno; 85 goto fail; 86 } 87 if ((ss->req = malloc(ss->omtu)) == NULL) { 88 ss->error = ENOMEM; 89 goto fail; 90 } 91 ss->req_e = ss->req + ss->omtu; 92 93 size = sizeof(ss->imtu); 94 if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) { 95 ss->error = errno; 96 goto fail; 97 } 98 if ((ss->rsp = malloc(ss->imtu)) == NULL) { 99 ss->error = ENOMEM; 100 goto fail; 101 } 102 ss->rsp_e = ss->rsp + ss->imtu; 103 ss->error = 0; 104 fail: 105 return ((void *) ss); 106 } 107 108 void * 109 sdp_open_local(char const *control) 110 { 111 sdp_session_p ss = NULL; 112 struct sockaddr_un sa; 113 114 if ((ss = calloc(1, sizeof(*ss))) == NULL) 115 goto fail; 116 117 ss->s = socket(PF_UNIX, SOCK_STREAM, 0); 118 if (ss->s < 0) { 119 ss->error = errno; 120 goto fail; 121 } 122 123 if (control == NULL) 124 control = SDP_LOCAL_PATH; 125 126 sa.sun_len = sizeof(sa); 127 sa.sun_family = AF_UNIX; 128 strlcpy(sa.sun_path, control, sizeof(sa.sun_path)); 129 130 if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 131 ss->error = errno; 132 goto fail; 133 } 134 135 ss->flags |= SDP_SESSION_LOCAL; 136 ss->imtu = ss->omtu = SDP_LOCAL_MTU; 137 138 if ((ss->req = malloc(ss->omtu)) == NULL) { 139 ss->error = ENOMEM; 140 goto fail; 141 } 142 ss->req_e = ss->req + ss->omtu; 143 144 if ((ss->rsp = malloc(ss->imtu)) == NULL) { 145 ss->error = ENOMEM; 146 goto fail; 147 } 148 ss->rsp_e = ss->rsp + ss->imtu; 149 ss->error = 0; 150 fail: 151 return ((void *) ss); 152 } 153 154 int32_t 155 sdp_close(void *xss) 156 { 157 sdp_session_p ss = (sdp_session_p) xss; 158 159 if (ss != NULL) { 160 if (ss->s >= 0) 161 close(ss->s); 162 163 if (ss->req != NULL) 164 free(ss->req); 165 if (ss->rsp != NULL) 166 free(ss->rsp); 167 168 memset(ss, 0, sizeof(*ss)); 169 free(ss); 170 } 171 172 return (0); 173 } 174 175 int32_t 176 sdp_error(void *xss) 177 { 178 sdp_session_p ss = (sdp_session_p) xss; 179 180 return ((ss != NULL)? ss->error : EINVAL); 181 } 182 183 int32_t 184 sdp_get_lcaddr(void *xss, bdaddr_t *l) 185 { 186 sdp_session_p ss = (sdp_session_p) xss; 187 struct sockaddr_l2cap sa; 188 socklen_t size; 189 190 if (l == NULL || ss == NULL || ss->flags & SDP_SESSION_LOCAL) { 191 ss->error = EINVAL; 192 goto fail; 193 } 194 195 size = sizeof(sa); 196 if (getsockname(ss->s, (struct sockaddr *)&sa, &size) == 0) { 197 bdaddr_copy(l, &sa.l2cap_bdaddr); 198 ss->error = 0; 199 } else 200 ss->error = errno; 201 fail: 202 return ((ss->error == 0) ? 0 : -1); 203 } 204