1124758Semax/* 2124758Semax * service.c 3124758Semax * 4124758Semax * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5124758Semax * All rights reserved. 6124758Semax * 7124758Semax * Redistribution and use in source and binary forms, with or without 8124758Semax * modification, are permitted provided that the following conditions 9124758Semax * are met: 10124758Semax * 1. Redistributions of source code must retain the above copyright 11124758Semax * notice, this list of conditions and the following disclaimer. 12124758Semax * 2. Redistributions in binary form must reproduce the above copyright 13124758Semax * notice, this list of conditions and the following disclaimer in the 14124758Semax * documentation and/or other materials provided with the distribution. 15124758Semax * 16124758Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17124758Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18124758Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19124758Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20124758Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21124758Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22124758Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23124758Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24124758Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25124758Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26124758Semax * SUCH DAMAGE. 27124758Semax * 28124758Semax * $Id: service.c,v 1.1 2004/01/13 19:32:36 max Exp $ 29124758Semax * $FreeBSD$ 30124758Semax */ 31124758Semax 32124758Semax#include <sys/uio.h> 33124758Semax#include <netinet/in.h> 34124758Semax#include <arpa/inet.h> 35124758Semax#include <bluetooth.h> 36124758Semax#include <errno.h> 37124758Semax#include <string.h> 38124758Semax#include <unistd.h> 39124758Semax 40124758Semax#include <sdp-int.h> 41124758Semax#include <sdp.h> 42124758Semax 43124758Semaxstatic int32_t sdp_receive_error_pdu(sdp_session_p ss); 44124758Semax 45124758Semaxint32_t 46124758Semaxsdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr, 47124758Semax uint8_t const *data, uint32_t datalen, uint32_t *handle) 48124758Semax{ 49124758Semax sdp_session_p ss = (sdp_session_p) xss; 50124758Semax struct iovec iov[4]; 51124758Semax sdp_pdu_t pdu; 52124758Semax int32_t len; 53124758Semax 54124758Semax if (ss == NULL) 55124758Semax return (-1); 56124758Semax if (bdaddr == NULL || data == NULL || 57124758Semax datalen == 0 || !(ss->flags & SDP_SESSION_LOCAL)) { 58124758Semax ss->error = EINVAL; 59124758Semax return (-1); 60124758Semax } 61124758Semax if (sizeof(pdu)+sizeof(uuid)+sizeof(*bdaddr)+datalen > SDP_LOCAL_MTU) { 62124758Semax ss->error = EMSGSIZE; 63124758Semax return (-1); 64124758Semax } 65124758Semax 66124758Semax pdu.pid = SDP_PDU_SERVICE_REGISTER_REQUEST; 67124758Semax pdu.tid = htons(++ss->tid); 68124758Semax pdu.len = htons(sizeof(uuid) + sizeof(*bdaddr) + datalen); 69124758Semax 70124758Semax uuid = htons(uuid); 71124758Semax 72124758Semax iov[0].iov_base = (void *) &pdu; 73124758Semax iov[0].iov_len = sizeof(pdu); 74124758Semax 75124758Semax iov[1].iov_base = (void *) &uuid; 76124758Semax iov[1].iov_len = sizeof(uuid); 77124758Semax 78124758Semax iov[2].iov_base = (void *) bdaddr; 79124758Semax iov[2].iov_len = sizeof(*bdaddr); 80124758Semax 81124758Semax iov[3].iov_base = (void *) data; 82124758Semax iov[3].iov_len = datalen; 83124758Semax 84124758Semax do { 85124758Semax len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0])); 86124758Semax } while (len < 0 && errno == EINTR); 87124758Semax 88124758Semax if (len < 0) { 89124758Semax ss->error = errno; 90124758Semax return (-1); 91124758Semax } 92124758Semax 93124758Semax len = sdp_receive_error_pdu(ss); 94124758Semax if (len < 0) 95124758Semax return (-1); 96124758Semax if (len != sizeof(pdu) + sizeof(uint16_t) + sizeof(uint32_t)) { 97124758Semax ss->error = EIO; 98124758Semax return (-1); 99124758Semax } 100124758Semax 101124758Semax if (handle != NULL) { 102124758Semax *handle = (uint32_t) ss->rsp[--len]; 103124758Semax *handle |= (uint32_t) ss->rsp[--len] << 8; 104124758Semax *handle |= (uint32_t) ss->rsp[--len] << 16; 105124758Semax *handle |= (uint32_t) ss->rsp[--len] << 24; 106124758Semax } 107124758Semax 108124758Semax return (0); 109124758Semax} 110124758Semax 111124758Semaxint32_t 112124758Semaxsdp_unregister_service(void *xss, uint32_t handle) 113124758Semax{ 114124758Semax sdp_session_p ss = (sdp_session_p) xss; 115124758Semax struct iovec iov[2]; 116124758Semax sdp_pdu_t pdu; 117124758Semax int32_t len; 118124758Semax 119124758Semax if (ss == NULL) 120124758Semax return (-1); 121124758Semax if (!(ss->flags & SDP_SESSION_LOCAL)) { 122124758Semax ss->error = EINVAL; 123124758Semax return (-1); 124124758Semax } 125124758Semax if (sizeof(pdu) + sizeof(handle) > SDP_LOCAL_MTU) { 126124758Semax ss->error = EMSGSIZE; 127124758Semax return (-1); 128124758Semax } 129124758Semax 130124758Semax pdu.pid = SDP_PDU_SERVICE_UNREGISTER_REQUEST; 131124758Semax pdu.tid = htons(++ss->tid); 132124758Semax pdu.len = htons(sizeof(handle)); 133124758Semax 134124758Semax handle = htonl(handle); 135124758Semax 136124758Semax iov[0].iov_base = (void *) &pdu; 137124758Semax iov[0].iov_len = sizeof(pdu); 138124758Semax 139124758Semax iov[1].iov_base = (void *) &handle; 140124758Semax iov[1].iov_len = sizeof(handle); 141124758Semax 142124758Semax do { 143124758Semax len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0])); 144124758Semax } while (len < 0 && errno == EINTR); 145124758Semax 146124758Semax if (len < 0) { 147124758Semax ss->error = errno; 148124758Semax return (-1); 149124758Semax } 150124758Semax 151124758Semax return ((sdp_receive_error_pdu(ss) < 0)? -1 : 0); 152124758Semax} 153124758Semax 154124758Semaxint32_t 155124758Semaxsdp_change_service(void *xss, uint32_t handle, 156124758Semax uint8_t const *data, uint32_t datalen) 157124758Semax{ 158124758Semax sdp_session_p ss = (sdp_session_p) xss; 159124758Semax struct iovec iov[3]; 160124758Semax sdp_pdu_t pdu; 161124758Semax int32_t len; 162124758Semax 163124758Semax if (ss == NULL) 164124758Semax return (-1); 165124758Semax if (data == NULL || datalen == 0 || !(ss->flags & SDP_SESSION_LOCAL)) { 166124758Semax ss->error = EINVAL; 167124758Semax return (-1); 168124758Semax } 169124758Semax if (sizeof(pdu) + sizeof(handle) + datalen > SDP_LOCAL_MTU) { 170124758Semax ss->error = EMSGSIZE; 171124758Semax return (-1); 172124758Semax } 173124758Semax 174124758Semax pdu.pid = SDP_PDU_SERVICE_CHANGE_REQUEST; 175124758Semax pdu.tid = htons(++ss->tid); 176124758Semax pdu.len = htons(sizeof(handle) + datalen); 177124758Semax 178124758Semax handle = htons(handle); 179124758Semax 180124758Semax iov[0].iov_base = (void *) &pdu; 181124758Semax iov[0].iov_len = sizeof(pdu); 182124758Semax 183124758Semax iov[1].iov_base = (void *) &handle; 184124758Semax iov[1].iov_len = sizeof(handle); 185124758Semax 186124758Semax iov[2].iov_base = (void *) data; 187124758Semax iov[2].iov_len = datalen; 188124758Semax 189124758Semax do { 190124758Semax len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0])); 191124758Semax } while (len < 0 && errno == EINTR); 192124758Semax 193124758Semax if (len < 0) { 194124758Semax ss->error = errno; 195124758Semax return (-1); 196124758Semax } 197124758Semax 198124758Semax return ((sdp_receive_error_pdu(ss) < 0)? -1 : 0); 199124758Semax} 200124758Semax 201124758Semaxstatic int32_t 202124758Semaxsdp_receive_error_pdu(sdp_session_p ss) 203124758Semax{ 204124758Semax sdp_pdu_p pdu; 205124758Semax int32_t len; 206124758Semax uint16_t error; 207124758Semax 208124758Semax do { 209124758Semax len = read(ss->s, ss->rsp, ss->rsp_e - ss->rsp); 210124758Semax } while (len < 0 && errno == EINTR); 211124758Semax 212124758Semax if (len < 0) { 213124758Semax ss->error = errno; 214124758Semax return (-1); 215124758Semax } 216124758Semax 217124758Semax pdu = (sdp_pdu_p) ss->rsp; 218124758Semax pdu->tid = ntohs(pdu->tid); 219124758Semax pdu->len = ntohs(pdu->len); 220124758Semax 221124758Semax if (pdu->pid != SDP_PDU_ERROR_RESPONSE || pdu->tid != ss->tid || 222124758Semax pdu->len < 2 || pdu->len != len - sizeof(*pdu)) { 223124758Semax ss->error = EIO; 224124758Semax return (-1); 225124758Semax } 226124758Semax 227124758Semax error = (uint16_t) ss->rsp[sizeof(pdu)] << 8; 228124758Semax error |= (uint16_t) ss->rsp[sizeof(pdu) + 1]; 229124758Semax 230124758Semax if (error != 0) { 231124758Semax ss->error = EIO; 232124758Semax return (-1); 233124758Semax } 234124758Semax 235124758Semax return (len); 236124758Semax} 237124758Semax 238