15e53a4f9SPedro F. Giffuni /*- 20986ab12SMaksim Yevmenkin * session.c 30986ab12SMaksim Yevmenkin * 4*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 55e53a4f9SPedro F. Giffuni * 60986ab12SMaksim Yevmenkin * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 70986ab12SMaksim Yevmenkin * All rights reserved. 80986ab12SMaksim Yevmenkin * 90986ab12SMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without 100986ab12SMaksim Yevmenkin * modification, are permitted provided that the following conditions 110986ab12SMaksim Yevmenkin * are met: 120986ab12SMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright 130986ab12SMaksim Yevmenkin * notice, this list of conditions and the following disclaimer. 140986ab12SMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright 150986ab12SMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the 160986ab12SMaksim Yevmenkin * documentation and/or other materials provided with the distribution. 170986ab12SMaksim Yevmenkin * 180986ab12SMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 190986ab12SMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 200986ab12SMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 210986ab12SMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 220986ab12SMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 230986ab12SMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 240986ab12SMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 250986ab12SMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 260986ab12SMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 270986ab12SMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 280986ab12SMaksim Yevmenkin * SUCH DAMAGE. 290986ab12SMaksim Yevmenkin * 300986ab12SMaksim Yevmenkin * $Id: session.c,v 1.2 2003/09/04 22:12:13 max Exp $ 310986ab12SMaksim Yevmenkin * $FreeBSD$ 320986ab12SMaksim Yevmenkin */ 338d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED 340986ab12SMaksim Yevmenkin #include <bluetooth.h> 350986ab12SMaksim Yevmenkin #include <errno.h> 360986ab12SMaksim Yevmenkin #include <stdlib.h> 370986ab12SMaksim Yevmenkin #include <string.h> 380986ab12SMaksim Yevmenkin #include <unistd.h> 390986ab12SMaksim Yevmenkin 400986ab12SMaksim Yevmenkin #include <sdp-int.h> 410986ab12SMaksim Yevmenkin #include <sdp.h> 420986ab12SMaksim Yevmenkin 430986ab12SMaksim Yevmenkin void * 440986ab12SMaksim Yevmenkin sdp_open(bdaddr_t const *l, bdaddr_t const *r) 450986ab12SMaksim Yevmenkin { 460986ab12SMaksim Yevmenkin sdp_session_p ss = NULL; 470986ab12SMaksim Yevmenkin struct sockaddr_l2cap sa; 480986ab12SMaksim Yevmenkin socklen_t size; 490986ab12SMaksim Yevmenkin 500986ab12SMaksim Yevmenkin if ((ss = calloc(1, sizeof(*ss))) == NULL) 510986ab12SMaksim Yevmenkin goto fail; 520986ab12SMaksim Yevmenkin 530986ab12SMaksim Yevmenkin if (l == NULL || r == NULL) { 540986ab12SMaksim Yevmenkin ss->error = EINVAL; 550986ab12SMaksim Yevmenkin goto fail; 560986ab12SMaksim Yevmenkin } 570986ab12SMaksim Yevmenkin 580986ab12SMaksim Yevmenkin ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 590986ab12SMaksim Yevmenkin if (ss->s < 0) { 600986ab12SMaksim Yevmenkin ss->error = errno; 610986ab12SMaksim Yevmenkin goto fail; 620986ab12SMaksim Yevmenkin } 630986ab12SMaksim Yevmenkin 640986ab12SMaksim Yevmenkin sa.l2cap_len = sizeof(sa); 650986ab12SMaksim Yevmenkin sa.l2cap_family = AF_BLUETOOTH; 660986ab12SMaksim Yevmenkin sa.l2cap_psm = 0; 678d6f425dSTakanori Watanabe sa.l2cap_cid = 0; 688d6f425dSTakanori Watanabe sa.l2cap_bdaddr_type = BDADDR_BREDR; 698d6f425dSTakanori Watanabe 700986ab12SMaksim Yevmenkin memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr)); 710986ab12SMaksim Yevmenkin if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 720986ab12SMaksim Yevmenkin ss->error = errno; 730986ab12SMaksim Yevmenkin goto fail; 740986ab12SMaksim Yevmenkin } 750986ab12SMaksim Yevmenkin 760986ab12SMaksim Yevmenkin sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP); 770986ab12SMaksim Yevmenkin memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr)); 780986ab12SMaksim Yevmenkin if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 790986ab12SMaksim Yevmenkin ss->error = errno; 800986ab12SMaksim Yevmenkin goto fail; 810986ab12SMaksim Yevmenkin } 820986ab12SMaksim Yevmenkin 830986ab12SMaksim Yevmenkin size = sizeof(ss->omtu); 840986ab12SMaksim Yevmenkin if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) { 850986ab12SMaksim Yevmenkin ss->error = errno; 860986ab12SMaksim Yevmenkin goto fail; 870986ab12SMaksim Yevmenkin } 880986ab12SMaksim Yevmenkin if ((ss->req = malloc(ss->omtu)) == NULL) { 890986ab12SMaksim Yevmenkin ss->error = ENOMEM; 900986ab12SMaksim Yevmenkin goto fail; 910986ab12SMaksim Yevmenkin } 920986ab12SMaksim Yevmenkin ss->req_e = ss->req + ss->omtu; 930986ab12SMaksim Yevmenkin 940986ab12SMaksim Yevmenkin size = sizeof(ss->imtu); 950986ab12SMaksim Yevmenkin if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) { 960986ab12SMaksim Yevmenkin ss->error = errno; 970986ab12SMaksim Yevmenkin goto fail; 980986ab12SMaksim Yevmenkin } 990986ab12SMaksim Yevmenkin if ((ss->rsp = malloc(ss->imtu)) == NULL) { 1000986ab12SMaksim Yevmenkin ss->error = ENOMEM; 1010986ab12SMaksim Yevmenkin goto fail; 1020986ab12SMaksim Yevmenkin } 1030986ab12SMaksim Yevmenkin ss->rsp_e = ss->rsp + ss->imtu; 1040986ab12SMaksim Yevmenkin ss->error = 0; 1050986ab12SMaksim Yevmenkin fail: 1060986ab12SMaksim Yevmenkin return ((void *) ss); 1070986ab12SMaksim Yevmenkin } 1080986ab12SMaksim Yevmenkin 1090986ab12SMaksim Yevmenkin void * 110a4b187faSMaksim Yevmenkin sdp_open_local(char const *control) 1110986ab12SMaksim Yevmenkin { 1120986ab12SMaksim Yevmenkin sdp_session_p ss = NULL; 1130986ab12SMaksim Yevmenkin struct sockaddr_un sa; 1140986ab12SMaksim Yevmenkin 1150986ab12SMaksim Yevmenkin if ((ss = calloc(1, sizeof(*ss))) == NULL) 1160986ab12SMaksim Yevmenkin goto fail; 1170986ab12SMaksim Yevmenkin 1180986ab12SMaksim Yevmenkin ss->s = socket(PF_UNIX, SOCK_STREAM, 0); 1190986ab12SMaksim Yevmenkin if (ss->s < 0) { 1200986ab12SMaksim Yevmenkin ss->error = errno; 1210986ab12SMaksim Yevmenkin goto fail; 1220986ab12SMaksim Yevmenkin } 1230986ab12SMaksim Yevmenkin 124a4b187faSMaksim Yevmenkin if (control == NULL) 125a4b187faSMaksim Yevmenkin control = SDP_LOCAL_PATH; 126a4b187faSMaksim Yevmenkin 1270986ab12SMaksim Yevmenkin sa.sun_len = sizeof(sa); 1280986ab12SMaksim Yevmenkin sa.sun_family = AF_UNIX; 129a4b187faSMaksim Yevmenkin strlcpy(sa.sun_path, control, sizeof(sa.sun_path)); 1300986ab12SMaksim Yevmenkin 1310986ab12SMaksim Yevmenkin if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 1320986ab12SMaksim Yevmenkin ss->error = errno; 1330986ab12SMaksim Yevmenkin goto fail; 1340986ab12SMaksim Yevmenkin } 1350986ab12SMaksim Yevmenkin 1360986ab12SMaksim Yevmenkin ss->flags |= SDP_SESSION_LOCAL; 1376aae6f7eSMaksim Yevmenkin ss->imtu = ss->omtu = SDP_LOCAL_MTU; 1380986ab12SMaksim Yevmenkin 1390986ab12SMaksim Yevmenkin if ((ss->req = malloc(ss->omtu)) == NULL) { 1400986ab12SMaksim Yevmenkin ss->error = ENOMEM; 1410986ab12SMaksim Yevmenkin goto fail; 1420986ab12SMaksim Yevmenkin } 1430986ab12SMaksim Yevmenkin ss->req_e = ss->req + ss->omtu; 1440986ab12SMaksim Yevmenkin 1450986ab12SMaksim Yevmenkin if ((ss->rsp = malloc(ss->imtu)) == NULL) { 1460986ab12SMaksim Yevmenkin ss->error = ENOMEM; 1470986ab12SMaksim Yevmenkin goto fail; 1480986ab12SMaksim Yevmenkin } 1490986ab12SMaksim Yevmenkin ss->rsp_e = ss->rsp + ss->imtu; 1500986ab12SMaksim Yevmenkin ss->error = 0; 1510986ab12SMaksim Yevmenkin fail: 1520986ab12SMaksim Yevmenkin return ((void *) ss); 1530986ab12SMaksim Yevmenkin } 1540986ab12SMaksim Yevmenkin 1550986ab12SMaksim Yevmenkin int32_t 1560986ab12SMaksim Yevmenkin sdp_close(void *xss) 1570986ab12SMaksim Yevmenkin { 1580986ab12SMaksim Yevmenkin sdp_session_p ss = (sdp_session_p) xss; 1590986ab12SMaksim Yevmenkin 1600986ab12SMaksim Yevmenkin if (ss != NULL) { 1610986ab12SMaksim Yevmenkin if (ss->s >= 0) 1620986ab12SMaksim Yevmenkin close(ss->s); 1630986ab12SMaksim Yevmenkin 1640986ab12SMaksim Yevmenkin if (ss->req != NULL) 1650986ab12SMaksim Yevmenkin free(ss->req); 1660986ab12SMaksim Yevmenkin if (ss->rsp != NULL) 1670986ab12SMaksim Yevmenkin free(ss->rsp); 1680986ab12SMaksim Yevmenkin 1690986ab12SMaksim Yevmenkin memset(ss, 0, sizeof(*ss)); 1700986ab12SMaksim Yevmenkin free(ss); 1710986ab12SMaksim Yevmenkin } 1720986ab12SMaksim Yevmenkin 1730986ab12SMaksim Yevmenkin return (0); 1740986ab12SMaksim Yevmenkin } 1750986ab12SMaksim Yevmenkin 1760986ab12SMaksim Yevmenkin int32_t 1770986ab12SMaksim Yevmenkin sdp_error(void *xss) 1780986ab12SMaksim Yevmenkin { 1790986ab12SMaksim Yevmenkin sdp_session_p ss = (sdp_session_p) xss; 1800986ab12SMaksim Yevmenkin 1810986ab12SMaksim Yevmenkin return ((ss != NULL)? ss->error : EINVAL); 1820986ab12SMaksim Yevmenkin } 183515bb54cSVladimir Kondratyev 184515bb54cSVladimir Kondratyev int32_t 185515bb54cSVladimir Kondratyev sdp_get_lcaddr(void *xss, bdaddr_t *l) 186515bb54cSVladimir Kondratyev { 187515bb54cSVladimir Kondratyev sdp_session_p ss = (sdp_session_p) xss; 188515bb54cSVladimir Kondratyev struct sockaddr_l2cap sa; 189515bb54cSVladimir Kondratyev socklen_t size; 190515bb54cSVladimir Kondratyev 191515bb54cSVladimir Kondratyev if (l == NULL || ss == NULL || ss->flags & SDP_SESSION_LOCAL) { 192515bb54cSVladimir Kondratyev ss->error = EINVAL; 193515bb54cSVladimir Kondratyev goto fail; 194515bb54cSVladimir Kondratyev } 195515bb54cSVladimir Kondratyev 196515bb54cSVladimir Kondratyev size = sizeof(sa); 197515bb54cSVladimir Kondratyev if (getsockname(ss->s, (struct sockaddr *)&sa, &size) == 0) { 198515bb54cSVladimir Kondratyev bdaddr_copy(l, &sa.l2cap_bdaddr); 199515bb54cSVladimir Kondratyev ss->error = 0; 200515bb54cSVladimir Kondratyev } else 201515bb54cSVladimir Kondratyev ss->error = errno; 202515bb54cSVladimir Kondratyev fail: 203515bb54cSVladimir Kondratyev return ((ss->error == 0) ? 0 : -1); 204515bb54cSVladimir Kondratyev } 205