xref: /freebsd/lib/libsdp/session.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
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  */
328d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
330986ab12SMaksim Yevmenkin #include <bluetooth.h>
340986ab12SMaksim Yevmenkin #include <errno.h>
350986ab12SMaksim Yevmenkin #include <stdlib.h>
360986ab12SMaksim Yevmenkin #include <string.h>
370986ab12SMaksim Yevmenkin #include <unistd.h>
380986ab12SMaksim Yevmenkin 
390986ab12SMaksim Yevmenkin #include <sdp-int.h>
400986ab12SMaksim Yevmenkin #include <sdp.h>
410986ab12SMaksim Yevmenkin 
420986ab12SMaksim Yevmenkin void *
sdp_open(bdaddr_t const * l,bdaddr_t const * r)430986ab12SMaksim Yevmenkin sdp_open(bdaddr_t const *l, bdaddr_t const *r)
440986ab12SMaksim Yevmenkin {
450986ab12SMaksim Yevmenkin 	sdp_session_p		ss = NULL;
460986ab12SMaksim Yevmenkin 	struct sockaddr_l2cap	sa;
470986ab12SMaksim Yevmenkin 	socklen_t		size;
480986ab12SMaksim Yevmenkin 
490986ab12SMaksim Yevmenkin 	if ((ss = calloc(1, sizeof(*ss))) == NULL)
500986ab12SMaksim Yevmenkin 		goto fail;
510986ab12SMaksim Yevmenkin 
520986ab12SMaksim Yevmenkin 	if (l == NULL || r == NULL) {
530986ab12SMaksim Yevmenkin 		ss->error = EINVAL;
540986ab12SMaksim Yevmenkin 		goto fail;
550986ab12SMaksim Yevmenkin 	}
560986ab12SMaksim Yevmenkin 
570986ab12SMaksim Yevmenkin 	ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
580986ab12SMaksim Yevmenkin 	if (ss->s < 0) {
590986ab12SMaksim Yevmenkin 		ss->error = errno;
600986ab12SMaksim Yevmenkin 		goto fail;
610986ab12SMaksim Yevmenkin 	}
620986ab12SMaksim Yevmenkin 
630986ab12SMaksim Yevmenkin 	sa.l2cap_len = sizeof(sa);
640986ab12SMaksim Yevmenkin 	sa.l2cap_family = AF_BLUETOOTH;
650986ab12SMaksim Yevmenkin 	sa.l2cap_psm = 0;
668d6f425dSTakanori Watanabe 	sa.l2cap_cid = 0;
678d6f425dSTakanori Watanabe 	sa.l2cap_bdaddr_type = BDADDR_BREDR;
688d6f425dSTakanori Watanabe 
690986ab12SMaksim Yevmenkin 	memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr));
700986ab12SMaksim Yevmenkin 	if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
710986ab12SMaksim Yevmenkin 		ss->error = errno;
720986ab12SMaksim Yevmenkin 		goto fail;
730986ab12SMaksim Yevmenkin 	}
740986ab12SMaksim Yevmenkin 
750986ab12SMaksim Yevmenkin 	sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP);
760986ab12SMaksim Yevmenkin 	memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr));
770986ab12SMaksim Yevmenkin 	if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
780986ab12SMaksim Yevmenkin 		ss->error = errno;
790986ab12SMaksim Yevmenkin 		goto fail;
800986ab12SMaksim Yevmenkin 	}
810986ab12SMaksim Yevmenkin 
820986ab12SMaksim Yevmenkin 	size = sizeof(ss->omtu);
830986ab12SMaksim Yevmenkin 	if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) {
840986ab12SMaksim Yevmenkin 		ss->error = errno;
850986ab12SMaksim Yevmenkin 		goto fail;
860986ab12SMaksim Yevmenkin 	}
870986ab12SMaksim Yevmenkin 	if ((ss->req = malloc(ss->omtu)) == NULL) {
880986ab12SMaksim Yevmenkin 		ss->error = ENOMEM;
890986ab12SMaksim Yevmenkin 		goto fail;
900986ab12SMaksim Yevmenkin 	}
910986ab12SMaksim Yevmenkin 	ss->req_e = ss->req + ss->omtu;
920986ab12SMaksim Yevmenkin 
930986ab12SMaksim Yevmenkin 	size = sizeof(ss->imtu);
940986ab12SMaksim Yevmenkin 	if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) {
950986ab12SMaksim Yevmenkin 		ss->error = errno;
960986ab12SMaksim Yevmenkin 		goto fail;
970986ab12SMaksim Yevmenkin 	}
980986ab12SMaksim Yevmenkin 	if ((ss->rsp = malloc(ss->imtu)) == NULL) {
990986ab12SMaksim Yevmenkin 		ss->error = ENOMEM;
1000986ab12SMaksim Yevmenkin 		goto fail;
1010986ab12SMaksim Yevmenkin 	}
1020986ab12SMaksim Yevmenkin 	ss->rsp_e = ss->rsp + ss->imtu;
1030986ab12SMaksim Yevmenkin 	ss->error = 0;
1040986ab12SMaksim Yevmenkin fail:
1050986ab12SMaksim Yevmenkin 	return ((void *) ss);
1060986ab12SMaksim Yevmenkin }
1070986ab12SMaksim Yevmenkin 
1080986ab12SMaksim Yevmenkin void *
sdp_open_local(char const * control)109a4b187faSMaksim Yevmenkin sdp_open_local(char const *control)
1100986ab12SMaksim Yevmenkin {
1110986ab12SMaksim Yevmenkin 	sdp_session_p		ss = NULL;
1120986ab12SMaksim Yevmenkin 	struct sockaddr_un	sa;
1130986ab12SMaksim Yevmenkin 
1140986ab12SMaksim Yevmenkin 	if ((ss = calloc(1, sizeof(*ss))) == NULL)
1150986ab12SMaksim Yevmenkin 		goto fail;
1160986ab12SMaksim Yevmenkin 
1170986ab12SMaksim Yevmenkin 	ss->s = socket(PF_UNIX, SOCK_STREAM, 0);
1180986ab12SMaksim Yevmenkin 	if (ss->s < 0) {
1190986ab12SMaksim Yevmenkin 		ss->error = errno;
1200986ab12SMaksim Yevmenkin 		goto fail;
1210986ab12SMaksim Yevmenkin 	}
1220986ab12SMaksim Yevmenkin 
123a4b187faSMaksim Yevmenkin 	if (control == NULL)
124a4b187faSMaksim Yevmenkin 		control = SDP_LOCAL_PATH;
125a4b187faSMaksim Yevmenkin 
1260986ab12SMaksim Yevmenkin 	sa.sun_len = sizeof(sa);
1270986ab12SMaksim Yevmenkin 	sa.sun_family = AF_UNIX;
128a4b187faSMaksim Yevmenkin 	strlcpy(sa.sun_path, control, sizeof(sa.sun_path));
1290986ab12SMaksim Yevmenkin 
1300986ab12SMaksim Yevmenkin 	if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
1310986ab12SMaksim Yevmenkin 		ss->error = errno;
1320986ab12SMaksim Yevmenkin 		goto fail;
1330986ab12SMaksim Yevmenkin 	}
1340986ab12SMaksim Yevmenkin 
1350986ab12SMaksim Yevmenkin 	ss->flags |= SDP_SESSION_LOCAL;
1366aae6f7eSMaksim Yevmenkin 	ss->imtu = ss->omtu = SDP_LOCAL_MTU;
1370986ab12SMaksim Yevmenkin 
1380986ab12SMaksim Yevmenkin 	if ((ss->req = malloc(ss->omtu)) == NULL) {
1390986ab12SMaksim Yevmenkin 		ss->error = ENOMEM;
1400986ab12SMaksim Yevmenkin 		goto fail;
1410986ab12SMaksim Yevmenkin 	}
1420986ab12SMaksim Yevmenkin 	ss->req_e = ss->req + ss->omtu;
1430986ab12SMaksim Yevmenkin 
1440986ab12SMaksim Yevmenkin 	if ((ss->rsp = malloc(ss->imtu)) == NULL) {
1450986ab12SMaksim Yevmenkin 		ss->error = ENOMEM;
1460986ab12SMaksim Yevmenkin 		goto fail;
1470986ab12SMaksim Yevmenkin 	}
1480986ab12SMaksim Yevmenkin 	ss->rsp_e = ss->rsp + ss->imtu;
1490986ab12SMaksim Yevmenkin 	ss->error = 0;
1500986ab12SMaksim Yevmenkin fail:
1510986ab12SMaksim Yevmenkin 	return ((void *) ss);
1520986ab12SMaksim Yevmenkin }
1530986ab12SMaksim Yevmenkin 
1540986ab12SMaksim Yevmenkin int32_t
sdp_close(void * xss)1550986ab12SMaksim Yevmenkin sdp_close(void *xss)
1560986ab12SMaksim Yevmenkin {
1570986ab12SMaksim Yevmenkin 	sdp_session_p	ss = (sdp_session_p) xss;
1580986ab12SMaksim Yevmenkin 
1590986ab12SMaksim Yevmenkin 	if (ss != NULL) {
1600986ab12SMaksim Yevmenkin 		if (ss->s >= 0)
1610986ab12SMaksim Yevmenkin 			close(ss->s);
1620986ab12SMaksim Yevmenkin 
1630986ab12SMaksim Yevmenkin 		if (ss->req != NULL)
1640986ab12SMaksim Yevmenkin 			free(ss->req);
1650986ab12SMaksim Yevmenkin 		if (ss->rsp != NULL)
1660986ab12SMaksim Yevmenkin 			free(ss->rsp);
1670986ab12SMaksim Yevmenkin 
1680986ab12SMaksim Yevmenkin 		memset(ss, 0, sizeof(*ss));
1690986ab12SMaksim Yevmenkin 		free(ss);
1700986ab12SMaksim Yevmenkin 	}
1710986ab12SMaksim Yevmenkin 
1720986ab12SMaksim Yevmenkin 	return (0);
1730986ab12SMaksim Yevmenkin }
1740986ab12SMaksim Yevmenkin 
1750986ab12SMaksim Yevmenkin int32_t
sdp_error(void * xss)1760986ab12SMaksim Yevmenkin sdp_error(void *xss)
1770986ab12SMaksim Yevmenkin {
1780986ab12SMaksim Yevmenkin 	sdp_session_p	ss = (sdp_session_p) xss;
1790986ab12SMaksim Yevmenkin 
1800986ab12SMaksim Yevmenkin 	return ((ss != NULL)? ss->error : EINVAL);
1810986ab12SMaksim Yevmenkin }
182515bb54cSVladimir Kondratyev 
183515bb54cSVladimir Kondratyev int32_t
sdp_get_lcaddr(void * xss,bdaddr_t * l)184515bb54cSVladimir Kondratyev sdp_get_lcaddr(void *xss, bdaddr_t *l)
185515bb54cSVladimir Kondratyev {
186515bb54cSVladimir Kondratyev 	sdp_session_p		ss = (sdp_session_p) xss;
187515bb54cSVladimir Kondratyev 	struct sockaddr_l2cap	sa;
188515bb54cSVladimir Kondratyev 	socklen_t		size;
189515bb54cSVladimir Kondratyev 
190515bb54cSVladimir Kondratyev 	if (l == NULL || ss == NULL || ss->flags & SDP_SESSION_LOCAL) {
191515bb54cSVladimir Kondratyev 		ss->error = EINVAL;
192515bb54cSVladimir Kondratyev 		goto fail;
193515bb54cSVladimir Kondratyev 	}
194515bb54cSVladimir Kondratyev 
195515bb54cSVladimir Kondratyev 	size = sizeof(sa);
196515bb54cSVladimir Kondratyev 	if (getsockname(ss->s, (struct sockaddr *)&sa, &size) == 0) {
197515bb54cSVladimir Kondratyev 		bdaddr_copy(l, &sa.l2cap_bdaddr);
198515bb54cSVladimir Kondratyev 		ss->error = 0;
199515bb54cSVladimir Kondratyev 	} else
200515bb54cSVladimir Kondratyev 		ss->error = errno;
201515bb54cSVladimir Kondratyev fail:
202515bb54cSVladimir Kondratyev 	return ((ss->error == 0) ? 0 : -1);
203515bb54cSVladimir Kondratyev }
204