diff options
author | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
---|---|---|
committer | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
commit | 41bb0e8fd2568243020852e22a6d176bccfa60cd (patch) | |
tree | 0ae0c2be63f9f9161693789721b96beb9cabcc77 | |
parent | 66feac7937e372f502539e7d443aee80a25abe16 (diff) | |
download | FreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.zip FreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.tar.gz |
Update Bluetooth code.
Reviewed by: M. Warner Losh <imp@bsdimp.com>; John Hay <jhay@freebsd.org>
Approved by: M. Warner Losh <imp@bsdimp.com> (mentor)
109 files changed, 5997 insertions, 988 deletions
diff --git a/etc/bluetooth/hcsecd.conf b/etc/bluetooth/hcsecd.conf new file mode 100644 index 0000000..fc43685 --- /dev/null +++ b/etc/bluetooth/hcsecd.conf @@ -0,0 +1,56 @@ +# $Id: hcsecd.conf,v 1.1 2003/05/26 22:50:47 max Exp $ +# $FreeBSD$ +# +# HCI security daemon configuration file +# +# Format: +# +# device { +# option value ; +# } +# +# Possible options and values +# +# Options Values +# ---------------------------------- +# bdaddr xx:xx:xx:xx:xx:xx ; - remote device BD_ADDR +# name "any char" ; - to set user friendly device name +# key 0x11223344 | nokey ; - to set link key for the device +# pin "secret" | nopin ; - to PIN code for the device +# +# Notes: +# +# Currently there is no way to select keys/PIN code based on which +# local device received the request. Everything is based on remote +# device BD_ADDR. +# +# "nokey" means that no link key has been defined and we should +# send Link_Key_Negative_Reply command to the device. +# +# "nopin" means that no PIN code has been defined and we should +# send PIN_Code_Negative_Reply command to the device +# + +# Default entry is applied if no better match found +# It MUST have 00:00:00:00:00:00 as bdaddr +device { + bdaddr 00:00:00:00:00:00; + name "Default entry"; + key nokey; + pin nopin; +} + +device { + bdaddr 00:1:2:3:4:5; + name "Dummy"; + key nokey; + pin "0000"; +} + +device { + bdaddr 00:11:22:33:44:55; + name "Dummy"; + key 0x00112233445566778899aabbccddeeff; # 16 bytes key (hex string) + pin nopin; +} + diff --git a/etc/bluetooth/hosts b/etc/bluetooth/hosts new file mode 100644 index 0000000..4ad0a04 --- /dev/null +++ b/etc/bluetooth/hosts @@ -0,0 +1,11 @@ +# $Id: hosts,v 1.1 2003/05/21 17:48:40 max Exp $ +# $FreeBSD$ +# +# Bluetooth Host Database +# +# This file should contain the Bluetooth addresses and aliases for hosts. +# +# BD_ADDR Name [ alias0 alias1 ... ] + +ff:ff:ff:00:00:00 localhost local # Magic sdpd address + diff --git a/etc/bluetooth/protocols b/etc/bluetooth/protocols new file mode 100644 index 0000000..222798b --- /dev/null +++ b/etc/bluetooth/protocols @@ -0,0 +1,21 @@ +# $Id: protocols,v 1.2 2003/05/21 22:17:14 max Exp $ +# $FreeBSD$ +# +# Bluetooth Protocol/Service Multiplexor (PSM) names and numbers +# +# See also http://www.bluetoothsig.org/assigned-numbers/ +# +# Protocol PSM Alias Reference + +sdp 1 SDP # Service Discovery Protocol +rfcomm 3 RFCOMM # RFCOMM with TS 07.10 +tcs-bin 5 TCS-BIN # Telephony Control Specification +tcs-bin-cordless 7 TCS-BIN-CORDLESS # Telephony Control Specification +bnep 15 BNEP # Bluetooth Network Encapsulation Protocol +hid-control 17 HID-Control # Human Interface Device (control) +hid-interrupt 19 HID-Interrupt # Human Interface Device (interrupt) +upnp 21 UPnP # See ESDP, Bluetooth SIG +avctp 23 AVCTP # Audio/Video Control Transport Protocol +avdtp 25 AVDTP # Audio/Video Distribution Transport Protocol +udi-c-plane 29 UDI-C-Plane # Unrestricted Digital Information Profile + diff --git a/lib/Makefile b/lib/Makefile index 428ed81..d24d7b1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -23,12 +23,13 @@ SUBDIR= ${_csu} libcom_err libcrypt libkvm msun libmd \ libncurses libradius librpcsvc libsbuf libtacplus libutil libypclnt \ - ${_compat} libalias ${_libatm} ${_libbind} libbz2 libc ${_libc_r} \ + ${_compat} libalias ${_libatm} ${_libbind} \ + ${_libbluetooth} libbz2 libc ${_libc_r} \ libcalendar libcam libcompat libdevinfo libdevstat ${_libdisk} \ libedit libexpat libfetch libform libftpio libgeom ${_libio} libipsec \ libipx libisc libkiconv libmenu ${_libmilter} ${_libmp} ${_libncp} \ libnetgraph libopie libpam libpanel libpcap ${_libpthread} \ - ${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \ + ${_libsdp} ${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \ libstand libtelnet ${_libthr} libufs libugidfw ${_libusbhid} \ ${_libvgl} libwrap libxpg4 liby libz @@ -68,7 +69,9 @@ _libusbhid= libusbhid .if ${MACHINE_ARCH} == "i386" _compat= compat +_libbluetooth= libbluetooth _libncp= libncp +_libsdp= libsdp _libsmb= libsmb _libvgl= libvgl .endif diff --git a/lib/libbluetooth/Makefile b/lib/libbluetooth/Makefile new file mode 100644 index 0000000..becd41b --- /dev/null +++ b/lib/libbluetooth/Makefile @@ -0,0 +1,30 @@ +# $Id: Makefile,v 1.5 2003/07/22 18:38:04 max Exp $ +# $FreeBSD$ + +LIB= bluetooth +MAN= bluetooth.3 + +WARNS?= 2 +CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys + +SHLIB_MAJOR= 1 + +SRCS= bluetooth.c +INCS= bluetooth.h + +MLINKS+= bluetooth.3 bt_gethostbyname.3 +MLINKS+= bluetooth.3 bt_gethostbyaddr.3 +MLINKS+= bluetooth.3 bt_gethostent.3 +MLINKS+= bluetooth.3 bt_sethostent.3 +MLINKS+= bluetooth.3 bt_endhostent.3 + +MLINKS+= bluetooth.3 bt_getprotobyname.3 +MLINKS+= bluetooth.3 bt_getprotobynumber.3 +MLINKS+= bluetooth.3 bt_getprotoent.3 +MLINKS+= bluetooth.3 bt_setprotoent.3 +MLINKS+= bluetooth.3 bt_endprotoent.3 + +MLINKS+= bluetooth.3 bt_ntoa.3 +MLINKS+= bluetooth.3 bt_aton.3 + +.include <bsd.lib.mk> diff --git a/lib/libbluetooth/bluetooth.3 b/lib/libbluetooth/bluetooth.3 new file mode 100644 index 0000000..5980027 --- /dev/null +++ b/lib/libbluetooth/bluetooth.3 @@ -0,0 +1,293 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: bluetooth.3,v 1.5 2003/05/20 23:04:30 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 7, 2003 +.Dt BLUETOOTH 3 +.Os +.Sh NAME +.Nm bt_gethostbyname , +.Nm bt_gethostbyaddr , +.Nm bt_gethostent , +.Nm bt_sethostent , +.Nm bt_endhostent +.Nd get Bluetooth host entry +.Pp +.Nm bt_getprotobyname , +.Nm bt_getprotobynumber , +.Nm bt_getprotoent , +.Nm bt_setprotoent , +.Nm bt_endprotoent +.Nd get Bluetooth Protocol Service Multiplexor entry +.Pp +.Nm bt_aton , +.Nm bt_ntoa +.Nd Bluetooth address manipulation routines +.Sh LIBRARY +.Lb libbluetooth +.Sh SYNOPSIS +.In bluetooth.h +.Ft struct hostent * +.Fn bt_gethostbyname "const char *name" +.Ft struct hostent * +.Fn bt_gethostbyaddr "const char *addr" "int len" "int type" +.Ft struct hostent * +.Fn bt_gethostent void +.Ft void +.Fn bt_sethostent "int stayopen" +.Ft void +.Fn bt_endhostent void +.Ft struct protoent * +.Fn bt_getprotobyname "const char *name" +.Ft struct protoent * +.Fn bt_getprotobynumber "int proto" +.Ft struct protoent * +.Fn bt_getprotoent void +.Ft void +.Fn bt_setprotoent "int stayopen" +.Ft void +.Fn bt_endprotoent void +.Ft int +.Fn bt_aton "const char *str" "bdaddr_t *ba" +.Ft const char * +.Fn bt_ntoa "const bdaddr_t *ba" "char *str" +.Sh DESCRIPTION +The +.Fn bt_gethostent , +.Fn bt_gethostbyname +and +.Fn bt_gethostbyaddr +functions +each return a pointer to an object with the +.Vt hostent +structure describing a Bluetooth host +referenced by name or by address, respectively. +.Pp +The +.Fa name +argument passed to +.Fn bt_gethostbyname +should point to a +.Dv NUL Ns -terminated +hostname. +The +.Fa addr +argument passed to +.Fn bt_gethostbyaddr +should point to an address which is +.Fa len +bytes long, +in binary form +(i.e. not an Bluetooth BD_ADDR in human readable +.Tn ASCII +form). +The +.Fa type +argument specifies the address family of this address and must be set to +.Dv AF_BLUETOOTH . +.Pp +The structure returned contains the information obtained from a line in +.Pa /etc/bluetooth/hosts +file. +.Pp +The +.Fn bt_sethostent +function controls whether +.Pa /etc/bluetooth/hosts +file should stay open after each call to +.Fn bt_gethostbyname +or +.Fn bt_gethostbyaddr . +If the +.Fa stayopen +flag is non-zero, the file will not be closed. +.Pp +The +.Fn bt_endhostent +function closes the +.Pa /etc/bluetooth/hosts +file. +.Pp +The +.Fn bt_getprotoent , +.Fn bt_getprotobyname +and +.Fn bt_getprotobynumber +functions each return a pointer to an object with the +.Vt protoent +structure describing a Bluetooth Protocol Service Multiplexor referenced +by name or number, respectively. +.Pp +The +.Fa name +argument passed to +.Fn bt_getprotobyname +should point to a +.Dv NUL Ns -terminated +Bluetooth Protocol Service Multiplexor name. +The +.Fa proto +argument passed to +.Fn bt_getprotobynumber +should have numeric value of the desired Bluetooth Protocol Service Multiplexor. +.Pp +The structure returned contains the information obtained from a line in +.Pa /etc/bluetooth/protocols +file. +.Pp +The +.Fn bt_setprotoent +function controls whether +.Pa /etc/bluetooth/protocols +file should stay open after each call to +.Fn bt_getprotobyname +or +.Fn bt_getprotobynumber . +If the +.Fa stayopen +flag is non-zero, the file will not be closed. +.Pp +The +.Fn bt_endprotoent +function closes the +.Pa /etc/bluetooth/protocols +file. +.Pp +The +.Fn bt_aton +routine interprets the specified character string as a Bluetooth address, +placing the address into the structure provided. +It returns 1 if the string was successfully interpreted, +or 0 if the string is invalid. +.Pp +The routine +.Fn bt_ntoa +takes a Bluetooth address and places an +.Tn ASCII +string representing the address into the buffer provided. +It is up to the caller to ensure that provided buffer has enough space. +If no buffer was provided then internal static buffer will be used. +.Sh FILES +.Bl -tag -width /etc/bluetooth/hosts -compact +.It Pa /etc/bluetooth/hosts +.It Pa /etc/bluetooth/protocols +.El +.Sh EXAMPLES +Print out the hostname associated with a specific BD_ADDR: +.Bd -literal -offset indent +const char *bdstr = "00:01:02:03:04:05"; +bdaddr_t bd; +struct hostent *hp; + +if (!bt_aton(bdstr, &bd)) + errx(1, "can't parse BD_ADDR %s", bdstr); + +if ((hp = bt_gethostbyaddr((const char *)&bd, + sizeof(bd), AF_BLUETOOTH)) == NULL) + errx(1, "no name associated with %s", bdstr); + +printf("name associated with %s is %s\en", bdstr, hp->h_name); +.Ed +.Sh DIAGNOSTICS +Error return status from +.Fn bt_gethostent , +.Fn bt_gethostbyname +and +.Fn bt_gethostbyaddr +is indicated by return of a +.Dv NULL +pointer. +The external integer +.Va h_errno +may then be checked to see whether this is a temporary failure +or an invalid or unknown host. +The routine +.Fn herror +can be used to print an error message describing the failure. +If its argument +.Fa string +is +.Pf non- Dv NULL , +it is printed, followed by a colon and a space. +The error message is printed with a trailing newline. +.Pp +The variable +.Va h_errno +can have the following values: +.Bl -tag -width HOST_NOT_FOUND +.It Dv HOST_NOT_FOUND +No such host is known. +.It Dv NO_RECOVERY +Some unexpected server failure was encountered. +This is a non-recoverable error. +.El +.Pp +The +.Fn bt_getprotoent , +.Fn bt_getprotobyname +and +.Fn bt_getprotobynumber +return Null pointer (0) on +.Dv EOF +or error. +.Sh SEE ALSO +.Xr gethostbyaddr 3 , +.Xr gethostbyname 3 , +.Xr getprotobyaddr 3 , +.Xr getprotobynumber 3 , +.Xr herror 3 , +.Xr inet_aton 3 , +.Xr inet_ntoa 3 +.Sh CAVEAT +The +.Fn bt_gethostent +function reads the next line of +.Pa /etc/bluetooth/hosts , +opening the file if necessary. +.Pp +The +.Fn bt_sethostent +function opens and/or rewinds the +.Pa /etc/bluetooth/hosts +file. +.Pp +The +.Fn bt_getprotoent +function reads the next line of +.Pa /etc/bluetooth/protocols , +opening the file if necessary. +.Pp +The +.Fn bt_setprotoent +function opens and/or rewinds the +.Pa /etc/bluetooth/protocols +file. +.Sh BUGS +These functions use static data storage; +if the data is needed for future use, it should be +copied before any subsequent calls overwrite it. +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/lib/libbluetooth/bluetooth.c b/lib/libbluetooth/bluetooth.c new file mode 100644 index 0000000..4678509 --- /dev/null +++ b/lib/libbluetooth/bluetooth.c @@ -0,0 +1,369 @@ +/* + * bluetooth.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: bluetooth.c,v 1.3 2003/05/20 23:04:30 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define _PATH_BT_HOSTS "/etc/bluetooth/hosts" +#define _PATH_BT_PROTOCOLS "/etc/bluetooth/protocols" +#define MAXALIASES 35 + +static FILE *hostf = NULL; +static int host_stayopen = 0; +static struct hostent host; +static bdaddr_t host_addr; +static char *host_addr_ptrs[2]; +static char *host_aliases[MAXALIASES]; + +static FILE *protof = NULL; +static int proto_stayopen = 0; +static struct protoent proto; +static char *proto_aliases[MAXALIASES]; + +static char buf[BUFSIZ + 1]; + +static int bt_hex_byte (char const *str); +static int bt_hex_nibble (char nibble); + +struct hostent * +bt_gethostbyname(char const *name) +{ + struct hostent *p; + char **cp; + + bt_sethostent(host_stayopen); + while ((p = bt_gethostent()) != NULL) { + if (strcasecmp(p->h_name, name) == 0) + break; + for (cp = p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0) + goto found; + } +found: + bt_endhostent(); + + return (p); +} + +struct hostent * +bt_gethostbyaddr(char const *addr, int len, int type) +{ + struct hostent *p; + + if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) { + h_errno = NO_RECOVERY; + return (NULL); + } + + bt_sethostent(host_stayopen); + while ((p = bt_gethostent()) != NULL) + if (p->h_addrtype == type && bcmp(p->h_addr, addr, len) == 0) + break; + bt_endhostent(); + + return (p); +} + +struct hostent * +bt_gethostent(void) +{ + char *p, *cp, **q; + + if (hostf == NULL) + hostf = fopen(_PATH_BT_HOSTS, "r"); + + if (hostf == NULL) { + h_errno = NETDB_INTERNAL; + return (NULL); + } +again: + if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) == NULL) + goto again; + *cp = 0; + if ((cp = strpbrk(p, " \t")) == NULL) + goto again; + *cp++ = 0; + if (bt_aton(p, &host_addr) == 0) + goto again; + host_addr_ptrs[0] = (char *) &host_addr; + host_addr_ptrs[1] = NULL; + host.h_addr_list = host_addr_ptrs; + host.h_length = sizeof(host_addr); + host.h_addrtype = AF_BLUETOOTH; + while (*cp == ' ' || *cp == '\t') + cp++; + host.h_name = cp; + q = host.h_aliases = host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = 0; + while (cp != NULL && *cp != 0) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = 0; + } + *q = NULL; + h_errno = NETDB_SUCCESS; + + return (&host); +} + +void +bt_sethostent(int stayopen) +{ + if (hostf == NULL) + hostf = fopen(_PATH_BT_HOSTS, "r"); + else + rewind(hostf); + + host_stayopen = stayopen; +} + +void +bt_endhostent(void) +{ + if (hostf != NULL && host_stayopen == 0) { + (void) fclose(hostf); + hostf = NULL; + } +} + +struct protoent * +bt_getprotobyname(char const *name) +{ + struct protoent *p; + char **cp; + + bt_setprotoent(proto_stayopen); + while ((p = bt_getprotoent()) != NULL) { + if (strcmp(p->p_name, name) == 0) + break; + for (cp = p->p_aliases; *cp != 0; cp++) + if (strcmp(*cp, name) == 0) + goto found; + } +found: + bt_endprotoent(); + + return (p); +} + +struct protoent * +bt_getprotobynumber(int proto) +{ + struct protoent *p; + + bt_setprotoent(proto_stayopen); + while ((p = bt_getprotoent()) != NULL) + if (p->p_proto == proto) + break; + bt_endprotoent(); + + return (p); +} + +struct protoent * +bt_getprotoent(void) +{ + char *p, *cp, **q; + + if (protof == NULL) + protof = fopen(_PATH_BT_PROTOCOLS, "r"); + + if (protof == NULL) + return (NULL); +again: + if ((p = fgets(buf, sizeof(buf), protof)) == NULL) + return (NULL); + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) == NULL) + goto again; + *cp = '\0'; + proto.p_name = p; + if ((cp = strpbrk(p, " \t")) == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((p = strpbrk(cp, " \t")) != NULL) + *p++ = '\0'; + proto.p_proto = atoi(cp); + q = proto.p_aliases = proto_aliases; + if (p != NULL) { + cp = p; + while (cp != NULL && *cp != 0) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &proto_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + + return (&proto); +} + +void +bt_setprotoent(int stayopen) +{ + if (protof == NULL) + protof = fopen(_PATH_BT_PROTOCOLS, "r"); + else + rewind(protof); + + proto_stayopen = stayopen; +} + +void +bt_endprotoent(void) +{ + if (protof != NULL) { + (void) fclose(protof); + protof = NULL; + } +} + +char const * +bt_ntoa(bdaddr_t const *ba, char *str) +{ + static char buffer[24]; + + if (str == NULL) + str = buffer; + + sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]); + + return (str); +} + +int +bt_aton(char const *str, bdaddr_t *ba) +{ + int i, b; + char *end = NULL; + + memset(ba, 0, sizeof(*ba)); + + for (i = 5, end = strchr(str, ':'); + i > 0 && *str != NULL && end != NULL; + i --, str = end + 1, end = strchr(str, ':')) { + switch (end - str) { + case 1: + b = bt_hex_nibble(str[0]); + break; + + case 2: + b = bt_hex_byte(str); + break; + + default: + b = -1; + break; + } + + if (b < 0) + return (0); + + ba->b[i] = b; + } + + if (i != 0 || end != NULL || *str == 0) + return (0); + + switch (strlen(str)) { + case 1: + b = bt_hex_nibble(str[0]); + break; + + case 2: + b = bt_hex_byte(str); + break; + + default: + b = -1; + break; + } + + if (b < 0) + return (0); + + ba->b[i] = b; + + return (1); +} + +static int +bt_hex_byte(char const *str) +{ + int n1, n2; + + if ((n1 = bt_hex_nibble(str[0])) < 0) + return (-1); + + if ((n2 = bt_hex_nibble(str[1])) < 0) + return (-1); + + return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff); +} + +static int +bt_hex_nibble(char nibble) +{ + if ('0' <= nibble && nibble <= '9') + return (nibble - '0'); + + if ('a' <= nibble && nibble <= 'f') + return (nibble - 'a' + 0xa); + + if ('A' <= nibble && nibble <= 'F') + return (nibble - 'A' + 0xa); + + return (-1); +} + diff --git a/lib/libbluetooth/bluetooth.h b/lib/libbluetooth/bluetooth.h new file mode 100644 index 0000000..516f691 --- /dev/null +++ b/lib/libbluetooth/bluetooth.h @@ -0,0 +1,78 @@ +/* + * bluetooth.h + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: bluetooth.h,v 1.5 2003/09/14 23:28:42 max Exp $ + * $FreeBSD$ + */ + +#ifndef _BLUETOOTH_H_ +#define _BLUETOOTH_H_ + +#include <sys/types.h> +#include <sys/bitstring.h> +#include <sys/endian.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netdb.h> +#include <netgraph/bluetooth/include/ng_hci.h> +#include <netgraph/bluetooth/include/ng_l2cap.h> +#include <netgraph/bluetooth/include/ng_btsocket.h> + +__BEGIN_DECLS + +/* + * Lunux BlueZ compatibility + */ + +#define bacmp(ba1, ba2) memcmp((ba1), (ba2), sizeof(bdaddr_t)) +#define bacpy(dst, src) memcpy((dst), (src), sizeof(bdaddr_t)) +#define ba2str(ba, str) bt_ntoa((ba), (str)) +#define str2ba(str, ba) (bt_aton((str), (ba)) == 1? 0 : -1) + +/* + * Interface to the outside world + */ + +struct hostent * bt_gethostbyname (char const *name); +struct hostent * bt_gethostbyaddr (char const *addr, int len, int type); +struct hostent * bt_gethostent (void); +void bt_sethostent (int stayopen); +void bt_endhostent (void); + +struct protoent * bt_getprotobyname (char const *name); +struct protoent * bt_getprotobynumber (int proto); +struct protoent * bt_getprotoent (void); +void bt_setprotoent (int stayopen); +void bt_endprotoent (void); + +char const * bt_ntoa (bdaddr_t const *ba, char *str); +int bt_aton (char const *str, bdaddr_t *ba); + +__END_DECLS + +#endif /* ndef _BLUETOOTH_H_ */ + diff --git a/lib/libsdp/Makefile b/lib/libsdp/Makefile new file mode 100644 index 0000000..4df7471 --- /dev/null +++ b/lib/libsdp/Makefile @@ -0,0 +1,33 @@ +# $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $ +# $FreeBSD$ + +LIB= sdp +MAN= sdp.3 + +WARNS?= 2 +CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys + +SHLIB_MAJOR= 1 + +SRCS= search.c session.c util.c +INCS= sdp.h + +MLINKS+= sdp.3 SDP_GET8.3 +MLINKS+= sdp.3 SDP_GET16.3 +MLINKS+= sdp.3 SDP_GET32.3 +MLINKS+= sdp.3 SDP_GET64.3 +MLINKS+= sdp.3 SDP_GET128.3 +MLINKS+= sdp.3 SDP_PUT8.3 +MLINKS+= sdp.3 SDP_PUT16.3 +MLINKS+= sdp.3 SDP_PUT32.3 +MLINKS+= sdp.3 SDP_PUT64.3 +MLINKS+= sdp.3 SDP_PUT128.3 +MLINKS+= sdp.3 sdp_open.3 +MLINKS+= sdp.3 sdp_open_local.3 +MLINKS+= sdp.3 sdp_close.3 +MLINKS+= sdp.3 sdp_error.3 +MLINKS+= sdp.3 sdp_search.3 +MLINKS+= sdp.3 sdp_attr2desc.3 +MLINKS+= sdp.3 sdp_uuid2desc.3 + +.include <bsd.lib.mk> diff --git a/lib/libsdp/sdp-int.h b/lib/libsdp/sdp-int.h new file mode 100644 index 0000000..95aeb43 --- /dev/null +++ b/lib/libsdp/sdp-int.h @@ -0,0 +1,65 @@ +/* + * sdp-int.h + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdp-int.h,v 1.1 2003/09/01 23:01:07 max Exp $ + * $FreeBSD$ + */ + +#ifndef _SDP_INT_H_ +#define _SDP_INT_H_ + +__BEGIN_DECLS + +#define SDP_UNSOCK_PATH "/var/run/sdp" +#define SDP_UNSOCK_MTU 2048 + +/* + * SDP session + */ + +struct sdp_session { + u_int16_t flags; +#define SDP_SESSION_LOCAL (1 << 0) + u_int16_t tid; /* current session transaction ID (tid) */ + u_int16_t omtu; /* outgoing MTU (req buffer size) */ + u_int16_t imtu; /* incoming MTU (rsp buffer size) */ + u_int8_t *req; /* request buffer (start) */ + u_int8_t *req_e; /* request buffer (end) */ + u_int8_t *rsp; /* response buffer (start) */ + u_int8_t *rsp_e; /* response buffer (end) */ + u_int32_t cslen; /* continuation state length */ + u_int8_t cs[16];/* continuation state */ + int32_t s; /* L2CAP socket */ + int32_t error; /* last error code */ +}; +typedef struct sdp_session sdp_session_t; +typedef struct sdp_session * sdp_session_p; + +__END_DECLS + +#endif /* ndef _SDP_INT_H_ */ + diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3 new file mode 100644 index 0000000..94ef34e --- /dev/null +++ b/lib/libsdp/sdp.3 @@ -0,0 +1,309 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $ +.\" $FreeBSD$ +.\" +.Dd September 7, 2003 +.Dt SDP 3 +.Os +.Sh NAME +.Nm SDP_GET8 , +.Nm SDP_GET16 , +.Nm SDP_GET32 , +.Nm SDP_GET64 , +.Nm SDP_GET128 +.Nd get SDP integer +.Pp +.Nm SDP_PUT8 , +.Nm SDP_PUT16 , +.Nm SDP_PUT32 , +.Nm SDP_PUT64 , +.Nm SDP_PUT128 +.Nd put SPD integer +.Pp +.Nm sdp_open , +.Nm sdp_open_local , +.Nm sdp_close +.Nm sdp_error +.Nd control SDP session +.Pp +.Nm sdp_search +.Nd perform SDP query +.Pp +.Nm sdp_attr2desc , +.Nm sdp_uuid2desc +.Nd convert numeric SDP attribute/UUID value into human readable description +.Sh LIBRARY +.Lb libsdp +.Sh SYNOPSIS +.In bluetooth.h +.In sdp.h +.Fn SDP_GET8 "b" "cp" +.Fn SDP_GET16 "s" "cp" +.Fn SDP_GET32 "l" "cp" +.Fn SDP_GET64 "l" "cp" +.Fn SDP_GET128 "l" "cp" +.Fn SDP_PUT8 "b" "cp" +.Fn SDP_PUT16 "s" "cp" +.Fn SDP_PUT32 "l" "cp" +.Fn SDP_PUT64 "l" "cp" +.Fn SDP_PUT128 "l" "cp" +.Ft void * +.Fn sdp_open "bdaddr_t const *l" "bdaddr_t const *r" +.Ft void * +.Fn sdp_open_local "void" +.Ft int32_t +.Fn sdp_close "void *xs" +.Ft int32_t +.Fn sdp_error "void *xs" +.Ft int32_t +.Fn sdp_search "void *xs" "u_int32_t plen" "u_int16_t const *pp" "u_int32_t alen" "u_int32_t const *ap" "u_int32_t vlen" "sdp_attr_t *vp" +.Ft char const * const +.Fn sdp_attr2desc "u_int16_t attr" +.Ft char const * const +.Fn sdp_uuid2desc "u_int16_t uuid" +.Sh DESCRIPTION +The +.Fn SDP_GET8 , +.Fn SDP_GET16 , +.Fn SDP_GET32 , +.Fn SDP_GET64 +and +.Fn SDP_GET128 +macros are used to get byte, short, long, long long and 128-bit integer +from the buffer pointed by +.Vt cp +pointer. The pointer is automatically advanced. +.Pp +The +.Fn SDP_PUT8 , +.Fn SDP_PUT16 , +.Fn SDP_PUT32 , +.Fn SDP_PUT64 +and +.Fn SDP_PUT128 +macros are used to put byte, short, long, long long and 128-bit integer +into the buffer pointed by +.Vt cp +pointer. The pointer is automatically advanced. +.Pp +.Fn sdp_open +and +.Fn sdp_open_local +functions each return a pointer to an opaque object describing SDP session. +The +.Vt l +argument passed to +.Fn sdp_open +function should point to a source BD_ADDR. +If source BD_ADDR is +.Dv NULL +then source address +.Dv NG_HCI_BDADDR_ANY +is used. +The +.Vt r +argument passed to +.Fn sdp_open +function should point to a non +.Dv NULL +remote BD_ADDR. +Remote BD_ADDR can not be +.Dv NG_HCI_BDADDR_ANY . +The +.Fn sdp_open_local +function takes no arguments and opens a connection to a local SDP server. +.Pp +The +.Fn sdp_close +function terminates active SDP session and deletes SDP session object. +The +.Vt xs +parameter should point to a valid SDP session object created with +.Fn sdp_open +or +.Fn sdp_open_local . +.Pp +The +.Fn sdp_error +function returns last error that is stored inside SDP session object. +The +.Vt xs +parameter should point to a valid SDP session object created with +.Fn sdp_open +or +.Fn sdp_open_local . +The error value returned can be converted to a human readable message by +calling +.Xr strerror 3 +function. +.Pp +The +.Fn sdp_search +function is used to perform SDP Service Search Attribute Request. +The +.Vt xs +parameter should point to a valid SDP session object created with +.Fn sdp_open +or +.Fn sdp_open_local . +The +.Vt pp +parameter is a Service Search Pattern - an array of one or more Service +Class IDs. +The maximum number of Service Class IDs in the array is 12. +The +.Vt plen +parameter is the length of the Service Search pattern. +The +.Vt ap +parameter is a Attribute ID Range List - an array of one or more SDP Attribute +ID Range. Each attribute ID Range is encoded as a 32-bit unsigned integer data +element, where the high order 16 bits are interpreted as the beginning +attribute ID of the range and the low order 16 bits are interpreted as the +ending attribute ID of the range. +The attribute IDs contained in the Attribute ID Ranges List must be listed in +ascending order without duplication of any attribute ID values. +Note that all attributes may be requested by specifying a range of +0x0000-0xFFFF. +The +.Vt alen +parameter is the length of the Attribute ID Ranges List. +The +.Fn SDP_ATTR_RANGE "lo" "hi" +macro can be used to prepare Attribute ID Range. +The +.Vt vp +parameter should be an array of +.Vt sdp_attr_t +structures. +Each +.Vt sdp_attr_t +structure describes single SDP attribute and defined as follows: +.Bd -literal -offset indent +struct sdp_attr { + u_int16_t flags; +#define SDP_ATTR_OK (0 << 0) +#define SDP_ATTR_INVALID (1 << 0) +#define SDP_ATTR_TRUNCATED (1 << 1) + u_int16_t attr; /* SDP_ATTR_xxx */ + u_int32_t vlen; /* length of the value[] in bytes */ + u_int8_t *value; /* base pointer */ +}; +typedef struct sdp_attr sdp_attr_t; +typedef struct sdp_attr * sdp_attr_p; +.Ed +.Pp +The caller of the +.Fn sdp_search +function is expected to prepare the array of +.Vt sdp_attr +structures and for each element of the array both +.Vt vlen +and +.Vt value +must be set. +The +.Fn sdp_search +function will fill each +.Vt sdp_attr_t +structure with attribute and value, i.e. it will set +.Vt flags , +.Vt attr +and +.Vt vlen +fields. +The actual value of the attribute will be copied into +.Vt value +buffer. +Note: attributes are returned in the order they appear in the Service Search +Attribute Response. +SDP server could return several attributes for the same record. +In this case the order of the attributes will be: all attributes for the first +records, then all attributes for the secord record etc. +.Pp +The +.Fn sdp_attr2desc +and +.Fn sdp_uuid2desc +functions each take a numeric attribute ID/UUID value and convert it to a +human readable description. +.Sh EXAMPLES +The following example shows how to get +.Dv SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST +attribute for the +.Dv SDP_SERVICE_CLASS_SERIAL_PORT +service from the remote device. +.Bd -literal -offset indent +bdaddr_t remote; +u_int8_t buffer[1024]; +void *ss = NULL; +u_int16_t serv = SDP_SERVICE_CLASS_SERIAL_PORT; +u_int32_t attr = SDP_ATTR_RANGE( + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); +sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer }; + +/* Obtain/set remote BDADDR here */ + +if ((ss = sdp_open(NG_HCI_BDADDR_ANY, remote)) == NULL) + /* exit ENOMEM */ +if (sdp_error(ss) != 0) + /* exit spd_error(ss) */ + +if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0) + /* exit sdp_error(ss) */ + +if (proto.flags != SDP_ATTR_OK) + /* exit see proto.flags for details */ + +/* If we got here then we have attribute value in proto.value */ +.Ed +.Sh DIAGNOSTICS +Both +.Fn sdp_open +and +.Fn sdp_open_local +will return +.Dv NULL +if memory allocation for the new SDP session object fails. +If the new SDP object was created then caller is still expected to call +.Fn sdp_error +to check if there was connection error. +.Pp +The +.Fn sdp_search +function returns non-zero value on error. +The caller is expected to call +.Fn sdp_error +to find out more about error. +.Sh SEE ALSO +.Xr bluetooth 3 , +.Xr strerror 3 +.Sh BUGS +This is client only library for now. +Please report bugs if found. +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h new file mode 100644 index 0000000..83f5977 --- /dev/null +++ b/lib/libsdp/sdp.h @@ -0,0 +1,477 @@ +/* + * sdp.h + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdp.h,v 1.3 2003/09/05 00:33:59 max Exp $ + * $FreeBSD$ + */ + +#ifndef _SDP_H_ +#define _SDP_H_ + +__BEGIN_DECLS + +/* + * Data representation (page 349) + */ + +/* Nil, the null type */ +#define SDP_DATA_NIL 0x00 + +/* Unsigned integer */ +#define SDP_DATA_UINT8 0x08 +#define SDP_DATA_UINT16 0x09 +#define SDP_DATA_UINT32 0x0A +#define SDP_DATA_UINT64 0x0B +#define SDP_DATA_UINT128 0x0C + +/* Signed two's-complement integer */ +#define SDP_DATA_INT8 0x10 +#define SDP_DATA_INT16 0x11 +#define SDP_DATA_INT32 0x12 +#define SDP_DATA_INT64 0x13 +#define SDP_DATA_INT128 0x14 + +/* UUID, a universally unique identifier */ +#define SDP_DATA_UUID16 0x19 +#define SDP_DATA_UUID32 0x1A +#define SDP_DATA_UUID128 0x1C + +/* Text string */ +#define SDP_DATA_STR8 0x25 +#define SDP_DATA_STR16 0x26 +#define SDP_DATA_STR32 0x27 + +/* Boolean */ +#define SDP_DATA_BOOL 0x28 + +/* + * Data element sequence. + * A data element whose data field is a sequence of data elements + */ +#define SDP_DATA_SEQ8 0x35 +#define SDP_DATA_SEQ16 0x36 +#define SDP_DATA_SEQ32 0x37 + +/* + * Data element alternative. + * A data element whose data field is a sequence of data elements from + * which one data element is to be selected. + */ +#define SDP_DATA_ALT8 0x3D +#define SDP_DATA_ALT16 0x3E +#define SDP_DATA_ALT32 0x3F + +/* URL, a uniform resource locator */ +#define SDP_DATA_URL8 0x45 +#define SDP_DATA_URL16 0x46 +#define SDP_DATA_URL32 0x47 + +/* + * Protocols UUID (short) http://www.bluetoothsig.org/assigned-numbers/sdp.htm + * BASE UUID 00000000-0000-1000-8000-00805F9B34FB + */ + +#define SDP_UUID_PROTOCOL_SDP 0x0001 +#define SDP_UUID_PROTOCOL_UDP 0x0002 +#define SDP_UUID_PROTOCOL_RFCOMM 0x0003 +#define SDP_UUID_PROTOCOL_TCP 0x0004 +#define SDP_UUID_PROTOCOL_TCS_BIN 0x0005 +#define SDP_UUID_PROTOCOL_TCS_AT 0x0006 +#define SDP_UUID_PROTOCOL_OBEX 0x0008 +#define SDP_UUID_PROTOCOL_IP 0x0009 +#define SDP_UUID_PROTOCOL_FTP 0x000A +#define SDP_UUID_PROTOCOL_HTTP 0x000C +#define SDP_UUID_PROTOCOL_WSP 0x000E +#define SDP_UUID_PROTOCOL_BNEP 0x000F +#define SDP_UUID_PROTOCOL_UPNP 0x0010 +#define SDP_UUID_PROTOCOL_HIDP 0x0011 +#define SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL 0x0012 +#define SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL 0x0014 +#define SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION 0x0016 +#define SDP_UUID_PROTOCOL_AVCTP 0x0017 +#define SDP_UUID_PROTOCOL_AVDTP 0x0019 +#define SDP_UUID_PROTOCOL_CMPT 0x001B +#define SDP_UUID_PROTOCOL_UDI_C_PLANE 0x001D +#define SDP_UUID_PROTOCOL_L2CAP 0x0100 + +/* + * Service class IDs http://www.bluetoothsig.org/assigned-numbers/sdp.htm + */ + +#define SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER 0x1000 +#define SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR 0x1001 +#define SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP 0x1002 +#define SDP_SERVICE_CLASS_SERIAL_PORT 0x1101 +#define SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP 0x1102 +#define SDP_SERVICE_CLASS_DIALUP_NETWORKING 0x1103 +#define SDP_SERVICE_CLASS_IR_MC_SYNC 0x1104 +#define SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH 0x1105 +#define SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER 0x1106 +#define SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND 0x1107 +#define SDP_SERVICE_CLASS_HEADSET 0x1108 +#define SDP_SERVICE_CLASS_CORDLESS_TELEPHONY 0x1109 +#define SDP_SERVICE_CLASS_AUDIO_SOURCE 0x110A +#define SDP_SERVICE_CLASS_AUDIO_SINK 0x110B +#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET 0x110C +#define SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION 0x110D +#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL 0x110E +#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING 0x110F +#define SDP_SERVICE_CLASS_INTERCOM 0x1110 +#define SDP_SERVICE_CLASS_FAX 0x1111 +#define SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY 0x1112 +#define SDP_SERVICE_CLASS_WAP 0x1113 +#define SDP_SERVICE_CLASS_WAP_CLIENT 0x1114 +#define SDP_SERVICE_CLASS_PANU 0x1115 +#define SDP_SERVICE_CLASS_NAP 0x1116 +#define SDP_SERVICE_CLASS_GN 0x1117 +#define SDP_SERVICE_CLASS_DIRECT_PRINTING 0x1118 +#define SDP_SERVICE_CLASS_REFERENCE_PRINTING 0x1119 +#define SDP_SERVICE_CLASS_IMAGING 0x111A +#define SDP_SERVICE_CLASS_IMAGING_RESPONDER 0x111B +#define SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE 0x111C +#define SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS 0x111D +#define SDP_SERVICE_CLASS_HANDSFREE 0x111E +#define SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY 0x111F +#define SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS 0x1120 +#define SDP_SERVICE_CLASS_REFLECTED_UI 0x1121 +#define SDP_SERVICE_CLASS_BASIC_PRINTING 0x1122 +#define SDP_SERVICE_CLASS_PRINTING_STATUS 0x1123 +#define SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE 0x1124 +#define SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT 0x1125 +#define SDP_SERVICE_CLASS_HCR_PRINT 0x1126 +#define SDP_SERVICE_CLASS_HCR_SCAN 0x1127 +#define SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS 0x1128 +#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW 0x1129 +#define SDP_SERVICE_CLASS_UDI_MT 0x112A +#define SDP_SERVICE_CLASS_UDI_TA 0x112B +#define SDP_SERVICE_CLASS_AUDIO_VIDEO 0x112C +#define SDP_SERVICE_CLASS_SIM_ACCESS 0x112D +#define SDP_SERVICE_CLASS_PNP_INFORMATION 0x1200 +#define SDP_SERVICE_CLASS_GENERIC_NETWORKING 0x1201 +#define SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER 0x1202 +#define SDP_SERVICE_CLASS_GENERIC_AUDIO 0x1203 +#define SDP_SERVICE_CLASS_GENERIC_TELEPHONY 0x1204 +#define SDP_SERVICE_CLASS_UPNP 0x1205 +#define SDP_SERVICE_CLASS_UPNP_IP 0x1206 +#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN 0x1300 +#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP 0x1301 +#define SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP 0x1302 + +/* + * Universal attribute definitions (page 366) and + * http://www.bluetoothsig.org/assigned-numbers/sdp.htm + */ + +#define SDP_ATTR_RANGE(lo, hi) \ + (u_int32_t)(((u_int16_t)(lo) << 16) | ((u_int16_t)(hi))) + +#define SDP_ATTR_SERVICE_RECORD_HANDLE 0x0000 +#define SDP_ATTR_SERVICE_CLASS_ID_LIST 0x0001 +#define SDP_ATTR_SERVICE_RECORD_STATE 0x0002 +#define SDP_ATTR_SERVICE_ID 0x0003 +#define SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST 0x0004 +#define SDP_ATTR_BROWSE_GROUP_LIST 0x0005 +#define SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST 0x0006 +#define SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE 0x0007 +#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008 +#define SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST 0x0009 +#define SDP_ATTR_DOCUMENTATION_URL 0x000A +#define SDP_ATTR_CLIENT_EXECUTABLE_URL 0x000B +#define SDP_ATTR_ICON_URL 0x000C +#define SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS 0x000D +#define SDP_ATTR_GROUP_ID 0x0200 +#define SDP_ATTR_IP_SUBNET 0x0200 +#define SDP_ATTR_VERSION_NUMBER_LIST 0x0200 +#define SDP_ATTR_SERVICE_DATABASE_STATE 0x0201 +#define SDP_ATTR_SERVICE_VERSION 0x0300 +#define SDP_ATTR_EXTERNAL_NETWORK 0x0301 +#define SDP_ATTR_NETWORK 0x0301 +#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301 +#define SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302 +#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302 +#define SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303 +#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303 +#define SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304 +#define SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305 +#define SDP_ATTR_NETWORK_ADDRESS 0x0306 +#define SDP_ATTR_WAP_GATEWAY 0x0307 +#define SDP_ATTR_HOME_PAGE_URL 0x0308 +#define SDP_ATTR_WAP_STACK_TYPE 0x0309 +#define SDP_ATTR_SECURITY_DESCRIPTION 0x030A +#define SDP_ATTR_NET_ACCESS_TYPE 0x030B +#define SDP_ATTR_MAX_NET_ACCESS_RATE 0x030C +#define SDP_ATTR_IPV4_SUBNET 0x030D +#define SDP_ATTR_IPV6_SUBNET 0x030E +#define SDP_ATTR_SUPPORTED_CAPABALITIES 0x0310 +#define SDP_ATTR_SUPPORTED_FEATURES 0x0311 +#define SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312 +#define SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313 + +/* + * The offset must be added to the attribute ID base (contained in the + * LANGUAGE_BASE_ATTRIBUTE_ID_LIST attribute) in order to compute the + * attribute ID for these attributes. + */ + +#define SDP_ATTR_SERVICE_NAME_OFFSET 0x0000 +#define SDP_ATTR_SERVICE_DESCRIPTION_OFFSET 0x0001 +#define SDP_ATTR_PROVIDER_NAME_OFFSET 0x0002 + +/* + * Protocol data unit (PDU) format (page 352) + */ + +#define SDP_PDU_ERROR_RESPONSE 0x01 +#define SDP_PDU_SERVICE_SEARCH_REQUEST 0x02 +#define SDP_PDU_SERVICE_SEARCH_RESPONSE 0x03 +#define SDP_PDU_SERVICE_ATTRIBUTE_REQUEST 0x04 +#define SDP_PDU_SERVICE_ATTRIBUTE_RESPONSE 0x05 +#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST 0x06 +#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_RESPONSE 0x07 + +struct sdp_pdu { + u_int8_t pid; /* PDU ID - SDP_PDU_xxx */ + u_int16_t tid; /* transaction ID */ + u_int16_t len; /* parameters length (in bytes) */ +} __attribute__ ((packed)); +typedef struct sdp_pdu sdp_pdu_t; +typedef struct sdp_pdu * sdp_pdu_p; + +/* + * SDP int128/uint128 parameter + */ + +struct int128 { + int8_t b[16]; +}; +typedef struct int128 int128_t; +typedef struct int128 u_int128_t; + +/* + * SDP attribute + */ + +struct sdp_attr { + u_int16_t flags; +#define SDP_ATTR_OK (0 << 0) +#define SDP_ATTR_INVALID (1 << 0) +#define SDP_ATTR_TRUNCATED (1 << 1) + u_int16_t attr; /* SDP_ATTR_xxx */ + u_int32_t vlen; /* length of the value[] in bytes */ + u_int8_t *value; /* base pointer */ +}; +typedef struct sdp_attr sdp_attr_t; +typedef struct sdp_attr * sdp_attr_p; + +/****************************************************************************** + * User interface + *****************************************************************************/ + +/* Inline versions of get/put byte/short/long. Pointer is advanced */ +#define SDP_GET8(b, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (b) = *t_cp; \ + (cp) ++; \ +} + +#define SDP_GET16(s, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += 2; \ +} + +#define SDP_GET32(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += 4; \ +} + +#define SDP_GET64(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (l) = ((u_int64_t)t_cp[0] << 56) \ + | ((u_int64_t)t_cp[1] << 48) \ + | ((u_int64_t)t_cp[2] << 40) \ + | ((u_int64_t)t_cp[3] << 32) \ + | ((u_int64_t)t_cp[4] << 24) \ + | ((u_int64_t)t_cp[5] << 16) \ + | ((u_int64_t)t_cp[6] << 8) \ + | ((u_int64_t)t_cp[7]) \ + ; \ + (cp) += 8; \ +} + +#if BYTE_ORDER == LITTLE_ENDIAN +#define SDP_GET128(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (l)->b[15] = *t_cp++; \ + (l)->b[14] = *t_cp++; \ + (l)->b[13] = *t_cp++; \ + (l)->b[12] = *t_cp++; \ + (l)->b[11] = *t_cp++; \ + (l)->b[10] = *t_cp++; \ + (l)->b[9] = *t_cp++; \ + (l)->b[8] = *t_cp++; \ + (l)->b[7] = *t_cp++; \ + (l)->b[6] = *t_cp++; \ + (l)->b[5] = *t_cp++; \ + (l)->b[4] = *t_cp++; \ + (l)->b[3] = *t_cp++; \ + (l)->b[2] = *t_cp++; \ + (l)->b[1] = *t_cp++; \ + (cp) += 16; \ +} +#else /* BYTE_ORDER != LITTLE_ENDIAN */ +#define SDP_GET128(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + (l)->b[0] = *t_cp++; \ + (l)->b[1] = *t_cp++; \ + (l)->b[2] = *t_cp++; \ + (l)->b[3] = *t_cp++; \ + (l)->b[4] = *t_cp++; \ + (l)->b[5] = *t_cp++; \ + (l)->b[6] = *t_cp++; \ + (l)->b[7] = *t_cp++; \ + (l)->b[8] = *t_cp++; \ + (l)->b[9] = *t_cp++; \ + (l)->b[10] = *t_cp++; \ + (l)->b[11] = *t_cp++; \ + (l)->b[12] = *t_cp++; \ + (l)->b[13] = *t_cp++; \ + (l)->b[14] = *t_cp++; \ + (l)->b[15] = *t_cp++; \ + (cp) += 16; \ +} +#endif /* BYTE_ORDER */ + +#define SDP_PUT8(b, cp) { \ + register u_int8_t t_b = (u_int8_t)(b); \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp = t_b; \ + (cp) ++; \ +} + +#define SDP_PUT16(s, cp) { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += 2; \ +} + +#define SDP_PUT32(l, cp) { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += 4; \ +} + +#define SDP_PUT64(l, cp) { \ + register u_int64_t t_l = (u_int64_t)(l); \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp++ = t_l >> 56; \ + *t_cp++ = t_l >> 48; \ + *t_cp++ = t_l >> 40; \ + *t_cp++ = t_l >> 32; \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += 8; \ +} + +#if BYTE_ORDER == LITTLE_ENDIAN +#define SDP_PUT128(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp++ = (l)->b[15]; \ + *t_cp++ = (l)->b[14]; \ + *t_cp++ = (l)->b[13]; \ + *t_cp++ = (l)->b[12]; \ + *t_cp++ = (l)->b[11]; \ + *t_cp++ = (l)->b[10]; \ + *t_cp++ = (l)->b[9]; \ + *t_cp++ = (l)->b[8]; \ + *t_cp++ = (l)->b[7]; \ + *t_cp++ = (l)->b[6]; \ + *t_cp++ = (l)->b[5]; \ + *t_cp++ = (l)->b[4]; \ + *t_cp++ = (l)->b[3]; \ + *t_cp++ = (l)->b[2]; \ + *t_cp++ = (l)->b[1]; \ + *t_cp = (l)->b[0]; \ + (cp) += 16; \ +} +#else /* BYTE_ORDER != LITTLE_ENDIAN */ +#define SDP_PUT128(l, cp) { \ + register u_int8_t *t_cp = (u_int8_t *)(cp); \ + *t_cp++ = (l)->b[0]; \ + *t_cp++ = (l)->b[1]; \ + *t_cp++ = (l)->b[2]; \ + *t_cp++ = (l)->b[3]; \ + *t_cp++ = (l)->b[4]; \ + *t_cp++ = (l)->b[5]; \ + *t_cp++ = (l)->b[6]; \ + *t_cp++ = (l)->b[7]; \ + *t_cp++ = (l)->b[8]; \ + *t_cp++ = (l)->b[9]; \ + *t_cp++ = (l)->b[10]; \ + *t_cp++ = (l)->b[11]; \ + *t_cp++ = (l)->b[12]; \ + *t_cp++ = (l)->b[13]; \ + *t_cp++ = (l)->b[14]; \ + *t_cp = (l)->b[15]; \ + (cp) += 16; \ +} +#endif /* BYTE_ORDER */ + +void * sdp_open (bdaddr_t const *l, bdaddr_t const *r); +void * sdp_open_local (void); +int32_t sdp_close (void *xs); +int32_t sdp_error (void *xs); + +int32_t sdp_search (void *xs, + u_int32_t plen, u_int16_t const *pp, + u_int32_t alen, u_int32_t const *ap, + u_int32_t vlen, sdp_attr_t *vp); + +char const * const sdp_attr2desc (u_int16_t attr); +char const * const sdp_uuid2desc (u_int16_t uuid); +void sdp_print (u_int32_t level, u_int8_t const *start, + u_int8_t const *end); + +__END_DECLS + +#endif /* ndef _SDP_H_ */ + diff --git a/lib/libsdp/search.c b/lib/libsdp/search.c new file mode 100644 index 0000000..ab495e3 --- /dev/null +++ b/lib/libsdp/search.c @@ -0,0 +1,383 @@ +/* + * search.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: search.c,v 1.2 2003/09/04 22:12:13 max Exp $ + * $FreeBSD$ + */ + +#include <sys/uio.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <bluetooth.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sdp-int.h> +#include <sdp.h> + +int32_t +sdp_search(void *xss, + u_int32_t plen, u_int16_t const *pp, + u_int32_t alen, u_int32_t const *ap, + u_int32_t vlen, sdp_attr_t *vp) +{ + struct sdp_xpdu { + sdp_pdu_t pdu; + u_int16_t len; + } __attribute__ ((packed)) xpdu; + + sdp_session_p ss = (sdp_session_p) xss; + u_int8_t *req = NULL, *rsp = NULL, *rsp_tmp = NULL; + int32_t type, len; + + if (ss == NULL) + return (-1); + + if (ss->req == NULL || ss->rsp == NULL || + plen == 0 || pp == NULL || alen == 0 || ap == NULL) { + ss->error = EINVAL; + return (-1); + } + + /* Calculate length of the request */ + req = ss->req; + plen = plen * (sizeof(pp[0]) + 1); + alen = alen * (sizeof(ap[0]) + 1); + + len = plen + sizeof(u_int8_t) + sizeof(u_int16_t) + + /* ServiceSearchPattern */ + sizeof(u_int16_t) + + /* MaximumAttributeByteCount */ + alen + sizeof(u_int8_t) + sizeof(u_int16_t); + /* AttributeIDList */ + + if (ss->req_e - req < len) { + ss->error = ENOBUFS; + return (-1); + } + + /* Put ServiceSearchPattern */ + SDP_PUT8(SDP_DATA_SEQ16, req); + SDP_PUT16(plen, req); + for (; plen > 0; pp ++, plen -= (sizeof(pp[0]) + 1)) { + SDP_PUT8(SDP_DATA_UUID16, req); + SDP_PUT16(*pp, req); + } + + /* Put MaximumAttributeByteCount */ + SDP_PUT16(0xffff, req); + + /* Put AttributeIDList */ + SDP_PUT8(SDP_DATA_SEQ16, req); + SDP_PUT16(alen, req); + for (; alen > 0; ap ++, alen -= (sizeof(ap[0]) + 1)) { + SDP_PUT8(SDP_DATA_UINT32, req); + SDP_PUT32(*ap, req); + } + + /* Submit ServiceSearchAttributeRequest and wait for response */ + ss->cslen = 0; + rsp = ss->rsp; + + do { + struct iovec iov[2]; + u_int8_t *req_cs = req; + + /* Add continuation state (if any) */ + if (ss->req_e - req_cs < ss->cslen + 1) { + ss->error = ENOBUFS; + return (-1); + } + + SDP_PUT8(ss->cslen, req_cs); + if (ss->cslen > 0) { + memcpy(req_cs, ss->cs, ss->cslen); + req_cs += ss->cslen; + } + + /* Prepare SDP PDU header */ + xpdu.pdu.pid = SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST; + xpdu.pdu.tid = htons(ss->tid); + xpdu.pdu.len = htons(req_cs - ss->req); + + /* Submit request */ + iov[0].iov_base = (void *) &xpdu; + iov[0].iov_len = sizeof(xpdu.pdu); + iov[1].iov_base = (void *) ss->req; + iov[1].iov_len = req_cs - ss->req; + + len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0])); + if (len < 0) { + ss->error = errno; + return (-1); + } + + /* Read response */ + iov[0].iov_base = (void *) &xpdu; + iov[0].iov_len = sizeof(xpdu); + iov[1].iov_base = (void *) rsp; + iov[1].iov_len = ss->imtu; + + len = readv(ss->s, iov, sizeof(iov)/sizeof(iov[0])); + if (len < 0) { + ss->error = errno; + return (-1); + } + if (len < sizeof(xpdu)) { + ss->error = ENOMSG; + return (-1); + } + + xpdu.pdu.tid = ntohs(xpdu.pdu.tid); + xpdu.pdu.len = ntohs(xpdu.pdu.len); + xpdu.len = ntohs(xpdu.len); + + if (xpdu.pdu.pid == SDP_PDU_ERROR_RESPONSE || + xpdu.pdu.tid != ss->tid || + xpdu.len > xpdu.pdu.len) { + ss->error = EIO; + return (-1); + } + + /* Save continuation state (if any) */ + ss->cslen = rsp[xpdu.len]; + if (ss->cslen > 0) { + if (ss->cslen > sizeof(ss->cs)) { + ss->error = ENOBUFS; + return (-1); + } + + memcpy(ss->cs, rsp + xpdu.len + 1, ss->cslen); + + /* + * Ensure that we always have ss->imtu bytes + * available in the ss->rsp buffer + */ + + if (ss->rsp_e - rsp <= ss->imtu) { + u_int32_t size, offset; + + size = ss->rsp_e - ss->rsp + ss->imtu; + offset = rsp - ss->rsp; + + rsp_tmp = realloc(ss->rsp, size); + if (rsp_tmp == NULL) { + ss->error = ENOMEM; + return (-1); + } + + ss->rsp = rsp_tmp; + ss->rsp_e = ss->rsp + size; + rsp = ss->rsp + offset; + } + } + + rsp += xpdu.len; + ss->tid ++; + } while (ss->cslen > 0); + + /* + * If we got here then we have completed SDP transaction and now + * we must populate attribute values into vp array. At this point + * ss->rsp points to the beginning of the response and rsp points + * to the end of the response. + * + * From Bluetooth v1.1 spec page 364 + * + * The AttributeLists is a data element sequence where each element + * in turn is a data element sequence representing an attribute list. + * Each attribute list contains attribute IDs and attribute values + * from one service record. The first element in each attribute list + * contains the attribute ID of the first attribute to be returned for + * that service record. The second element in each attribute list + * contains the corresponding attribute value. Successive pairs of + * elements in each attribute list contain additional attribute ID + * and value pairs. Only attributes that have non-null values within + * the service record and whose attribute IDs were specified in the + * SDP_ServiceSearchAttributeRequest are contained in the AttributeLists + * Neither an attribute ID nor attribute value is placed in + * AttributeLists for attributes in the service record that have no + * value. Within each attribute list, the attributes are listed in + * ascending order of attribute ID value. + */ + + if (vp == NULL) + goto done; + + rsp_tmp = ss->rsp; + + /* Skip the first SEQ */ + SDP_GET8(type, rsp_tmp); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, rsp_tmp); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, rsp_tmp); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, rsp_tmp); + break; + + default: + ss->error = ENOATTR; + return (-1); + /* NOT REACHED */ + } + + for (; rsp_tmp < rsp && vlen > 0; ) { + /* Get set of attributes for the next record */ + SDP_GET8(type, rsp_tmp); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, rsp_tmp); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, rsp_tmp); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, rsp_tmp); + break; + + default: + ss->error = ENOATTR; + return (-1); + /* NOT REACHED */ + } + + /* Now rsp_tmp points to list of (attr,value) pairs */ + for (; len > 0 && vlen > 0; vp ++, vlen --) { + /* Attribute */ + SDP_GET8(type, rsp_tmp); + if (type != SDP_DATA_UINT16) { + ss->error = ENOATTR; + return (-1); + } + SDP_GET16(vp->attr, rsp_tmp); + + /* Attribute value */ + switch (rsp_tmp[0]) { + case SDP_DATA_NIL: + alen = 0; + break; + + case SDP_DATA_UINT8: + case SDP_DATA_INT8: + case SDP_DATA_BOOL: + alen = sizeof(u_int8_t); + break; + + case SDP_DATA_UINT16: + case SDP_DATA_INT16: + case SDP_DATA_UUID16: + alen = sizeof(u_int16_t); + break; + + case SDP_DATA_UINT32: + case SDP_DATA_INT32: + case SDP_DATA_UUID32: + alen = sizeof(u_int32_t); + break; + + case SDP_DATA_UINT64: + case SDP_DATA_INT64: + alen = sizeof(u_int64_t); + break; + + case SDP_DATA_UINT128: + case SDP_DATA_INT128: + case SDP_DATA_UUID128: + alen = sizeof(u_int128_t); + break; + + case SDP_DATA_STR8: + case SDP_DATA_URL8: + case SDP_DATA_SEQ8: + case SDP_DATA_ALT8: + alen = rsp_tmp[1] + sizeof(u_int8_t); + break; + + case SDP_DATA_STR16: + case SDP_DATA_URL16: + case SDP_DATA_SEQ16: + case SDP_DATA_ALT16: + alen = ((u_int16_t)rsp_tmp[1] << 8) + | ((u_int16_t)rsp_tmp[2]); + alen += sizeof(u_int16_t); + break; + + case SDP_DATA_STR32: + case SDP_DATA_URL32: + case SDP_DATA_SEQ32: + case SDP_DATA_ALT32: + alen = ((u_int32_t)rsp_tmp[1] << 24) + | ((u_int32_t)rsp_tmp[2] << 16) + | ((u_int32_t)rsp_tmp[3] << 8) + | ((u_int32_t)rsp_tmp[4]); + alen += sizeof(u_int32_t); + break; + + default: + ss->error = ENOATTR; + return (-1); + /* NOT REACHED */ + } + + alen += sizeof(u_int8_t); + + if (vp->value != NULL) { + if (alen <= vp->vlen) { + vp->flags = SDP_ATTR_OK; + vp->vlen = alen; + } else + vp->flags = SDP_ATTR_TRUNCATED; + + memcpy(vp->value, rsp_tmp, vp->vlen); + } else + vp->flags = SDP_ATTR_INVALID; + + len -= ( + sizeof(u_int8_t) + sizeof(u_int16_t) + + alen + ); + + rsp_tmp += alen; + } + } +done: + ss->error = 0; + + return (0); +} + diff --git a/lib/libsdp/session.c b/lib/libsdp/session.c new file mode 100644 index 0000000..199f8cd --- /dev/null +++ b/lib/libsdp/session.c @@ -0,0 +1,174 @@ +/* + * session.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: session.c,v 1.2 2003/09/04 22:12:13 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sdp-int.h> +#include <sdp.h> + +void * +sdp_open(bdaddr_t const *l, bdaddr_t const *r) +{ + sdp_session_p ss = NULL; + struct sockaddr_l2cap sa; + socklen_t size; + + if ((ss = calloc(1, sizeof(*ss))) == NULL) + goto fail; + + if (l == NULL || r == NULL) { + ss->error = EINVAL; + goto fail; + } + + ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); + if (ss->s < 0) { + ss->error = errno; + goto fail; + } + + sa.l2cap_len = sizeof(sa); + sa.l2cap_family = AF_BLUETOOTH; + sa.l2cap_psm = 0; + memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr)); + if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + ss->error = errno; + goto fail; + } + + sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP); + memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr)); + if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + ss->error = errno; + goto fail; + } + + size = sizeof(ss->omtu); + if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) { + ss->error = errno; + goto fail; + } + if ((ss->req = malloc(ss->omtu)) == NULL) { + ss->error = ENOMEM; + goto fail; + } + ss->req_e = ss->req + ss->omtu; + + size = sizeof(ss->imtu); + if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) { + ss->error = errno; + goto fail; + } + if ((ss->rsp = malloc(ss->imtu)) == NULL) { + ss->error = ENOMEM; + goto fail; + } + ss->rsp_e = ss->rsp + ss->imtu; + ss->error = 0; +fail: + return ((void *) ss); +} + +void * +sdp_open_local(void) +{ + sdp_session_p ss = NULL; + struct sockaddr_un sa; + + if ((ss = calloc(1, sizeof(*ss))) == NULL) + goto fail; + + ss->s = socket(PF_UNIX, SOCK_STREAM, 0); + if (ss->s < 0) { + ss->error = errno; + goto fail; + } + + sa.sun_len = sizeof(sa); + sa.sun_family = AF_UNIX; + strlcpy(sa.sun_path, SDP_UNSOCK_PATH, sizeof(sa.sun_path)); + + if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + ss->error = errno; + goto fail; + } + + ss->flags |= SDP_SESSION_LOCAL; + ss->imtu = ss->omtu = SDP_UNSOCK_MTU; + + if ((ss->req = malloc(ss->omtu)) == NULL) { + ss->error = ENOMEM; + goto fail; + } + ss->req_e = ss->req + ss->omtu; + + if ((ss->rsp = malloc(ss->imtu)) == NULL) { + ss->error = ENOMEM; + goto fail; + } + ss->rsp_e = ss->rsp + ss->imtu; + ss->error = 0; +fail: + return ((void *) ss); +} + +int32_t +sdp_close(void *xss) +{ + sdp_session_p ss = (sdp_session_p) xss; + + if (ss != NULL) { + if (ss->s >= 0) + close(ss->s); + + if (ss->req != NULL) + free(ss->req); + if (ss->rsp != NULL) + free(ss->rsp); + + memset(ss, 0, sizeof(*ss)); + free(ss); + } + + return (0); +} + +int32_t +sdp_error(void *xss) +{ + sdp_session_p ss = (sdp_session_p) xss; + + return ((ss != NULL)? ss->error : EINVAL); +} diff --git a/lib/libsdp/util.c b/lib/libsdp/util.c new file mode 100644 index 0000000..923b347 --- /dev/null +++ b/lib/libsdp/util.c @@ -0,0 +1,439 @@ +/* + * util.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: util.c,v 1.5 2003/09/08 02:29:35 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <stdio.h> +#include <sdp.h> + +/* + * SDP attribute description + */ + +struct sdp_attr_desc { + u_int32_t attr; + char const *desc; +}; +typedef struct sdp_attr_desc sdp_attr_desc_t; +typedef struct sdp_attr_desc * sdp_attr_desc_p; + +static sdp_attr_desc_t sdp_uuids_desc[] = { +{ SDP_UUID_PROTOCOL_SDP, "SDP", }, +{ SDP_UUID_PROTOCOL_UDP, "UDP", }, +{ SDP_UUID_PROTOCOL_RFCOMM, "RFCOMM", }, +{ SDP_UUID_PROTOCOL_TCP, "TCP", }, +{ SDP_UUID_PROTOCOL_TCS_BIN, "TCS BIN", }, +{ SDP_UUID_PROTOCOL_TCS_AT, "TCS AT", }, +{ SDP_UUID_PROTOCOL_OBEX, "OBEX", }, +{ SDP_UUID_PROTOCOL_IP, "IP", }, +{ SDP_UUID_PROTOCOL_FTP, "FTP", }, +{ SDP_UUID_PROTOCOL_HTTP, "HTTP", }, +{ SDP_UUID_PROTOCOL_WSP, "WSP", }, +{ SDP_UUID_PROTOCOL_BNEP, "BNEP", }, +{ SDP_UUID_PROTOCOL_UPNP, "UPNP", }, +{ SDP_UUID_PROTOCOL_HIDP, "HIDP", }, +{ SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL, "Hardcopy Control Channel", }, +{ SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL, "Hardcopy Data Channel", }, +{ SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION, "Hardcopy Notification", }, +{ SDP_UUID_PROTOCOL_AVCTP, "AVCTP", }, +{ SDP_UUID_PROTOCOL_AVDTP, "AVDTP", }, +{ SDP_UUID_PROTOCOL_CMPT, "CMPT", }, +{ SDP_UUID_PROTOCOL_UDI_C_PLANE, "UDI C-Plane", }, +{ SDP_UUID_PROTOCOL_L2CAP, "L2CAP", }, +/* Service Class IDs/Bluetooth Profile IDs */ +{ SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, "Service Discovery Server", }, +{ SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR, "Browse Group Descriptor", }, +{ SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, "Public Browse Group", }, +{ SDP_SERVICE_CLASS_SERIAL_PORT, "Serial Port", }, +{ SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP, "LAN Access Using PPP", }, +{ SDP_SERVICE_CLASS_DIALUP_NETWORKING, "DailUp Networking", }, +{ SDP_SERVICE_CLASS_IR_MC_SYNC, "IrMC Sync", }, +{ SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH, "OBEX Object Push", }, +{ SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER, "OBEX File Transfer", }, +{ SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND, "IrMC Sync Command", }, +{ SDP_SERVICE_CLASS_HEADSET, "Headset", }, +{ SDP_SERVICE_CLASS_CORDLESS_TELEPHONY, "Cordless Telephony", }, +{ SDP_SERVICE_CLASS_AUDIO_SOURCE, "Audio Source", }, +{ SDP_SERVICE_CLASS_AUDIO_SINK, "Audio Sink", }, +{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET, "A/V Remote Control Target", }, +{ SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION, "Advanced Audio Distribution", }, +{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL, "A/V Remote Control", }, +{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING, "Video Conferencing", }, +{ SDP_SERVICE_CLASS_INTERCOM, "Intercom", }, +{ SDP_SERVICE_CLASS_FAX, "Fax", }, +{ SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY, "Headset Audio Gateway", }, +{ SDP_SERVICE_CLASS_WAP, "WAP", }, +{ SDP_SERVICE_CLASS_WAP_CLIENT, "WAP Client", }, +{ SDP_SERVICE_CLASS_PANU, "PANU", }, +{ SDP_SERVICE_CLASS_NAP, "Network Access Point", }, +{ SDP_SERVICE_CLASS_GN, "GN", }, +{ SDP_SERVICE_CLASS_DIRECT_PRINTING, "Direct Printing", }, +{ SDP_SERVICE_CLASS_REFERENCE_PRINTING, "Reference Printing", }, +{ SDP_SERVICE_CLASS_IMAGING, "Imaging", }, +{ SDP_SERVICE_CLASS_IMAGING_RESPONDER, "Imaging Responder", }, +{ SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE, "Imaging Automatic Archive", }, +{ SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS, "Imaging Referenced Objects", }, +{ SDP_SERVICE_CLASS_HANDSFREE, "Handsfree", }, +{ SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY, "Handsfree Audio Gateway", }, +{ SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS, "Direct Printing Reference Objects", }, +{ SDP_SERVICE_CLASS_REFLECTED_UI, "Reflected UI", }, +{ SDP_SERVICE_CLASS_BASIC_PRINTING, "Basic Printing", }, +{ SDP_SERVICE_CLASS_PRINTING_STATUS, "Printing Status", }, +{ SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE, "Human Interface Device", }, +{ SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT, "Hardcopy Cable Replacement", }, +{ SDP_SERVICE_CLASS_HCR_PRINT, "HCR Print", }, +{ SDP_SERVICE_CLASS_HCR_SCAN, "HCR Scan", }, +{ SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS, "Common ISDN Access", }, +{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW, "Video Conferencing Gateway", }, +{ SDP_SERVICE_CLASS_UDI_MT, "UDI MT", }, +{ SDP_SERVICE_CLASS_UDI_TA, "UDI TA", }, +{ SDP_SERVICE_CLASS_AUDIO_VIDEO, "Audio/Video", }, +{ SDP_SERVICE_CLASS_SIM_ACCESS, "SIM Access", }, +{ SDP_SERVICE_CLASS_PNP_INFORMATION, "PNP Information", }, +{ SDP_SERVICE_CLASS_GENERIC_NETWORKING, "Generic Networking", }, +{ SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER, "Generic File Transfer", }, +{ SDP_SERVICE_CLASS_GENERIC_AUDIO, "Generic Audio", }, +{ SDP_SERVICE_CLASS_GENERIC_TELEPHONY, "Generic Telephony", }, +{ SDP_SERVICE_CLASS_UPNP, "UPNP", }, +{ SDP_SERVICE_CLASS_UPNP_IP, "UPNP IP", }, +{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN, "ESDP UPNP IP PAN", }, +{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP, "ESDP UPNP IP LAP", }, +{ SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP, "ESDP UPNP L2CAP", }, +{ 0xffff, NULL, } +}; + +static sdp_attr_desc_t sdp_attrs_desc[] = { +{ SDP_ATTR_SERVICE_RECORD_HANDLE, + "Record handle", + }, +{ SDP_ATTR_SERVICE_CLASS_ID_LIST, + "Service Class ID list", + }, +{ SDP_ATTR_SERVICE_RECORD_STATE, + "Service Record State", + }, +{ SDP_ATTR_SERVICE_ID, + "Service ID", + }, +{ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + "Protocol Descriptor List", + }, +{ SDP_ATTR_BROWSE_GROUP_LIST, + "Browse Group List", + }, +{ SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, + "Language Base Attribute ID List", + }, +{ SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE, + "Service Info Time-To-Live", + }, +{ SDP_ATTR_SERVICE_AVAILABILITY, + "Service Availability", + }, +{ SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, + "Bluetooh Profile Descriptor List", + }, +{ SDP_ATTR_DOCUMENTATION_URL, + "Documentation URL", + }, +{ SDP_ATTR_CLIENT_EXECUTABLE_URL, + "Client Executable URL", + }, +{ SDP_ATTR_ICON_URL, + "Icon URL", + }, +{ SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS, + "Additional Protocol Descriptor Lists" }, +{ SDP_ATTR_GROUP_ID, +/*SDP_ATTR_IP_SUBNET, + SDP_ATTR_VERSION_NUMBER_LIST*/ + "Group ID/IP Subnet/Version Number List", + }, +{ SDP_ATTR_SERVICE_DATABASE_STATE, + "Service Database State", + }, +{ SDP_ATTR_SERVICE_VERSION, + "Service Version", + }, +{ SDP_ATTR_EXTERNAL_NETWORK, +/*SDP_ATTR_NETWORK, + SDP_ATTR_SUPPORTED_DATA_STORES_LIST*/ + "External Network/Network/Supported Data Stores List", + }, +{ SDP_ATTR_FAX_CLASS1_SUPPORT, +/*SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL*/ + "Fax Class1 Support/Remote Audio Volume Control", + }, +{ SDP_ATTR_FAX_CLASS20_SUPPORT, +/*SDP_ATTR_SUPPORTED_FORMATS_LIST*/ + "Fax Class20 Support/Supported Formats List", + }, +{ SDP_ATTR_FAX_CLASS2_SUPPORT, + "Fax Class2 Support", + }, +{ SDP_ATTR_AUDIO_FEEDBACK_SUPPORT, + "Audio Feedback Support", + }, +{ SDP_ATTR_NETWORK_ADDRESS, + "Network Address", + }, +{ SDP_ATTR_WAP_GATEWAY, + "WAP Gateway", + }, +{ SDP_ATTR_HOME_PAGE_URL, + "Home Page URL", + }, +{ SDP_ATTR_WAP_STACK_TYPE, + "WAP Stack Type", + }, +{ SDP_ATTR_SECURITY_DESCRIPTION, + "Security Description", + }, +{ SDP_ATTR_NET_ACCESS_TYPE, + "Net Access Type", + }, +{ SDP_ATTR_MAX_NET_ACCESS_RATE, + "Max Net Access Rate", + }, +{ SDP_ATTR_IPV4_SUBNET, + "IPv4 Subnet", + }, +{ SDP_ATTR_IPV6_SUBNET, + "IPv6 Subnet", + }, +{ SDP_ATTR_SUPPORTED_CAPABALITIES, + "Supported Capabalities", + }, +{ SDP_ATTR_SUPPORTED_FEATURES, + "Supported Features", + }, +{ SDP_ATTR_SUPPORTED_FUNCTIONS, + "Supported Functions", + }, +{ SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY, + "Total Imaging Data Capacity", + }, +{ 0xffff, NULL, } +}; + +char const * const +sdp_attr2desc(u_int16_t attr) +{ + register sdp_attr_desc_p a = sdp_attrs_desc; + + for (; a->desc != NULL; a++) + if (attr == a->attr) + break; + + return ((a->desc != NULL)? a->desc : "Unknown"); +} + +char const * const +sdp_uuid2desc(u_int16_t uuid) +{ + register sdp_attr_desc_p a = sdp_uuids_desc; + + for (; a->desc != NULL; a++) + if (uuid == a->attr) + break; + + return ((a->desc != NULL)? a->desc : "Unknown"); +} + +void +sdp_print(u_int32_t level, u_int8_t const *start, u_int8_t const *end) +{ + union { + int8_t int8; + int16_t int16; + int32_t int32; + int64_t int64; + int128_t int128; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + } value; + u_int8_t type; + u_int32_t i; + + if (start == NULL || end == NULL) + return; + + while (start < end) { + for (i = 0; i < level; i++) + printf("\t"); + + SDP_GET8(type, start); + + switch (type) { + case SDP_DATA_NIL: + printf("nil\n"); + break; + + case SDP_DATA_UINT8: + SDP_GET8(value.uint8, start); + printf("uint8 %u\n", value.uint8); + break; + case SDP_DATA_UINT16: + SDP_GET16(value.uint16, start); + printf("uint16 %u\n", value.uint16); + break; + case SDP_DATA_UINT32: + SDP_GET32(value.uint32, start); + printf("uint32 %u\n", value.uint32); + break; + case SDP_DATA_UINT64: + SDP_GET64(value.uint64, start); + printf("uint64 %llu\n", value.uint64); + break; + + case SDP_DATA_UINT128: + case SDP_DATA_INT128: + case SDP_DATA_UUID128: + SDP_GET128(&value.int128, start); + printf("int128/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&value.int128.b[0], + *(u_int16_t *)&value.int128.b[4], + *(u_int16_t *)&value.int128.b[6], + *(u_int16_t *)&value.int128.b[8], + *(u_int16_t *)&value.int128.b[10], + *(u_int32_t *)&value.int128.b[12]); + break; + + case SDP_DATA_INT8: + SDP_GET8(value.int8, start); + printf("int8 %d\n", value.int8); + break; + case SDP_DATA_INT16: + SDP_GET16(value.int16, start); + printf("int16 %d\n", value.int16); + break; + case SDP_DATA_INT32: + SDP_GET32(value.int32, start); + printf("int32 %d\n", value.int32); + break; + case SDP_DATA_INT64: + SDP_GET64(value.int64, start); + printf("int64 %lld\n", value.int64); + break; + + case SDP_DATA_UUID16: + SDP_GET16(value.uint16, start); + printf("uuid16 %#4.4x - %s\n", value.uint16, + sdp_uuid2desc(value.uint16)); + break; + case SDP_DATA_UUID32: + SDP_GET32(value.uint32, start); + printf("uuid32 %#8.8x\n", value.uint32); + break; + + case SDP_DATA_STR8: + SDP_GET8(value.uint8, start); + printf("str8 %*.*s\n", value.uint8, value.uint8, start); + start += value.uint8; + break; + case SDP_DATA_STR16: + SDP_GET16(value.uint16, start); + printf("str16 %*.*s\n", value.uint16, value.uint16, start); + start += value.uint16; + break; + case SDP_DATA_STR32: + SDP_GET32(value.uint32, start); + printf("str32 %*.*s\n", value.uint32, value.uint32, start); + start += value.uint32; + break; + + case SDP_DATA_BOOL: + SDP_GET8(value.uint8, start); + printf("bool %d\n", value.uint8); + break; + + case SDP_DATA_SEQ8: + SDP_GET8(value.uint8, start); + printf("seq8 %d\n", value.uint8); + sdp_print(level + 1, start, start + value.uint8); + start += value.uint8; + break; + case SDP_DATA_SEQ16: + SDP_GET16(value.uint16, start); + printf("seq16 %d\n", value.uint16); + sdp_print(level + 1, start, start + value.uint16); + start += value.uint16; + break; + case SDP_DATA_SEQ32: + SDP_GET32(value.uint32, start); + printf("seq32 %d\n", value.uint32); + sdp_print(level + 1, start, start + value.uint32); + start += value.uint32; + break; + + case SDP_DATA_ALT8: + SDP_GET8(value.uint8, start); + printf("alt8 %d\n", value.uint8); + sdp_print(level + 1, start, start + value.uint8); + start += value.uint8; + break; + case SDP_DATA_ALT16: + SDP_GET16(value.uint16, start); + printf("alt16 %d\n", value.uint16); + sdp_print(level + 1, start, start + value.uint16); + start += value.uint16; + break; + case SDP_DATA_ALT32: + SDP_GET32(value.uint32, start); + printf("alt32 %d\n", value.uint32); + sdp_print(level + 1, start, start + value.uint32); + start += value.uint32; + break; + + case SDP_DATA_URL8: + SDP_GET8(value.uint8, start); + printf("url8 %*.*s\n", value.uint8, value.uint8, start); + start += value.uint8; + break; + case SDP_DATA_URL16: + SDP_GET16(value.uint16, start); + printf("url16 %*.*s\n", value.uint16, value.uint16, start); + start += value.uint16; + break; + case SDP_DATA_URL32: + SDP_GET32(value.uint32, start); + printf("url32 %*.*s\n", value.uint32, value.uint32, start); + start += value.uint32; + break; + + default: + printf("unknown data type: %#02x\n", *start ++); + break; + } + } +} + diff --git a/share/man/man4/ng_bluetooth.4 b/share/man/man4/ng_bluetooth.4 index 7d19625..5fb3ec0 100644 --- a/share/man/man4/ng_bluetooth.4 +++ b/share/man/man4/ng_bluetooth.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_bluetooth.4,v 1.2 2003/04/26 22:38:25 max Exp $ +.\" $Id: ng_bluetooth.4,v 1.3 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd November 9, 2002 diff --git a/share/man/man4/ng_bt3c.4 b/share/man/man4/ng_bt3c.4 index f10f83f..99a745d 100644 --- a/share/man/man4/ng_bt3c.4 +++ b/share/man/man4/ng_bt3c.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_bt3c.4,v 1.1 2002/11/24 19:37:54 max Exp $ +.\" $Id: ng_bt3c.4,v 1.3 2003/09/14 23:28:51 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/share/man/man4/ng_btsocket.4 b/share/man/man4/ng_btsocket.4 index c3405eca..b882947 100644 --- a/share/man/man4/ng_btsocket.4 +++ b/share/man/man4/ng_btsocket.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_btsocket.4,v 1.6 2003/03/18 00:09:34 max Exp $ +.\" $Id: ng_btsocket.4,v 1.7 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd July 8, 2002 @@ -186,6 +186,10 @@ Returns list of active baseband connections (i.e. ACL links) for the L2CAP node. .It Dv SIOC_L2CAP_NODE_GET_CHAN_LIST Returns list of active channels for the L2CAP node. +.It Dv SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO +Returns current value of the auto disconnect timeout for the L2CAP node. +.It Dv SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO +Sets current value of the auto disconnect timeout for the L2CAP node. .It Dv SIOC_L2CAP_L2CA_PING Issues L2CAP .Dv ECHO_REQUEST . diff --git a/share/man/man4/ng_h4.4 b/share/man/man4/ng_h4.4 index 024714a..760a19f 100644 --- a/share/man/man4/ng_h4.4 +++ b/share/man/man4/ng_h4.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_h4.4,v 1.1 2002/11/24 19:37:54 max Exp $ +.\" $Id: ng_h4.4,v 1.2 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/share/man/man4/ng_hci.4 b/share/man/man4/ng_hci.4 index b0b791f..37c0b73 100644 --- a/share/man/man4/ng_hci.4 +++ b/share/man/man4/ng_hci.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_hci.4,v 1.2 2003/03/18 00:09:34 max Exp $ +.\" $Id: ng_hci.4,v 1.3 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd June 25, 2002 diff --git a/share/man/man4/ng_l2cap.4 b/share/man/man4/ng_l2cap.4 index 5e9d9e9..d5c38a2 100644 --- a/share/man/man4/ng_l2cap.4 +++ b/share/man/man4/ng_l2cap.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_l2cap.4,v 1.2 2003/04/28 20:16:29 max Exp $ +.\" $Id: ng_l2cap.4,v 1.4 2003/09/14 23:37:52 max Exp $ .\" $FreeBSD$ .\" .Dd July 4, 2002 @@ -58,7 +58,7 @@ The ACL link between two units is set up. The Baseband provides orderly delivery of data packets, although there might be individual packet corruption and duplicates. -No more than 1 ACL link exists between any two devices. +No more than one ACL link exists between any two devices. .It The Baseband always provides the impression of full-duplex communication channels. @@ -220,7 +220,7 @@ Upper layer protocol upstream hook. Usually the Bluetooth L2CAP socket layer is connected to the hook. .It Dv ctl Control hook. -Usually Bluetooth raw L2CAP sockets layer is connected to the hook. +Usually the Bluetooth raw L2CAP sockets layer is connected to the hook. .El .Sh INTERFACE TO THE UPPER LAYER PROTOCOLS (L2CA CONTROL MESSAGES) Bluetooth specification says that L2CA request must block until response diff --git a/share/man/man4/ng_ubt.4 b/share/man/man4/ng_ubt.4 index 7c91360..ca6a5a6 100644 --- a/share/man/man4/ng_ubt.4 +++ b/share/man/man4/ng_ubt.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ng_ubt.4,v 1.2 2003/03/22 23:44:32 max Exp $ +.\" $Id: ng_ubt.4,v 1.3 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/share/man/man4/ubtbcmfw.4 b/share/man/man4/ubtbcmfw.4 index 6412628..1369879 100644 --- a/share/man/man4/ubtbcmfw.4 +++ b/share/man/man4/ubtbcmfw.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ubtbcmfw.4,v 1.1 2003/04/28 17:09:46 max Exp $ +.\" $Id: ubtbcmfw.4,v 1.3 2003/05/21 19:37:35 max Exp $ .\" $FreeBSD$ .\" .Dd April 28, 2003 diff --git a/share/man/man5/Makefile b/share/man/man5/Makefile index 0f59542..dab3a96 100644 --- a/share/man/man5/Makefile +++ b/share/man/man5/Makefile @@ -2,7 +2,8 @@ # $FreeBSD$ #MISSING: dump.5 plot.5 -MAN= a.out.5 acct.5 core.5 config.5 devfs.5 device.hints.5 \ +MAN= a.out.5 acct.5 bluetooth.hosts.5 bluetooth.protocols.5 \ + core.5 config.5 devfs.5 device.hints.5 \ dir.5 disktab.5 drivers.conf.5 \ elf.5 ethers.5 fbtab.5 fdescfs.5 forward.5 fs.5 fstab.5 group.5 \ hesiod.conf.5 \ diff --git a/share/man/man5/bluetooth.hosts.5 b/share/man/man5/bluetooth.hosts.5 new file mode 100644 index 0000000..eba3e97 --- /dev/null +++ b/share/man/man5/bluetooth.hosts.5 @@ -0,0 +1,63 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: bluetooth.hosts.5,v 1.5 2003/05/20 22:52:39 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 8, 2003 +.Dt BLUETOOTH.HOSTS 5 +.Os +.Sh NAME +.Nm /etc/bluetooth/hosts +.Nd Bluetooth host name database +.Sh DESCRIPTION +The +.Nm +file contains information regarding the known Bluetooth hosts. +For each Bluetooth host a single line should be present with the +following information: +.Bd -unfilled -offset indent +Bluetooth address +official host name +aliases +.Ed +.Pp +Items are separated by any number of blanks and/or tab characters. +A +.Dq # +indicates the beginning of a comment; characters up to the end of the line are +not interpreted by routines which search the file. +.Pp +Bluetooth addresses are specified as six hex bytes separated by columns +(BD_ADDR). +Host names may contain any printable character other than a field +delimiter, newline, or comment character. +.Sh FILES +.Bl -tag -width /etc/bluetooth/hosts -compact +.It Pa /etc/bluetooth/hosts +.El +.Sh SEE ALSO +.Xr bluetooth 3 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/share/man/man5/bluetooth.protocols.5 b/share/man/man5/bluetooth.protocols.5 new file mode 100644 index 0000000..25adebd --- /dev/null +++ b/share/man/man5/bluetooth.protocols.5 @@ -0,0 +1,62 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: bluetooth.protocols.5,v 1.1 2003/05/20 22:52:39 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 8, 2003 +.Dt BLUETOOTH.PROTOCOLS 5 +.Os +.Sh NAME +.Nm /etc/bluetooth/protocols +.Nd Bluetooth Protocol Service Multiplexor database +.Sh DESCRIPTION +The +.Nm +file contains information regarding the known Bluetooth Protocol Service +Multiplexor values. +For each Bluetooth Protocol Service Multiplexor a single line should be +present with the following information: +.Bd -unfilled -offset indent +official Protocol Service Multiplexor name +official Protocol Service Multiplexor value +aliases +.Ed +.Pp +Items are separated by any number of blanks and/or tab characters. +A +.Dq # +indicates the beginning of a comment; characters up to the end of the line are +not interpreted by routines which search the file. +.Pp +Bluetooth Protocol Service Multiplexor names may contain any printable +character other than a field delimiter, newline, or comment character. +.Sh FILES +.Bl -tag -width /etc/bluetooth/hosts -compact +.It Pa /etc/bluetooth/protocols +.El +.Sh SEE ALSO +.Xr bluetooth 3 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 965b187..949b2e8 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -14,6 +14,7 @@ LIBALIAS?= ${DESTDIR}${LIBDIR}/libalias.a LIBASN1?= ${DESTDIR}${LIBDIR}/libasn1.a # XXX in secure dist, not base LIBATM?= ${DESTDIR}${LIBDIR}/libatm.a LIBBSDXML?= ${DESTDIR}${LIBDIR}/libbsdxml.a +LIBBLUETOOTH?= ${DESTDIR}${LIBDIR}/libbluetooth.a LIBBZ2?= ${DESTDIR}${LIBDIR}/libbz2.a LIBC?= ${DESTDIR}${LIBDIR}/libc.a LIBC_PIC?= ${DESTDIR}${LIBDIR}/libc_pic.a @@ -100,6 +101,7 @@ LIBREADLINE?= ${DESTDIR}${LIBDIR}/libreadline.a LIBRESOLV?= ${DESTDIR}${LIBDIR}/libresolv.a # XXX doesn't exist LIBROKEN?= ${DESTDIR}${LIBDIR}/libroken.a # XXX in secure dist, not base LIBRPCSVC?= ${DESTDIR}${LIBDIR}/librpcsvc.a +LIBSDP?= ${DESTDIR}${LIBDIR}/libsdp.a LIBSBUF?= ${DESTDIR}${LIBDIR}/libsbuf.a LIBSMB?= ${DESTDIR}${LIBDIR}/libsmb.a LIBSSH?= ${DESTDIR}${LIBDIR}/libssh.a # XXX in secure dist, not base diff --git a/sys/modules/netgraph/bluetooth/bluetooth/Makefile b/sys/modules/netgraph/bluetooth/bluetooth/Makefile index 55317b9..aae3984 100644 --- a/sys/modules/netgraph/bluetooth/bluetooth/Makefile +++ b/sys/modules/netgraph/bluetooth/bluetooth/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/common -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include KMOD= ng_bluetooth SRCS= ng_bluetooth.c diff --git a/sys/modules/netgraph/bluetooth/bt3c/Makefile b/sys/modules/netgraph/bluetooth/bt3c/Makefile index de1aa20..4d00d32 100644 --- a/sys/modules/netgraph/bluetooth/bt3c/Makefile +++ b/sys/modules/netgraph/bluetooth/bt3c/Makefile @@ -3,12 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 -#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1 - KMOD= ng_bt3c SRCS= ng_bt3c_pccard.c bus_if.h card_if.h device_if.h MAN4= ng_bt3c.4 diff --git a/sys/modules/netgraph/bluetooth/h4/Makefile b/sys/modules/netgraph/bluetooth/h4/Makefile index 51e85cb..c5d63b5 100644 --- a/sys/modules/netgraph/bluetooth/h4/Makefile +++ b/sys/modules/netgraph/bluetooth/h4/Makefile @@ -3,11 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4 -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4 -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 - KMOD= ng_h4 SRCS= ng_h4.c MAN4= ng_h4.4 diff --git a/sys/modules/netgraph/bluetooth/hci/Makefile b/sys/modules/netgraph/bluetooth/hci/Makefile index 48a6bfa..2423e51 100644 --- a/sys/modules/netgraph/bluetooth/hci/Makefile +++ b/sys/modules/netgraph/bluetooth/hci/Makefile @@ -3,11 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/hci -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/hci -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 - KMOD= ng_hci SRCS= ng_hci_main.c ng_hci_cmds.c ng_hci_evnt.c \ ng_hci_ulpi.c ng_hci_misc.c diff --git a/sys/modules/netgraph/bluetooth/l2cap/Makefile b/sys/modules/netgraph/bluetooth/l2cap/Makefile index d2cc849..623fd86 100644 --- a/sys/modules/netgraph/bluetooth/l2cap/Makefile +++ b/sys/modules/netgraph/bluetooth/l2cap/Makefile @@ -3,11 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/l2cap -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/l2cap -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 - KMOD= ng_l2cap SRCS= ng_l2cap_main.c ng_l2cap_cmds.c ng_l2cap_evnt.c \ ng_l2cap_ulpi.c ng_l2cap_llpi.c ng_l2cap_misc.c diff --git a/sys/modules/netgraph/bluetooth/socket/Makefile b/sys/modules/netgraph/bluetooth/socket/Makefile index 4cb414b..ba82b5c 100644 --- a/sys/modules/netgraph/bluetooth/socket/Makefile +++ b/sys/modules/netgraph/bluetooth/socket/Makefile @@ -3,10 +3,7 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/socket -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include - -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 -#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1 +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include KMOD= ng_btsocket SRCS= ng_btsocket.c \ diff --git a/sys/modules/netgraph/bluetooth/ubt/Makefile b/sys/modules/netgraph/bluetooth/ubt/Makefile index ad50892..941bf33 100644 --- a/sys/modules/netgraph/bluetooth/ubt/Makefile +++ b/sys/modules/netgraph/bluetooth/ubt/Makefile @@ -3,12 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 -#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1 - KMOD= ng_ubt SRCS= ng_ubt.c bus_if.h device_if.h vnode_if.h opt_usb.h MAN4= ng_ubt.4 diff --git a/sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile b/sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile index ede61d7..a7f0fcc 100644 --- a/sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile +++ b/sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile @@ -3,12 +3,9 @@ .PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw -CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \ +CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \ -I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw -#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1 -#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1 - KMOD= ubtbcmfw SRCS= ubtbcmfw.c bus_if.h device_if.h vnode_if.h opt_usb.h MAN4= ubtbcmfw.4 diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c index 5f98d8d..dd5ef65 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_ubt.c,v 1.14 2003/04/14 23:00:50 max Exp $ + * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $ * $FreeBSD$ */ @@ -2704,7 +2704,6 @@ ubt_create_device_nodes(ubt_softc_p sc) Static void ubt_destroy_device_nodes(ubt_softc_p sc) { - /* * Wait for processes to go away. This should be safe as we will not * call ubt_destroy_device_nodes() from Netgraph unless all devices diff --git a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c index 5fbcd06..8e4eeb2 100644 --- a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c +++ b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ubtbcmfw.c,v 1.1 2003/04/27 00:20:15 max Exp $ + * $Id: ubtbcmfw.c,v 1.3 2003/10/10 19:15:08 max Exp $ * $FreeBSD$ */ diff --git a/sys/netgraph/bluetooth/hci/ng_hci_cmds.c b/sys/netgraph/bluetooth/hci/ng_hci_cmds.c index 83b640b..57a9c9d 100644 --- a/sys/netgraph/bluetooth/hci/ng_hci_cmds.c +++ b/sys/netgraph/bluetooth/hci/ng_hci_cmds.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_hci_cmds.c,v 1.3 2003/04/01 18:15:25 max Exp $ + * $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $ * $FreeBSD$ */ @@ -355,11 +355,17 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp) /* * Now we can remove command timeout, dequeue completed command - * and return command parameters. Note: ng_hci_command_untimeout() - * will drop NG_HCI_UNIT_COMMAND_PENDING flag. + * and return command parameters. ng_hci_command_untimeout will + * drop NG_HCI_UNIT_COMMAND_PENDING flag. + * Note: if ng_hci_command_untimeout() fails (returns non-zero) + * then timeout aready happened and timeout message went info node + * queue. In this case we ignore command completion and pretend + * there is a timeout. */ - ng_hci_command_untimeout(unit); + if (ng_hci_command_untimeout(unit) != 0) + return (ETIMEDOUT); + NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp); m_adj(*cp, sizeof(ng_hci_cmd_pkt_t)); @@ -373,17 +379,24 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp) void ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) { - ng_hci_unit_p unit = (ng_hci_unit_p) arg1; + ng_hci_unit_p unit = NULL; struct mbuf *m = NULL; u_int16_t opcode; + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } + + unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node); + if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) { - NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m); + unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; + NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m); if (m == NULL) { - KASSERT(0, -("%s: %s - command queue is out of sync!\n", - __func__, NG_NODE_NAME(unit->node))); + NG_HCI_ALERT( +"%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node)); return; } @@ -396,18 +409,12 @@ ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) __func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode), NG_HCI_OCF(opcode)); - /* - * Try to send more commands - */ - + /* Try to send more commands */ NG_HCI_BUFF_CMD_SET(unit->buffer, 1); - - unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; ng_hci_send_command(unit); } else - KASSERT(0, -("%s: %s - no pending command, state=%#x\n", - __func__, NG_NODE_NAME(unit->node), unit->state)); + NG_HCI_ALERT( +"%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node)); } /* ng_hci_process_command_timeout */ /* @@ -616,6 +623,10 @@ process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf, while (!LIST_EMPTY(&unit->con_list)) { con = LIST_FIRST(&unit->con_list); + /* Remove all timeouts (if any) */ + if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) + ng_hci_con_untimeout(con); + /* Connection terminated by local host */ ng_hci_lp_discon_ind(con, 0x16); ng_hci_free_con(con); diff --git a/sys/netgraph/bluetooth/hci/ng_hci_evnt.c b/sys/netgraph/bluetooth/hci/ng_hci_evnt.c index 1f1c74a..fcc00fb 100644 --- a/sys/netgraph/bluetooth/hci/ng_hci_evnt.c +++ b/sys/netgraph/bluetooth/hci/ng_hci_evnt.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_hci_evnt.c,v 1.5 2003/04/01 18:15:25 max Exp $ + * $Id: ng_hci_evnt.c,v 1.6 2003/09/08 18:57:51 max Exp $ * $FreeBSD$ */ @@ -454,7 +454,10 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event) * Two possible cases: * * 1) We have found connection descriptor. That means upper layer has - * requested this connection via LP_CON_REQ message + * requested this connection via LP_CON_REQ message. In this case + * connection must have timeout set. If ng_hci_con_untimeout() fails + * then timeout message already went into node's queue. In this case + * ignore Connection_Complete event and let timeout deal with it. * * 2) We do not have connection descriptor. That means upper layer * nas not requested this connection or (less likely) we gave up @@ -474,8 +477,8 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event) } bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr)); - } else - ng_hci_con_untimeout(con); + } else if ((error = ng_hci_con_untimeout(con)) != 0) + goto out; /* * Update connection descriptor and send notification @@ -543,7 +546,7 @@ out: NG_FREE_M(event); return (error); -} /* com_compl */ +} /* con_compl */ /* Connection request event */ static int @@ -617,8 +620,10 @@ con_req(ng_hci_unit_p unit, struct mbuf *event) ng_hci_con_timeout(con); error = ng_hci_lp_con_ind(con, ep->uclass); - if (error != 0) + if (error != 0) { + ng_hci_con_untimeout(con); ng_hci_free_con(con); + } } else error = ENOMEM; } @@ -655,6 +660,11 @@ discon_compl(ng_hci_unit_p unit, struct mbuf *event) con = ng_hci_con_by_handle(unit, h); if (con != NULL) { error = ng_hci_lp_discon_ind(con, ep->reason); + + /* Remove all timeouts (if any) */ + if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) + ng_hci_con_untimeout(con); + ng_hci_free_con(con); } else { NG_HCI_ALERT( diff --git a/sys/netgraph/bluetooth/hci/ng_hci_misc.c b/sys/netgraph/bluetooth/hci/ng_hci_misc.c index fb7c661..7de83c3 100644 --- a/sys/netgraph/bluetooth/hci/ng_hci_misc.c +++ b/sys/netgraph/bluetooth/hci/ng_hci_misc.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_hci_misc.c,v 1.4 2003/04/26 22:35:21 max Exp $ + * $Id: ng_hci_misc.c,v 1.5 2003/09/08 18:57:51 max Exp $ * $FreeBSD$ */ @@ -51,9 +51,6 @@ ****************************************************************************** ******************************************************************************/ -static void ng_hci_command_queue_timeout (void *); -static void ng_hci_con_queue_timeout (void *); - /* * Give packet to RAW hook * Assumes input mbuf is read only. @@ -145,6 +142,10 @@ ng_hci_unit_clean(ng_hci_unit_p unit, int reason) while (!LIST_EMPTY(&unit->con_list)) { ng_hci_unit_con_p con = LIST_FIRST(&unit->con_list); + /* Remove all timeouts (if any) */ + if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) + ng_hci_con_untimeout(con); + /* * Notify upper layer protocol and destroy connection * descriptor. Do not really care about the result. @@ -253,12 +254,32 @@ ng_hci_new_con(ng_hci_unit_p unit, int link_type) { ng_hci_unit_con_p con = NULL; int num_pkts; + static int fake_con_handle = 0x0f00; MALLOC(con, ng_hci_unit_con_p, sizeof(*con), M_NETGRAPH_HCI, M_NOWAIT | M_ZERO); if (con != NULL) { con->unit = unit; con->state = NG_HCI_CON_CLOSED; + + /* + * XXX + * + * Assign fake connection handle to the connection descriptor. + * Bluetooth specification marks 0x0f00 - 0x0fff connection + * handles as reserved. We need this fake connection handles + * for timeouts. Connection handle will be passed as argument + * to timeout so when timeout happens we can find the right + * connection descriptor. We can not pass pointers, because + * timeouts are external (to Netgraph) events and there might + * be a race when node/hook goes down and timeout event already + * went into node's queue + */ + + con->con_handle = fake_con_handle ++; + if (fake_con_handle > 0x0fff) + fake_con_handle = 0x0f00; + con->link_type = link_type; if (con->link_type == NG_HCI_LINK_ACL) @@ -285,10 +306,6 @@ ng_hci_free_con(ng_hci_unit_con_p con) { LIST_REMOVE(con, next); - /* Remove all timeouts (if any) */ - if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) - ng_hci_con_untimeout(con); - /* * If we have pending packets then assume that Host Controller has * flushed these packets and we can free them too @@ -340,102 +357,83 @@ ng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type) /* * Set HCI command timeout + * XXX FIXME: check unit->cmd_timo.callout != NULL */ -void +int ng_hci_command_timeout(ng_hci_unit_p unit) { - if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) { - NG_NODE_REF(unit->node); - unit->state |= NG_HCI_UNIT_COMMAND_PENDING; - unit->cmd_timo = timeout(ng_hci_command_queue_timeout, unit, - bluetooth_hci_command_timeout()); - } else - KASSERT(0, -("%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node))); + if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) + panic( +"%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node)); + + unit->state |= NG_HCI_UNIT_COMMAND_PENDING; + unit->cmd_timo = ng_timeout(unit->node, NULL, + bluetooth_hci_command_timeout(), + ng_hci_process_command_timeout, NULL, 0); + + return (0); } /* ng_hci_command_timeout */ /* * Unset HCI command timeout */ -void +int ng_hci_command_untimeout(ng_hci_unit_p unit) { - if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) { - unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; - untimeout(ng_hci_command_queue_timeout, unit, unit->cmd_timo); - NG_NODE_UNREF(unit->node); - } else - KASSERT(0, -("%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node))); -} /* ng_hci_command_untimeout */ + if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) + panic( +"%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node)); -/* - * OK timeout has happend, so queue timeout processing function - */ - -static void -ng_hci_command_queue_timeout(void *context) -{ - ng_hci_unit_p unit = (ng_hci_unit_p) context; - node_p node = unit->node; + if (ng_untimeout(unit->cmd_timo, unit->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node,NULL,&ng_hci_process_command_timeout,unit,0); + unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; - NG_NODE_UNREF(node); -} /* ng_hci_command_queue_timeout */ + return (0); +} /* ng_hci_command_untimeout */ /* * Set HCI connection timeout + * XXX FIXME: check unit->cmd_timo.callout != NULL */ -void +int ng_hci_con_timeout(ng_hci_unit_con_p con) { - if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) { - NG_NODE_REF(con->unit->node); - con->flags |= NG_HCI_CON_TIMEOUT_PENDING; - con->con_timo = timeout(ng_hci_con_queue_timeout, con, - bluetooth_hci_connect_timeout()); - } else - KASSERT(0, -("%s: %s - Duplicated connection timeout!\n", - __func__, NG_NODE_NAME(con->unit->node))); + if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) + panic( +"%s: %s - Duplicated connection timeout!\n", + __func__, NG_NODE_NAME(con->unit->node)); + + con->flags |= NG_HCI_CON_TIMEOUT_PENDING; + con->con_timo = ng_timeout(con->unit->node, NULL, + bluetooth_hci_connect_timeout(), + ng_hci_process_con_timeout, NULL, + con->con_handle); + + return (0); } /* ng_hci_con_timeout */ /* * Unset HCI connection timeout */ -void +int ng_hci_con_untimeout(ng_hci_unit_con_p con) { - if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) { - con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING; - untimeout(ng_hci_con_queue_timeout, con, con->con_timo); - NG_NODE_UNREF(con->unit->node); - } else - KASSERT(0, -("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node))); -} /* ng_hci_con_untimeout */ + if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) + panic( +"%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node)); -/* - * OK timeout has happend, so queue timeout processing function - */ - -static void -ng_hci_con_queue_timeout(void *context) -{ - ng_hci_unit_con_p con = (ng_hci_unit_con_p) context; - node_p node = con->unit->node; + if (ng_untimeout(con->con_timo, con->unit->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node, NULL, &ng_hci_process_con_timeout, con, 0); + con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING; - NG_NODE_UNREF(node); -} /* ng_hci_con_queue_timeout */ + return (0); +} /* ng_hci_con_untimeout */ #if 0 /* diff --git a/sys/netgraph/bluetooth/hci/ng_hci_misc.h b/sys/netgraph/bluetooth/hci/ng_hci_misc.h index b9f29cd..6d1a61f 100644 --- a/sys/netgraph/bluetooth/hci/ng_hci_misc.h +++ b/sys/netgraph/bluetooth/hci/ng_hci_misc.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_hci_misc.h,v 1.2 2003/04/26 22:35:21 max Exp $ + * $Id: ng_hci_misc.h,v 1.3 2003/09/08 18:57:51 max Exp $ * $FreeBSD$ */ @@ -47,10 +47,10 @@ void ng_hci_free_con (ng_hci_unit_con_p); ng_hci_unit_con_p ng_hci_con_by_handle (ng_hci_unit_p, int); ng_hci_unit_con_p ng_hci_con_by_bdaddr (ng_hci_unit_p, bdaddr_p, int); -void ng_hci_command_timeout (ng_hci_unit_p); -void ng_hci_command_untimeout (ng_hci_unit_p); -void ng_hci_con_timeout (ng_hci_unit_con_p); -void ng_hci_con_untimeout (ng_hci_unit_con_p); +int ng_hci_command_timeout (ng_hci_unit_p); +int ng_hci_command_untimeout (ng_hci_unit_p); +int ng_hci_con_timeout (ng_hci_unit_con_p); +int ng_hci_con_untimeout (ng_hci_unit_con_p); #endif /* ndef _NETGRAPH_HCI_MISC_H_ */ diff --git a/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c b/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c index 927cfe1..e7b2d3a 100644 --- a/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c +++ b/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_hci_ulpi.c,v 1.6 2003/04/26 22:35:21 max Exp $ + * $Id: ng_hci_ulpi.c,v 1.7 2003/09/08 18:57:51 max Exp $ * $FreeBSD$ */ @@ -195,11 +195,9 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit, item_p item, hook_p hook) } break; default: - KASSERT(0, -("%s: %s - Invalid connection state=%d\n", - __func__, NG_NODE_NAME(unit->node),con->state)); - - error = EINVAL; + panic( +"%s: %s - Invalid connection state=%d\n", + __func__, NG_NODE_NAME(unit->node), con->state); break; } @@ -390,12 +388,10 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook) break; default: - KASSERT(0, -("%s: %s - Inavalid connection state=%d\n", + panic( +"%s: %s - Inavalid connection state=%d\n", __func__, NG_NODE_NAME(unit->node), - sco_con->state)); - - error = EINVAL; + sco_con->state); break; } @@ -763,10 +759,13 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook) } /* - * Remove connection timeout and check connection state + * Remove connection timeout and check connection state. + * Note: if ng_hci_con_untimeout() fails (returns non-zero value) then + * timeout already happened and event went into node's queue. */ - ng_hci_con_untimeout(con); + if ((error = ng_hci_con_untimeout(con)) != 0) + goto out; switch (con->state) { case NG_HCI_CON_W4_LP_CON_RSP: @@ -856,11 +855,9 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook) break; default: - KASSERT(0, -("%s: %s - Invalid connection state=%d\n", - __func__, NG_NODE_NAME(unit->node), con->state)); - - error = EINVAL; + panic( +"%s: %s - Invalid connection state=%d\n", + __func__, NG_NODE_NAME(unit->node), con->state); break; } out: @@ -1150,12 +1147,33 @@ ng_hci_lp_qos_ind(ng_hci_unit_con_p con) */ void -ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2) +ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int con_handle) { - ng_hci_unit_con_p con = (ng_hci_unit_con_p) arg1; + ng_hci_unit_p unit = NULL; + ng_hci_unit_con_p con = NULL; + + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } - KASSERT((con->flags & NG_HCI_CON_TIMEOUT_PENDING), -("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(node))); + unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node); + con = ng_hci_con_by_handle(unit, con_handle); + + if (con == NULL) { + NG_HCI_ALERT( +"%s: %s - could not find connection, handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) { + NG_HCI_ALERT( +"%s: %s - no pending connection timeout, handle=%d, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(node), con_handle, con->state, + con->flags); + return; + } con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING; @@ -1181,9 +1199,9 @@ ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2) break; default: - KASSERT(0, -("%s: %s - Invalid connection state=%d\n", - __func__, NG_NODE_NAME(node), con->state)); + panic( +"%s: %s - Invalid connection state=%d\n", + __func__, NG_NODE_NAME(node), con->state); break; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c index 844c5a6..68e57ef 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_cmds.c,v 1.1 2002/11/24 19:47:06 max Exp $ + * $Id: ng_l2cap_cmds.c,v 1.2 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -69,7 +69,7 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con) TAILQ_FOREACH(cmd, &con->cmd_list, next) { KASSERT((cmd->con == con), ("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); + __func__, NG_NODE_NAME(con->l2cap->node))); if (!(cmd->flags & NG_L2CAP_CMD_PENDING)) break; @@ -200,12 +200,9 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unknown command code=%d\n", - __func__, NG_NODE_NAME(con->l2cap->node), cmd->code)); - - ng_l2cap_unlink_cmd(cmd); - ng_l2cap_free_cmd(cmd); + panic( +"%s: %s - unknown command code=%d\n", + __func__, NG_NODE_NAME(con->l2cap->node), cmd->code); break; } } /* ng_l2cap_con_wakeup */ @@ -237,7 +234,7 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) KASSERT((cmd->con == con), ("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); + __func__, NG_NODE_NAME(l2cap->node))); switch (cmd->code) { case NG_L2CAP_CMD_REJ: @@ -280,10 +277,9 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unexpected command code=%d\n", - __func__, NG_NODE_NAME(con->l2cap->node), - cmd->code)); + panic( +"%s: %s - unexpected command code=%d\n", + __func__, NG_NODE_NAME(l2cap->node), cmd->code); break; } @@ -314,11 +310,34 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) void ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) { - ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) arg1; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; + ng_l2cap_cmd_p cmd = NULL; + u_int16_t con_handle = (arg2 & 0x0ffff); + u_int8_t ident = ((arg2 >> 16) & 0xff); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command flags flags=%#x!\n", - __func__, NG_NODE_NAME(cmd->con->l2cap->node), cmd->flags)); + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } + + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + + con = ng_l2cap_con_by_handle(l2cap, con_handle); + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + cmd = ng_l2cap_cmd_by_ident(con, ident); + if (cmd == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find command, con_handle=%d, ident=%d\n", + __func__, NG_NODE_NAME(node), con_handle, ident); + return; + } cmd->flags &= ~NG_L2CAP_CMD_PENDING; ng_l2cap_unlink_cmd(cmd); @@ -340,7 +359,7 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) case NG_L2CAP_ECHO_REQ: /* Echo request timed out. Let the upper layer know */ - ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, + ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, NG_L2CAP_TIMEOUT, NULL); break; @@ -353,10 +372,9 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unexpected command code=%d\n", - __func__, NG_NODE_NAME(cmd->con->l2cap->node), - cmd->code)); + panic( +"%s: %s - unexpected command code=%d\n", + __func__, NG_NODE_NAME(l2cap->node), cmd->code); break; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c index 4a9c6fd..de5217c 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_evnt.c,v 1.4 2003/04/01 18:15:26 max Exp $ + * $Id: ng_l2cap_evnt.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -285,14 +285,12 @@ ng_l2cap_process_cmd_rej(ng_l2cap_con_p con, u_int8_t ident) /* Check if we have pending command descriptor */ cmd = ng_l2cap_cmd_by_ident(con, ident); if (cmd != NULL) { - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(con->l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore reject */ + if (ng_l2cap_command_untimeout(cmd) != 0) { + NG_FREE_M(con->rx_pkt); + return (ETIMEDOUT); + } + ng_l2cap_unlink_cmd(cmd); switch (cmd->code) { @@ -432,10 +430,6 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify channel state, if invalid - do nothing */ if (cmd->ch->state != NG_L2CAP_W4_L2CAP_CON_RSP) { NG_L2CAP_ERR( @@ -458,10 +452,12 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident) /* * Looks good. We got confirmation from our peer. Now process * it. First disable RTX timer. Then check the result and send - * notification to the upper layer. + * notification to the upper layer. If command timeout already + * happened then ignore response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) + return (error); if (result == NG_L2CAP_PENDING) { /* @@ -585,10 +581,7 @@ ng_l2cap_process_cfg_req(ng_l2cap_con_p con, u_int8_t ident) bcopy(&val.flow, &ch->iflow, sizeof(ch->iflow)); break; - default: - KASSERT(0, -("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node), - hdr.type)); + default: /* Ignore unknown hint option */ break; } } else { /* Oops, something is wrong */ @@ -692,10 +685,6 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify CIDs and send reject if does not match */ if (cmd->ch->scid != scid) { NG_L2CAP_ERR( @@ -721,10 +710,14 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) * then verify C flag. If it is set then we shall expect more * configuration options from the peer and we will wait. Otherwise we * have received all options and we will send L2CA_ConfigRsp event to - * the upper layer protocol. + * the upper layer protocol. If command timeout already happened then + * ignore response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(m); + return (error); + } for (off = 0; ; ) { error = get_next_l2cap_opt(m, &off, &hdr, &val); @@ -745,19 +738,16 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) sizeof(cmd->ch->oflow)); break; - default: - KASSERT(0, -("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node), - hdr.type)); + default: /* Ignore unknown hint option */ break; } } else { /* * XXX FIXME What to do here? * - * This is really BAD :( options packet was broken, - * so let upper layer know and do not wait for more - * options + * This is really BAD :( options packet was broken, or + * peer sent us option that we did not understand. Let + * upper layer know and do not wait for more options. */ NG_L2CAP_ALERT( @@ -934,10 +924,6 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident) goto out; } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify channel state, do nothing if invalid */ if (cmd->ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) { NG_L2CAP_ERR( @@ -959,11 +945,14 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident) } /* - * Looks like we have successfuly disconnected channel, - * so notify upper layer. + * Looks like we have successfuly disconnected channel, so notify + * upper layer. If command timeout already happened then ignore + * response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) + goto out; + error = ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token, NG_L2CAP_SUCCESS); ng_l2cap_free_chan(cmd->ch); /* this will free commands too */ out: @@ -1025,14 +1014,12 @@ ng_l2cap_process_echo_rsp(ng_l2cap_con_p con, u_int8_t ident) /* Check if we have this command */ cmd = ng_l2cap_cmd_by_ident(con, ident); if (cmd != NULL) { - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore response */ + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(con->rx_pkt); + return (error); + } + ng_l2cap_unlink_cmd(cmd); error = ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, @@ -1133,14 +1120,12 @@ ng_l2cap_process_info_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore response */ + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(con->rx_pkt); + return (error); + } + ng_l2cap_unlink_cmd(cmd); if (cp->result == NG_L2CAP_SUCCESS) { diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c index bc110ad..b0b6fbe 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_llpi.c,v 1.4 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_llpi.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -114,7 +114,9 @@ ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr) NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL); if (error != 0) { - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + return (error); + ng_l2cap_free_con(con); } @@ -168,10 +170,13 @@ ng_l2cap_lp_con_cfm(ng_l2cap_p l2cap, struct ng_mesg *msg) /* * Looks like it is our confirmation. It is safe now to cancel - * connection timer and notify upper layer. + * connection timer and notify upper layer. If timeout already + * happened then ignore connection confirmation and let timeout + * handle that. */ - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + goto out; if (ep->status == 0) { con->state = NG_L2CAP_CON_OPEN; @@ -259,7 +264,9 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, struct ng_mesg *msg) NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, NULL); if (error != 0) { - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + goto out; + ng_l2cap_free_con(con); } out: @@ -311,9 +318,16 @@ ng_l2cap_lp_discon_ind(ng_l2cap_p l2cap, struct ng_mesg *msg) goto out; } - /* Notify upper layer and remove connection */ + /* + * Notify upper layer and remove connection + * Note: The connection could have auto disconnect timeout set. Try + * to remove it. If auto disconnect timeout happened then ignore + * disconnect indication and let timeout handle that. + */ + if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) - ng_l2cap_discon_untimeout(con); + if ((error = ng_l2cap_discon_untimeout(con)) != 0) + return (error); ng_l2cap_con_fail(con, ep->reason); out: @@ -791,13 +805,33 @@ drop: */ void -ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2) +ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int con_handle) { - ng_l2cap_con_p con = (ng_l2cap_con_p) arg1; - ng_l2cap_p l2cap = con->l2cap; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; + + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } - NG_L2CAP_ERR( -"%s: %s - ACL connection timeout\n", __func__, NG_NODE_NAME(l2cap->node)); + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + con = ng_l2cap_con_by_handle(l2cap, con_handle); + + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + if (!(con->flags & NG_L2CAP_CON_LP_TIMO)) { + NG_L2CAP_ALERT( +"%s: %s - no pending LP timeout, con_handle=%d, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(node), con_handle, con->state, + con->flags); + return; + } /* * Notify channels that connection has timed out. This will remove @@ -814,14 +848,37 @@ ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2) */ void -ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2) +ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int con_handle) { - ng_l2cap_con_p con = (ng_l2cap_con_p) arg1; - ng_l2cap_p l2cap = con->l2cap; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; struct ng_mesg *msg = NULL; ng_hci_lp_discon_req_ep *ep = NULL; int error; + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } + + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + con = ng_l2cap_con_by_handle(l2cap, con_handle); + + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)) { + NG_L2CAP_ALERT( +"%s: %s - no pending disconnect timeout, con_handle=%d, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(node), con_handle, con->state, + con->flags); + return; + } + con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO; /* Check if lower layer protocol is still connected */ @@ -829,7 +886,6 @@ ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2) NG_L2CAP_ERR( "%s: %s - hook \"%s\" is not connected or valid\n", __func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); - return; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c index 43a6d13..dd581c1 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_misc.c,v 1.4 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_misc.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -47,10 +47,7 @@ #include "ng_l2cap_ulpi.h" #include "ng_l2cap_misc.h" -static u_int16_t ng_l2cap_get_cid (ng_l2cap_p); -static void ng_l2cap_queue_discon_timeout (void *); -static void ng_l2cap_queue_lp_timeout (void *); -static void ng_l2cap_queue_command_timeout (void *); +static u_int16_t ng_l2cap_get_cid (ng_l2cap_p); /****************************************************************************** ****************************************************************************** @@ -101,6 +98,7 @@ ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2) ng_l2cap_con_p ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr) { + static int fake_con_handle = 0x0f00; ng_l2cap_con_p con = NULL; /* Create new connection descriptor */ @@ -112,6 +110,24 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr) con->l2cap = l2cap; con->state = NG_L2CAP_CON_CLOSED; + /* + * XXX + * + * Assign fake connection handle to the connection descriptor. + * Bluetooth specification marks 0x0f00 - 0x0fff connection + * handles as reserved. We need this fake connection handles + * for timeouts. Connection handle will be passed as argument + * to timeout so when timeout happens we can find the right + * connection descriptor. We can not pass pointers, because + * timeouts are external (to Netgraph) events and there might + * be a race when node/hook goes down and timeout event already + * went into node's queue + */ + + con->con_handle = fake_con_handle ++; + if (fake_con_handle > 0x0fff) + fake_con_handle = 0x0f00; + bcopy(bdaddr, &con->remote, sizeof(con->remote)); callout_handle_init(&con->con_timo); @@ -136,8 +152,10 @@ ng_l2cap_con_ref(ng_l2cap_con_p con) if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) { if ((con->state != NG_L2CAP_CON_OPEN) || (con->flags & NG_L2CAP_CON_OUTGOING) == 0) - panic("%s: %s - bad auto disconnect timeout\n", - __func__, NG_NODE_NAME(con->l2cap->node)); + panic( +"%s: %s - bad auto disconnect timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); ng_l2cap_discon_untimeout(con); } @@ -153,8 +171,8 @@ ng_l2cap_con_unref(ng_l2cap_con_p con) con->refcnt --; if (con->refcnt < 0) - panic("%s: %s - con->refcnt < 0\n", - __func__, NG_NODE_NAME(con->l2cap->node)); + panic( +"%s: %s - con->refcnt < 0\n", __func__, NG_NODE_NAME(con->l2cap->node)); /* * Set auto disconnect timer only if the following conditions are met: @@ -167,60 +185,53 @@ ng_l2cap_con_unref(ng_l2cap_con_p con) if ((con->refcnt == 0) && (con->state == NG_L2CAP_CON_OPEN) && (con->flags & NG_L2CAP_CON_OUTGOING) && - (con->l2cap->discon_timo > 0)) { - if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) - panic("%s: %s - duplicated auto disconnect timeout\n", - __func__, NG_NODE_NAME(con->l2cap->node)); - + (con->l2cap->discon_timo > 0)) ng_l2cap_discon_timeout(con); - } } /* ng_l2cap_con_unref */ /* * Set auto disconnect timeout + * XXX FIXME: check con->con_timo.callout != NULL */ -void +int ng_l2cap_discon_timeout(ng_l2cap_con_p con) { if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO)) - panic("%s: %s - invalid timeout, state=%d, flags=%#x\n", + panic( +"%s: %s - invalid timeout, state=%d, flags=%#x\n", __func__, NG_NODE_NAME(con->l2cap->node), con->state, con->flags); - NG_NODE_REF(con->l2cap->node); con->flags |= NG_L2CAP_CON_AUTO_DISCON_TIMO; - con->con_timo = timeout(ng_l2cap_queue_discon_timeout, con, - con->l2cap->discon_timo * hz); + con->con_timo = ng_timeout(con->l2cap->node, NULL, + con->l2cap->discon_timo * hz, + ng_l2cap_process_discon_timeout, NULL, + con->con_handle); + + return (0); } /* ng_l2cap_discon_timeout */ /* * Unset auto disconnect timeout */ -void +int ng_l2cap_discon_untimeout(ng_l2cap_con_p con) { - untimeout(ng_l2cap_queue_discon_timeout, con, con->con_timo); - con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO; - NG_NODE_UNREF(con->l2cap->node); -} /* ng_l2cap_discon_untimeout */ - -/* - * Queue auto disconnect timeout - */ - -static void -ng_l2cap_queue_discon_timeout(void *context) -{ - ng_l2cap_con_p con = (ng_l2cap_con_p) context; - node_p node = con->l2cap->node; + if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)) + panic( +"%s: %s - no disconnect timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); + + if (ng_untimeout(con->con_timo, con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node,NULL,&ng_l2cap_process_discon_timeout,con,0); + con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_discon_timeout */ + return (0); +} /* ng_l2cap_discon_untimeout */ /* * Free connection descriptor. Will unlink connection and free everything. @@ -231,20 +242,13 @@ ng_l2cap_free_con(ng_l2cap_con_p con) { ng_l2cap_chan_p f = NULL, n = NULL; - if (con->flags & NG_L2CAP_CON_LP_TIMO) - ng_l2cap_lp_untimeout(con); - else if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) - ng_l2cap_discon_untimeout(con); - con->state = NG_L2CAP_CON_CLOSED; - if (con->tx_pkt != NULL) { - while (con->tx_pkt != NULL) { - struct mbuf *m = con->tx_pkt->m_nextpkt; + while (con->tx_pkt != NULL) { + struct mbuf *m = con->tx_pkt->m_nextpkt; - m_freem(con->tx_pkt); - con->tx_pkt = m; - } + m_freem(con->tx_pkt); + con->tx_pkt = m; } NG_FREE_M(con->rx_pkt); @@ -262,6 +266,8 @@ ng_l2cap_free_con(ng_l2cap_con_p con) ng_l2cap_cmd_p cmd = TAILQ_FIRST(&con->cmd_list); ng_l2cap_unlink_cmd(cmd); + if (cmd->flags & NG_L2CAP_CMD_PENDING) + ng_l2cap_command_untimeout(cmd); ng_l2cap_free_cmd(cmd); } @@ -378,6 +384,8 @@ ng_l2cap_free_chan(ng_l2cap_chan_p ch) if (f->ch == ch) { ng_l2cap_unlink_cmd(f); + if (f->flags & NG_L2CAP_CMD_PENDING) + ng_l2cap_command_untimeout(f); ng_l2cap_free_cmd(f); } @@ -422,7 +430,7 @@ ng_l2cap_new_cmd(ng_l2cap_con_p con, ng_l2cap_chan_p ch, u_int8_t ident, } /* ng_l2cap_new_cmd */ /* - * Get L2CAP command descriptor by ident + * Get pending (i.e. initiated by local side) L2CAP command descriptor by ident */ ng_l2cap_cmd_p @@ -430,114 +438,107 @@ ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident) { ng_l2cap_cmd_p cmd = NULL; - TAILQ_FOREACH(cmd, &con->cmd_list, next) - if (cmd->ident == ident) + TAILQ_FOREACH(cmd, &con->cmd_list, next) { + if ((cmd->flags & NG_L2CAP_CMD_PENDING) && cmd->ident == ident) { + KASSERT((cmd->con == con), +("%s: %s - invalid connection pointer!\n", + __func__, NG_NODE_NAME(con->l2cap->node))); + break; + } + } return (cmd); } /* ng_l2cap_cmd_by_ident */ /* * Set LP timeout + * XXX FIXME: check con->con_timo.callout != NULL */ -void +int ng_l2cap_lp_timeout(ng_l2cap_con_p con) { if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO)) - panic("%s: %s - invalid timeout, state=%d, flags=%#x\n", + panic( +"%s: %s - invalid timeout, state=%d, flags=%#x\n", __func__, NG_NODE_NAME(con->l2cap->node), con->state, con->flags); - NG_NODE_REF(con->l2cap->node); con->flags |= NG_L2CAP_CON_LP_TIMO; - con->con_timo = timeout(ng_l2cap_queue_lp_timeout, con, - bluetooth_hci_connect_timeout()); + con->con_timo = ng_timeout(con->l2cap->node, NULL, + bluetooth_hci_connect_timeout(), + ng_l2cap_process_lp_timeout, NULL, + con->con_handle); + + return (0); } /* ng_l2cap_lp_timeout */ /* * Unset LP timeout */ -void +int ng_l2cap_lp_untimeout(ng_l2cap_con_p con) { - untimeout(ng_l2cap_queue_lp_timeout, con, con->con_timo); - con->flags &= ~NG_L2CAP_CON_LP_TIMO; - NG_NODE_UNREF(con->l2cap->node); -} /* ng_l2cap_lp_untimeout */ - -/* - * OK, timeout has happend so queue LP timeout processing function - */ - -static void -ng_l2cap_queue_lp_timeout(void *context) -{ - ng_l2cap_con_p con = (ng_l2cap_con_p) context; - node_p node = con->l2cap->node; - - /* - * We need to save node pointer here, because ng_send_fn() - * can execute ng_l2cap_process_lp_timeout() without putting - * item into node's queue (if node can be locked). Once - * ng_l2cap_process_lp_timeout() executed the con pointer - * is no longer valid. - */ + if (!(con->flags & NG_L2CAP_CON_LP_TIMO)) + panic( +"%s: %s - no LP connection timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); + + if (ng_untimeout(con->con_timo, con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node, NULL, &ng_l2cap_process_lp_timeout, con, 0); + con->flags &= ~NG_L2CAP_CON_LP_TIMO; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_lp_timeout */ + return (0); +} /* ng_l2cap_lp_untimeout */ /* * Set L2CAP command timeout + * XXX FIXME: check cmd->timo.callout != NULL */ -void +int ng_l2cap_command_timeout(ng_l2cap_cmd_p cmd, int timo) { - NG_NODE_REF(cmd->con->l2cap->node); + int arg; + + if (cmd->flags & NG_L2CAP_CMD_PENDING) + panic( +"%s: %s - duplicated command timeout, code=%#x, flags=%#x\n", + __func__, NG_NODE_NAME(cmd->con->l2cap->node), + cmd->code, cmd->flags); + + arg = ((cmd->ident << 16) | cmd->con->con_handle); cmd->flags |= NG_L2CAP_CMD_PENDING; - cmd->timo = timeout(ng_l2cap_queue_command_timeout, cmd, timo); + cmd->timo = ng_timeout(cmd->con->l2cap->node, NULL, timo, + ng_l2cap_process_command_timeout, NULL, arg); + + return (0); } /* ng_l2cap_command_timeout */ /* * Unset L2CAP command timeout */ -void +int ng_l2cap_command_untimeout(ng_l2cap_cmd_p cmd) { - cmd->flags &= ~NG_L2CAP_CMD_PENDING; - untimeout(ng_l2cap_queue_command_timeout, cmd, cmd->timo); - NG_NODE_UNREF(cmd->con->l2cap->node); -} /* ng_l2cap_command_untimeout */ - -/* - * OK, timeout has happend so queue L2CAP command timeout processing function - */ - -static void -ng_l2cap_queue_command_timeout(void *context) -{ - ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) context; - node_p node = cmd->con->l2cap->node; + if (!(cmd->flags & NG_L2CAP_CMD_PENDING)) + panic( +"%s: %s - no command timeout, code=%#x, flags=%#x\n", + __func__, NG_NODE_NAME(cmd->con->l2cap->node), + cmd->code, cmd->flags); - /* - * We need to save node pointer here, because ng_send_fn() - * can execute ng_l2cap_process_command_timeout() without - * putting item into node's queue (if node can be locked). - * Once ng_l2cap_process_command_timeout() executed the - * cmd pointer is no longer valid. - */ + if (ng_untimeout(cmd->timo, cmd->con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node,NULL,&ng_l2cap_process_command_timeout,cmd,0); + cmd->flags &= ~NG_L2CAP_CMD_PENDING; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_command_timeout */ + return (0); +} /* ng_l2cap_command_untimeout */ /* * Prepend "m"buf with "size" bytes diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h index a20d5b9..310f676 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_misc.h,v 1.2 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_misc.h,v 1.3 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -71,9 +71,6 @@ do { \ #define ng_l2cap_free_cmd(cmd) \ do { \ - if ((cmd)->flags & NG_L2CAP_CMD_PENDING) \ - ng_l2cap_command_untimeout((cmd)); \ - \ NG_FREE_M((cmd)->aux); \ bzero((cmd), sizeof(*(cmd))); \ FREE((cmd), M_NETGRAPH_L2CAP); \ @@ -88,12 +85,12 @@ u_int8_t ng_l2cap_get_ident (ng_l2cap_con_p); * Timeout */ -void ng_l2cap_discon_timeout (ng_l2cap_con_p); -void ng_l2cap_discon_untimeout (ng_l2cap_con_p); -void ng_l2cap_lp_timeout (ng_l2cap_con_p); -void ng_l2cap_lp_untimeout (ng_l2cap_con_p); -void ng_l2cap_command_timeout (ng_l2cap_cmd_p, int); -void ng_l2cap_command_untimeout (ng_l2cap_cmd_p); +int ng_l2cap_discon_timeout (ng_l2cap_con_p); +int ng_l2cap_discon_untimeout (ng_l2cap_con_p); +int ng_l2cap_lp_timeout (ng_l2cap_con_p); +int ng_l2cap_lp_untimeout (ng_l2cap_con_p); +int ng_l2cap_command_timeout (ng_l2cap_cmd_p, int); +int ng_l2cap_command_untimeout (ng_l2cap_cmd_p); /* * Other stuff diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket.c b/sys/netgraph/bluetooth/socket/ng_btsocket.c index be719fc..e8ad4ad 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket.c,v 1.3 2003/01/19 00:19:04 max Exp $ + * $Id: ng_btsocket.c,v 1.4 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/errno.h> #include <sys/domain.h> #include <sys/kernel.h> @@ -41,7 +42,6 @@ #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/taskqueue.h> -#include <sys/bitstring.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> #include "ng_bluetooth.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c index 631753d..bcf4196 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_hci_raw.c,v 1.13 2003/04/01 18:15:27 max Exp $ + * $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -49,7 +50,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c index d074342..799e259 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_l2cap.c,v 1.14 2003/04/06 22:53:18 max Exp $ + * $Id: ng_btsocket_l2cap.c,v 1.16 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -49,7 +50,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" @@ -1411,7 +1411,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook) rt->src.b[2], rt->src.b[1], rt->src.b[0], hdr->dcid, hdr->length); - if (NG_L2CAP_FIRST_CID <= hdr->dcid && hdr->dcid <= NG_L2CAP_LAST_CID) { + if (hdr->dcid >= NG_L2CAP_FIRST_CID) { mtx_lock(&ng_btsocket_l2cap_sockets_mtx); diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c index 7fcb36e..85df6c2 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_l2cap_raw.c,v 1.11 2003/04/27 19:52:14 max Exp $ + * $Id: ng_btsocket_l2cap_raw.c,v 1.12 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/errno.h> #include <sys/filedesc.h> @@ -48,7 +49,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c index 7ffb828..8827210 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_rfcomm.c,v 1.24 2003/04/07 01:37:05 max Exp $ + * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -51,7 +52,6 @@ #include <sys/uio.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" @@ -2025,6 +2025,9 @@ ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci) pcb->dlci = dlci; error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); + if (error == 0) + error = ng_btsocket_rfcomm_send_msc(pcb); + if (error == 0) { pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; soisconnected(pcb->so); @@ -3139,7 +3142,13 @@ ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb) hdr->length = RFCOMM_MKLEN8(sizeof(*pn)); pn->dlci = pcb->dlci; - pn->priority = 0; + + /* + * Set default DLCI priority as described in GSM 07.10 + * (ETSI TS 101 369) clause 5.6 page 42 + */ + + pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61; pn->ack_timer = 0; pn->mtu = htole16(pcb->mtu); pn->max_retrans = 0; diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 1a61881..da67aaa 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -244,7 +244,8 @@ SUBDIR+=usbhidaction \ .if ${MACHINE_ARCH} == "i386" # Things that don't compile on alpha or are aout specific: -SUBDIR+=doscmd \ +SUBDIR+=bluetooth \ + doscmd \ ncplist \ ncplogin \ sasc \ diff --git a/usr.bin/bluetooth/Makefile b/usr.bin/bluetooth/Makefile index be3146e..9ef16cc 100644 --- a/usr.bin/bluetooth/Makefile +++ b/usr.bin/bluetooth/Makefile @@ -1,7 +1,9 @@ # $Id $ # $FreeBSD$ -SUBDIR= btsockstat \ +SUBDIR= \ + bthost \ + btsockstat \ rfcomm_sppd .include <bsd.subdir.mk> diff --git a/usr.bin/bluetooth/Makefile.inc b/usr.bin/bluetooth/Makefile.inc new file mode 100644 index 0000000..c0e05cf --- /dev/null +++ b/usr.bin/bluetooth/Makefile.inc @@ -0,0 +1,4 @@ +# $FreeBSD$ + +.include "${.CURDIR}/../../Makefile.inc" + diff --git a/usr.bin/bluetooth/bthost/Makefile b/usr.bin/bluetooth/bthost/Makefile new file mode 100644 index 0000000..a761bbc --- /dev/null +++ b/usr.bin/bluetooth/bthost/Makefile @@ -0,0 +1,12 @@ +# $Id: Makefile,v 1.4 2003/08/14 20:07:13 max Exp $ +# $FreeBSD$ + +PROG= bthost +MAN= bthost.1 +SRCS= bthost.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth + +.include <bsd.prog.mk> diff --git a/usr.bin/bluetooth/bthost/bthost.1 b/usr.bin/bluetooth/bthost/bthost.1 new file mode 100644 index 0000000..2fda952 --- /dev/null +++ b/usr.bin/bluetooth/bthost/bthost.1 @@ -0,0 +1,111 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: bthost.1,v 1.7 2003/05/21 22:19:00 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 8, 2003 +.Dt BTHOST 1 +.Os +.Sh NAME +.Nm bthost +.Nd look up Bluetooth host names and Protocol Service Multiplexor values +.Sh SYNOPSIS +.Nm bthost +.Op Fl bhp +.Ar host_or_protocol +.Sh DESCRIPTION +The +.Nm +utility looks for information about Bluetooth hosts and +Protocol Service Multiplexor (PSM) values. +It gets this information from the +.Pa /etc/bluetooth/hosts +and +.Pa /etc/bluetooth/protocols +files. +.Pp +In host mode it simply converts between host names and Bluetooth addresses. +The argument can be either host name or Bluetooth address. +The program first attempts to interpret it as Bluetooth address. +If this fails, it will treat it as host name. +A Bluetooth address consists of six hex bytes sparated by column, +e.g. 01:02:03:04:05:06. +A host name consists of names separated by dots, e.g. my.cell.phone. +.Pp +In protocol mode it simply converts between Protocol Service Multiplexor names +and assigned numbers. +The argument can be either Protocol Service Multiplexor name or assigned number. +The program first attempts to interpret it as assigned number. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl b +Produce brief output. +.It Fl h +Display usage message and exit. +.It Fl p +Activate protocol mode. +.El +.Pp +The +.Nm +utility will print results to the standard output and error messages to the +standard error. +You may see output of different kinds. +Here is an example that shows all of them: +.Pp +.D1 Ic % bthost localhost +.Dl Host localhost has address FF:FF:FF:00:00:00 +.D1 Ic % bthost ff:ff:ff:00:00:00 +.Dl Host FF:FF:FF:00:00:00 has name localhost +.D1 Ic % bthost -b localhost +.Dl FF:FF:FF:00:00:00 +.D1 Ic % bthost -b ff:ff:ff:00:00:00 +.Dl localhost +.D1 Ic % bthost do.not.exists +.Dl do.not.exists: Unknown host +.D1 Ic % bthost 0:0:0:0:0:0 +.Dl 00:00:00:00:00:00: Unknown host +.D1 Ic % bthost -p sdp +.Dl Protocol/Service Multiplexor sdp has number 1 +.D1 Ic % bthost -p 3 +.Dl Protocol/Service Multiplexor rfcomm has number 3 +.D1 Ic % bthost -bp HID-Control +.Dl 17 +.D1 Ic % bthost -p foo +.Dl foo: Unknown Protocol/Service Multiplexor +.Sh FILES +.Bl -tag -width "/etc/bluetooth/hosts" -compact +.It Pa /etc/bluetooth/hosts +.It Pa /etc/bluetooth/protocols +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr bluetooth 3 , +.Xr bluetooth.hosts 5 , +.Xr bluetooth.protocols 5 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/usr.bin/bluetooth/bthost/bthost.c b/usr.bin/bluetooth/bthost/bthost.c new file mode 100644 index 0000000..2dd5635 --- /dev/null +++ b/usr.bin/bluetooth/bthost/bthost.c @@ -0,0 +1,142 @@ +/* + * bthost.c + * + * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: bthost.c,v 1.5 2003/05/21 20:30:01 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static int hostmode (char const *arg, int brief); +static int protomode (char const *arg, int brief); +static void usage (void); + +int +main(int argc, char **argv) +{ + int opt, brief = 0, proto = 0; + + while ((opt = getopt(argc, argv, "bhp")) != -1) { + switch (opt) { + case 'b': + brief = 1; + break; + + case 'p': + proto = 1; + break; + + case 'h': + default: + usage(); + /* NOT REACHED */ + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + exit(proto? protomode(*argv, brief) : hostmode(*argv, brief)); +} + +static int +hostmode(char const *arg, int brief) +{ + struct hostent *he = NULL; + bdaddr_t ba; + char bastr[32]; + int reverse; + + if (bt_aton(arg, &ba) == 1) { + reverse = 1; + he = bt_gethostbyaddr((char const *) &ba, sizeof(ba), + AF_BLUETOOTH); + } else { + reverse = 0; + he = bt_gethostbyname(arg); + } + + if (he == NULL) { + herror(reverse? bt_ntoa(&ba, bastr) : arg); + return (1); + } + + if (brief) + printf("%s", reverse? he->h_name : + bt_ntoa((bdaddr_t *)(he->h_addr), bastr)); + else + printf("Host %s has %s %s\n", + reverse? bt_ntoa(&ba, bastr) : arg, + reverse? "name" : "address", + reverse? he->h_name : + bt_ntoa((bdaddr_t *)(he->h_addr), bastr)); + + return (0); +} + +static int +protomode(char const *arg, int brief) +{ + struct protoent *pe = NULL; + int proto; + + if ((proto = atoi(arg)) != 0) + pe = bt_getprotobynumber(proto); + else + pe = bt_getprotobyname(arg); + + if (pe == NULL) { + fprintf(stderr, "%s: Unknown Protocol/Service Multiplexor\n", arg); + return (1); + } + + if (brief) { + if (proto) + printf("%s", pe->p_name); + else + printf("%d", pe->p_proto); + } else { + printf("Protocol/Service Multiplexor %s has number %d\n", + pe->p_name, pe->p_proto); + } + + return (0); +} + +static void +usage(void) +{ + fprintf(stdout, "Usage: bthost [-b -h -p] host_or_protocol\n"); + exit(255); +} + diff --git a/usr.bin/bluetooth/btsockstat/Makefile b/usr.bin/bluetooth/btsockstat/Makefile index 7614881..c2314ba 100644 --- a/usr.bin/bluetooth/btsockstat/Makefile +++ b/usr.bin/bluetooth/btsockstat/Makefile @@ -1,19 +1,14 @@ -# $Id: Makefile,v 1.3 2003/03/24 23:59:49 max Exp $ +# $Id: Makefile,v 1.7 2003/08/14 20:07:14 max Exp $ # $FreeBSD$ PROG= btsockstat +MAN= btsockstat.1 +SRCS= btsockstat.c +WARNS?= 2 BINGRP= kmem BINMODE= 2555 -MAN1= btsockstat.1 - -DESTDIR= /usr/bin/ -MANDIR= ../share/man/man -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/ - -SRCS= btsockstat.c -DPADD= ${LIBKVM} -LDADD= -lkvm +DPADD= ${LIBBLUETOOTH} ${LIBKVM} +LDADD= -lbluetooth -lkvm .include <bsd.prog.mk> diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.1 b/usr.bin/bluetooth/btsockstat/btsockstat.1 index d76799b..f9b6064 100644 --- a/usr.bin/bluetooth/btsockstat/btsockstat.1 +++ b/usr.bin/bluetooth/btsockstat/btsockstat.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: btsockstat.1,v 1.4 2003/04/27 19:25:15 max Exp $ +.\" $Id: btsockstat.1,v 1.6 2003/05/21 00:09:45 max Exp $ .\" $FreeBSD$ .\" .Dd August 31, 2002 @@ -33,7 +33,7 @@ .Nd show Bluetooth sockets information .Sh SYNOPSIS .Nm -.Op Fl rh +.Op Fl nrh .Op Fl M Ar core .Op Fl p Ar protocol .Sh DESCRIPTION @@ -57,6 +57,10 @@ Display usage message and exit. Extract values associated with the name list from the specified core instead of the default .Pa /dev/kmem . +.It Fl n +Show Bluetooth addresses as numbers. Normally +.Nm +attempts to resolve Bluetooth addresses, and display them symbolically. .It Fl p Ar protocol Display a list of active sockets (protocol control blocks) for each specified protocol. diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.c b/usr.bin/bluetooth/btsockstat/btsockstat.c index 7911f40..54c1b49 100644 --- a/usr.bin/bluetooth/btsockstat/btsockstat.c +++ b/usr.bin/bluetooth/btsockstat/btsockstat.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: btsockstat.c,v 1.4 2003/03/29 22:28:18 max Exp $ + * $Id: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $ * $FreeBSD$ */ @@ -39,19 +39,16 @@ #include <net/if.h> #include <net/if_var.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <fcntl.h> #include <kvm.h> #include <limits.h> -#include <ng_bluetooth.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> -#include <ng_btsocket_hci_raw.h> -#include <ng_btsocket_l2cap.h> -#include <ng_btsocket_rfcomm.h> +#include <netgraph/bluetooth/include/ng_bluetooth.h> +#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h> +#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h> +#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h> #include <stdio.h> #include <stdlib.h> @@ -65,6 +62,8 @@ static void l2caprtpr (kvm_t *kvmd, u_long addr); static void rfcommpr (kvm_t *kvmd, u_long addr); static void rfcommpr_s (kvm_t *kvmd, u_long addr); +static char * bdaddrpr (bdaddr_p const ba, char *str, int len); + static kvm_t * kopen (char const *memf); static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size); @@ -99,6 +98,8 @@ static struct nlist nl[] = { * Main */ +static int numeric_bdaddr = 0; + int main(int argc, char *argv[]) { @@ -106,8 +107,12 @@ main(int argc, char *argv[]) kvm_t *kvmd = NULL; char *memf = NULL; - while ((opt = getopt(argc, argv, "hM:p:r")) != -1) { + while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) { switch (opt) { + case 'n': + numeric_bdaddr = 1; + break; + case 'M': memf = optarg; break; @@ -265,7 +270,6 @@ l2caprawpr(kvm_t *kvmd, u_long addr) ng_btsocket_l2cap_raw_pcb_t pcb; struct socket so; int first = 1; - char bdaddr[32]; if (addr == 0) return; @@ -293,22 +297,13 @@ l2caprawpr(kvm_t *kvmd, u_long addr) "Local address"); } - if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) { - bdaddr[0] = '*'; - bdaddr[1] = 0; - } else - snprintf(bdaddr, sizeof(bdaddr), -"%02x:%02x:%02x:%02x:%02x:%02x", - pcb.src.b[5], pcb.src.b[4], pcb.src.b[3], - pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]); - fprintf(stdout, "%-8.8x %-8.8x %6d %6d %-17.17s\n", (int) pcb.so, (int) this, so.so_rcv.sb_cc, so.so_snd.sb_cc, - bdaddr); + bdaddrpr(&pcb.src, NULL, 0)); } } /* l2caprawpr */ @@ -331,7 +326,7 @@ l2cappr(kvm_t *kvmd, u_long addr) ng_btsocket_l2cap_pcb_t pcb; struct socket so; int first = 1; - char local[32], remote[32]; + char local[24], remote[24]; if (addr == 0) return; @@ -361,31 +356,14 @@ l2cappr(kvm_t *kvmd, u_long addr) "State"); } - if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) - snprintf(local, sizeof(local), "*/%d", pcb.psm); - else - snprintf(local, sizeof(local), -"%02x:%02x:%02x:%02x:%02x:%02x/%d", - pcb.src.b[5], pcb.src.b[4], pcb.src.b[3], - pcb.src.b[2], pcb.src.b[1], pcb.src.b[0], - pcb.psm); - - if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) { - remote[0] = '*'; - remote[1] = 0; - } else - snprintf(remote, sizeof(remote), -"%02x:%02x:%02x:%02x:%02x:%02x", - pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3], - pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]); - fprintf(stdout, -"%-8.8x %6d %6d %-23.23s %-17.17s %-5d %s\n", +"%-8.8x %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n", (int) this, so.so_rcv.sb_cc, so.so_snd.sb_cc, - local, - remote, + bdaddrpr(&pcb.src, local, sizeof(local)), + pcb.psm, + bdaddrpr(&pcb.dst, remote, sizeof(remote)), pcb.cid, (so.so_options & SO_ACCEPTCONN)? "LISTEN" : state2str(pcb.state)); @@ -402,7 +380,6 @@ l2caprtpr(kvm_t *kvmd, u_long addr) ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL; ng_btsocket_l2cap_rtentry_t rt; int first = 1; - char bdaddr[32]; if (addr == 0) return; @@ -426,19 +403,11 @@ l2caprtpr(kvm_t *kvmd, u_long addr) "BD_ADDR"); } - if (memcmp(&rt.src, NG_HCI_BDADDR_ANY, sizeof(rt.src)) == 0) { - bdaddr[0] = '-'; - bdaddr[1] = 0; - } else - snprintf(bdaddr, sizeof(bdaddr), -"%02x:%02x:%02x:%02x:%02x:%02x", rt.src.b[5], rt.src.b[4], rt.src.b[3], - rt.src.b[2], rt.src.b[1], rt.src.b[0]); - fprintf(stdout, "%-8.8x %-8.8x %-17.17s\n", (int) this, (int) rt.hook, - bdaddr); + bdaddrpr(&rt.src, NULL, 0)); } } /* l2caprtpr */ @@ -462,7 +431,7 @@ rfcommpr(kvm_t *kvmd, u_long addr) ng_btsocket_rfcomm_pcb_t pcb; struct socket so; int first = 1; - char local[32], remote[32]; + char local[24], remote[24]; if (addr == 0) return; @@ -493,31 +462,13 @@ rfcommpr(kvm_t *kvmd, u_long addr) "State"); } - if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) { - local[0] = '*'; - local[1] = 0; - } else - snprintf(local, sizeof(local), -"%02x:%02x:%02x:%02x:%02x:%02x", - pcb.src.b[5], pcb.src.b[4], pcb.src.b[3], - pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]); - - if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) { - remote[0] = '*'; - remote[1] = 0; - } else - snprintf(remote, sizeof(remote), -"%02x:%02x:%02x:%02x:%02x:%02x", - pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3], - pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]); - fprintf(stdout, "%-8.8x %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n", (int) this, so.so_rcv.sb_cc, so.so_snd.sb_cc, - local, - remote, + bdaddrpr(&pcb.src, local, sizeof(local)), + bdaddrpr(&pcb.dst, remote, sizeof(remote)), pcb.channel, pcb.dlci, (so.so_options & SO_ACCEPTCONN)? @@ -587,6 +538,40 @@ rfcommpr_s(kvm_t *kvmd, u_long addr) } /* rfcommpr_s */ /* + * Return BD_ADDR as string + */ + +static char * +bdaddrpr(bdaddr_p const ba, char *str, int len) +{ + static char buffer[MAXHOSTNAMELEN]; + struct hostent *he = NULL; + + if (str == NULL) { + str = buffer; + len = sizeof(buffer); + } + + if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { + str[0] = '*'; + str[1] = 0; + + return (str); + } + + if (!numeric_bdaddr && + (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { + strlcpy(str, he->h_name, len); + + return (str); + } + + bt_ntoa(ba, str); + + return (str); +} /* bdaddrpr */ + +/* * Open kvm */ @@ -652,7 +637,7 @@ kread(kvm_t *kvmd, u_long addr, char *buffer, int size) static void usage(void) { - fprintf(stdout, "Usage: btsockstat [-M core ] [-p proto] [-r]\n"); + fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n"); exit(255); } /* usage */ diff --git a/usr.bin/bluetooth/rfcomm_sppd/Makefile b/usr.bin/bluetooth/rfcomm_sppd/Makefile index 53d9f31..6e493e8 100644 --- a/usr.bin/bluetooth/rfcomm_sppd/Makefile +++ b/usr.bin/bluetooth/rfcomm_sppd/Makefile @@ -1,15 +1,12 @@ -# $Id: Makefile,v 1.2 2003/04/26 23:55:34 max Exp $ +# $Id: Makefile,v 1.7 2003/09/07 18:15:55 max Exp $ # $FreeBSD$ PROG= rfcomm_sppd -MAN1= rfcomm_sppd.1 - -DESTDIR= /usr/bin/ -MANDIR= ../share/man/man - +MAN= rfcomm_sppd.1 +SRCS= rfcomm_sppd.c rfcomm_sdp.c WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/ -SRCS= rfcomm_sppd.c +DPADD= ${LIBBLUETOOTH} ${LIBSDP} +LDADD= -lbluetooth -lsdp .include <bsd.prog.mk> diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c new file mode 100644 index 0000000..ed6b827 --- /dev/null +++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c @@ -0,0 +1,266 @@ +/* + * rfcomm_sdp.c + * + * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: rfcomm_sdp.c,v 1.1 2003/09/07 18:15:55 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <errno.h> +#include <sdp.h> +#include <stdio.h> + +#undef PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE +#define PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE 256 + +#undef PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE +#define PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE 12 + +static int rfcomm_proto_list_parse (u_int8_t const *start, u_int8_t const *end, + int *channel, int *error); + +/* + * Lookup RFCOMM channel number in the Protocol Descriptor List + */ + +#undef rfcomm_channel_lookup_exit +#define rfcomm_channel_lookup_exit(e) { \ + if (error != NULL) \ + *error = (e); \ + if (ss != NULL) { \ + sdp_close(ss); \ + ss = NULL; \ + } \ + return (((e) == 0)? 0 : -1); \ +} + +int +rfcomm_channel_lookup(bdaddr_t const *local, bdaddr_t const *remote, + int service, int *channel, int *error) +{ + u_int8_t buffer[PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE]; + void *ss = NULL; + u_int16_t serv = (u_int16_t) service; + u_int32_t attr = SDP_ATTR_RANGE( + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); + sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer }; + u_int32_t type, len; + + if (local == NULL) + local = NG_HCI_BDADDR_ANY; + if (remote == NULL || channel == NULL) + rfcomm_channel_lookup_exit(EINVAL); + + if ((ss = sdp_open(local, remote)) == NULL) + rfcomm_channel_lookup_exit(ENOMEM); + if (sdp_error(ss) != 0) + rfcomm_channel_lookup_exit(sdp_error(ss)); + + if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0) + rfcomm_channel_lookup_exit(sdp_error(ss)); + if (proto.flags != SDP_ATTR_OK) + rfcomm_channel_lookup_exit(ENOATTR); + + sdp_close(ss); + ss = NULL; + + /* + * If it is possible for more than one kind of protocol stack to be + * used to gain access to the service, the ProtocolDescriptorList + * takes the form of a data element alternative. We always use the + * first protocol stack. + * + * A minimal Protocol Descriptor List for RFCOMM based service would + * look like + * + * seq8 len8 - 2 bytes + * seq8 len8 - 2 bytes + * uuid16 value16 - 3 bytes L2CAP + * seq8 len8 - 2 bytes + * uuid16 value16 - 3 bytes RFCOMM + * uint8 value8 - 2 bytes RFCOMM param #1 + * ========= + * 14 bytes + * + * Lets not count first [seq8 len8] wrapper, so the minimal size of + * the Protocol Descriptor List (the data we are actually interested + * in) for RFCOMM based service would be 12 bytes. + */ + + if (proto.vlen < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE) + rfcomm_channel_lookup_exit(EINVAL); + + SDP_GET8(type, proto.value); + + if (type == SDP_DATA_ALT8) { + SDP_GET8(len, proto.value); + } else if (type == SDP_DATA_ALT16) { + SDP_GET16(len, proto.value); + } else if (type == SDP_DATA_ALT32) { + SDP_GET32(len, proto.value); + } else + len = 0; + + if (len > 0) + SDP_GET8(type, proto.value); + + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, proto.value); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, proto.value); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, proto.value); + break; + + default: + rfcomm_channel_lookup_exit(ENOATTR); + /* NOT REACHED */ + } + + if (len < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE) + rfcomm_channel_lookup_exit(EINVAL); + + return (rfcomm_proto_list_parse(proto.value, + buffer + proto.vlen, channel, error)); +} + +/* + * Parse protocol descriptor list + * + * The ProtocolDescriptorList attribute describes one or more protocol + * stacks that may be used to gain access to the service described by + * the service record. If the ProtocolDescriptorList describes a single + * stack, it takes the form of a data element sequence in which each + * element of the sequence is a protocol descriptor. + */ + +#undef rfcomm_proto_list_parse_exit +#define rfcomm_proto_list_parse_exit(e) { \ + if (error != NULL) \ + *error = (e); \ + return (((e) == 0)? 0 : -1); \ +} + +static int +rfcomm_proto_list_parse(u_int8_t const *start, u_int8_t const *end, + int *channel, int *error) +{ + int type, len, value; + + while (start < end) { + + /* + * Parse protocol descriptor + * + * A protocol descriptor identifies a communications protocol + * and provides protocol specific parameters. A protocol + * descriptor is represented as a data element sequence. The + * first data element in the sequence must be the UUID that + * identifies the protocol. Additional data elements optionally + * provide protocol specific information, such as the L2CAP + * protocol/service multiplexer (PSM) and the RFCOMM server + * channel number (CN). + */ + + /* We must have at least one byte (type) */ + if (end - start < 1) + rfcomm_proto_list_parse_exit(EINVAL) + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + rfcomm_proto_list_parse_exit(ENOATTR) + /* NOT REACHED */ + } + + /* We must have at least 3 bytes (type + UUID16) */ + if (end - start < 3) + rfcomm_proto_list_parse_exit(EINVAL); + + /* Get protocol UUID */ + SDP_GET8(type, start); len -= sizeof(u_int8_t); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value, start); len -= sizeof(u_int16_t); + if (value != SDP_UUID_PROTOCOL_RFCOMM) + goto next_protocol; + break; + + case SDP_DATA_UUID32: /* XXX FIXME can we have 32-bit UUID */ + case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */ + default: + rfcomm_proto_list_parse_exit(ENOATTR); + /* NOT REACHED */ + } + + /* + * First protocol specific parameter for RFCOMM procotol must + * be uint8 that represents RFCOMM channel number. So we must + * have at least two bytes. + */ + + if (end - start < 2) + rfcomm_proto_list_parse_exit(EINVAL); + + SDP_GET8(type, start); + if (type != SDP_DATA_UINT8) + rfcomm_proto_list_parse_exit(ENOATTR); + + SDP_GET8(*channel, start); + + rfcomm_proto_list_parse_exit(0); + /* NOT REACHED */ +next_protocol: + start += len; + } + + /* + * If we got here then it means we could not find RFCOMM protocol + * descriptor, but the reply format was actually valid. + */ + + rfcomm_proto_list_parse_exit(ENOATTR); +} + diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 index a2804b0..8d4a258 100644 --- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 +++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: rfcomm_sppd.1,v 1.1 2003/04/26 23:55:34 max Exp $ +.\" $Id: rfcomm_sppd.1,v 1.3 2003/09/07 18:15:55 max Exp $ .\" $FreeBSD$ .\" .Dd April 26, 2003 @@ -72,8 +72,12 @@ This required option specifies the remote BD_ADDR of the RFCOMM server. .It Fl b Detach from the controlling terminal, i.e., run in background. .It Fl c Ar channel -This required option specifies RFCOMM channel to connect to. -This channel must provide Serial Port service. +This option specifies RFCOMM channel to connect to. +The channel must provide Serial Port service. +If channel was not specified then +.Nm +utility will try to obtain RFCOMM channel via Service Discovery Protocol from +the server. .It Fl h Display usage message and exit. .It Fl t Ar tty @@ -101,9 +105,7 @@ slave pseudo terminals .Sh DIAGNOSTICS .Ex -std .Sh BUGS -The -.Nm -utility is not currently integrated with SDP (Service Discovery Protocol). +Please report if found. .Sh SEE ALSO .Xr ng_btsocket 4 , .Xr pty 4 , diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c index dbb2032..ee689be 100644 --- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c +++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c @@ -25,22 +25,18 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: rfcomm_sppd.c,v 1.2 2003/04/27 19:22:30 max Exp $ + * $Id: rfcomm_sppd.c,v 1.4 2003/09/07 18:15:55 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> #include <sys/stat.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> #include <fcntl.h> #include <grp.h> #include <limits.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> +#include <sdp.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -54,6 +50,10 @@ #define SPPD_BUFFER_SIZE 1024 #define max(a, b) (((a) > (b))? (a) : (b)) +int rfcomm_channel_lookup (bdaddr_t const *local, + bdaddr_t const *remote, + int service, int *channel, int *error); + static int sppd_ttys_open (char const *tty, int *amaster, int *aslave); static int sppd_read (int fd, char *buffer, int size); static int sppd_write (int fd, char *buffer, int size); @@ -79,21 +79,16 @@ main(int argc, char *argv[]) /* Parse command line options */ while ((n = getopt(argc, argv, "a:bc:t:h")) != -1) { switch (n) { - case 'a': { /* BDADDR */ - int a0, a1, a2, a3, a4, a5; - - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - usage(); - /* NOT REACHED */ - - addr.b[0] = a0 & 0xff; - addr.b[1] = a1 & 0xff; - addr.b[2] = a2 & 0xff; - addr.b[3] = a3 & 0xff; - addr.b[4] = a4 & 0xff; - addr.b[5] = a5 & 0xff; - } break; + case 'a': /* BDADDR */ + if (!bt_aton(optarg, &addr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&addr, he->h_addr, sizeof(addr)); + } + break; case 'c': /* RFCOMM channel */ channel = atoi(optarg); @@ -115,8 +110,7 @@ main(int argc, char *argv[]) } /* Check if we have everything we need */ - if (channel == 0 || tty == NULL || - memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) + if (tty == NULL || memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) usage(); /* NOT REACHED */ @@ -139,6 +133,14 @@ main(int argc, char *argv[]) if (sigaction(SIGCHLD, &sa, NULL) < 0) err(1, "Could not sigaction(SIGCHLD)"); + /* Check channel, if was not set then obtain it via SDP */ + if (channel == 0) + if (rfcomm_channel_lookup(NULL, &addr, + SDP_SERVICE_CLASS_SERIAL_PORT, &channel, &n) != 0) + errc(1, n, "Could not obtain RFCOMM channel"); + if (channel <= 0 || channel > 30) + errx(1, "Invalid RFCOMM channel number %d", channel); + /* Open TTYs */ if (sppd_ttys_open(tty, &amaster, &aslave) < 0) exit(1); @@ -374,7 +376,7 @@ usage(void) "Where options are:\n" \ "\t-a bdaddr BDADDR to connect to (required)\n" \ "\t-b Run in background\n" \ -"\t-c channel RFCOMM channel to connect to (required)\n" \ +"\t-c channel RFCOMM channel to connect to\n" \ "\t-t tty TTY name\n" \ "\t-h Display this message\n", SPPD_IDENT); diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 84fb878..ab24b69 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -184,6 +184,7 @@ SUBDIR+=elf2exe \ SUBDIR+=apm \ apmd \ asf \ + bluetooth \ btxld \ kgmon \ kgzip \ diff --git a/usr.sbin/bluetooth/Makefile b/usr.sbin/bluetooth/Makefile index 32e1806..916a1aea 100644 --- a/usr.sbin/bluetooth/Makefile +++ b/usr.sbin/bluetooth/Makefile @@ -1,14 +1,16 @@ -# $Id: Makefile,v 1.3 2003/04/01 02:06:47 max Exp $ +# $Id: Makefile,v 1.5 2003/09/08 02:28:35 max Exp $ # $FreeBSD$ -SUBDIR= \ - bt3cfw \ - bcmfw \ - hccontrol \ - hcsecd \ - hcseriald \ - l2control \ - l2ping \ - rfcomm_pppd +SUBDIR= \ + bcmfw \ + bt3cfw \ + hccontrol \ + hcsecd \ + hcseriald \ + l2control \ + l2ping \ + rfcomm_pppd \ + sdpcontrol + .include <bsd.subdir.mk> diff --git a/usr.sbin/bluetooth/Makefile.inc b/usr.sbin/bluetooth/Makefile.inc new file mode 100644 index 0000000..c0e05cf --- /dev/null +++ b/usr.sbin/bluetooth/Makefile.inc @@ -0,0 +1,4 @@ +# $FreeBSD$ + +.include "${.CURDIR}/../../Makefile.inc" + diff --git a/usr.sbin/bluetooth/bcmfw/Makefile b/usr.sbin/bluetooth/bcmfw/Makefile index fc2abca..e601a76 100644 --- a/usr.sbin/bluetooth/bcmfw/Makefile +++ b/usr.sbin/bluetooth/bcmfw/Makefile @@ -1,23 +1,9 @@ -# $Id: Makefile,v 1.2 2003/04/27 00:44:54 max Exp $ +# $Id: Makefile,v 1.6 2003/08/14 20:05:58 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= bcmfw -MAN8= bcmfw.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= bcmfw.8 SRCS= bcmfw.c +WARNS?= 2 -#FILESDIR= ../local/etc/ -#FILES+= BCM2033-FW.bin BCM2033-MD.hex -#CLEANFILES+= BCM2033-FW.bin BCM2033-MD.hex -# -#BCM2033-FW.bin: BCM2033-FW.bin.uue -# uudecode BCM2033-FW.bin.uue -# -#BCM2033-MD.hex: BCM2033-MD.hex.uue -# uudecode BCM2033-MD.hex.uue -# .include <bsd.prog.mk> -#.include <bsd.files.mk> diff --git a/usr.sbin/bluetooth/bcmfw/bcmfw.8 b/usr.sbin/bluetooth/bcmfw/bcmfw.8 index b961167..d5b984b 100644 --- a/usr.sbin/bluetooth/bcmfw/bcmfw.8 +++ b/usr.sbin/bluetooth/bcmfw/bcmfw.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: bcmfw.8,v 1.4 2003/04/28 17:10:56 max Exp $ +.\" $Id: bcmfw.8,v 1.7 2003/05/21 00:33:40 max Exp $ .\" $FreeBSD$ .\" .Dd March 31, 2003 @@ -51,6 +51,17 @@ The vendor ID should be 0x0a5c .Pq Dv USB_VENDOR_BROADCOM and the product ID should be 0x2033. .Pp +Due to copyright issues I will no longer provide mini-driver and firmware +files for the device. These files can be obtained from the Linux BlueZ BlueFW +package. +.Pp +Visit http://bluez.sourceforge.net/download/download.html for details. +.Pp +I am using the following files: +.Pp +.Dl "MD5 (BCM2033-MD.hex) = 5580317158d07fc4ace90af04f8e1c73" +.Dl "MD5 (BCM2033-FW.bin) = a3a0edfcb85029f4a5d0b1c9649b127d" +.Pp The options are as follows: .Bl -tag -width indent .It Fl f Ar firmware_file_name diff --git a/usr.sbin/bluetooth/bt3cfw/Makefile b/usr.sbin/bluetooth/bt3cfw/Makefile index 6310c0a..daa0f65 100644 --- a/usr.sbin/bluetooth/bt3cfw/Makefile +++ b/usr.sbin/bluetooth/bt3cfw/Makefile @@ -1,13 +1,10 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:06:53 max Exp $ +# $Id: Makefile,v 1.5 2003/08/14 20:06:00 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= bt3cfw -MAN8= bt3cfw.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= bt3cfw.8 SRCS= bt3cfw.c +WARNS?= 2 DPADD= ${LIBNETGRAPH} LDADD= -lnetgraph diff --git a/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 b/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 index 83a3fcb..74aa6d7 100644 --- a/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 +++ b/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: bt3cfw.8,v 1.3 2003/04/27 19:45:22 max Exp $ +.\" $Id: bt3cfw.8,v 1.4 2003/05/21 00:34:51 max Exp $ .\" $FreeBSD$ .\" .Dd November 11, 2002 diff --git a/usr.sbin/bluetooth/bt3cfw/bt3cfw.c b/usr.sbin/bluetooth/bt3cfw/bt3cfw.c index d0a32a8..02b40ed 100644 --- a/usr.sbin/bluetooth/bt3cfw/bt3cfw.c +++ b/usr.sbin/bluetooth/bt3cfw/bt3cfw.c @@ -25,20 +25,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bt3cfw.c,v 1.1 2002/11/24 20:22:37 max Exp $ + * $Id: bt3cfw.c,v 1.2 2003/05/21 22:40:29 max Exp $ * $FreeBSD$ */ #include <sys/types.h> #include <errno.h> #include <netgraph.h> +#include <netgraph/bluetooth/include/ng_bt3c.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> -#include "ng_bt3c.h" #define BT3CFW_IDENT "bt3cfw" #define BT3CFW_MAX_FIRMWARE_SIZE 0xffff diff --git a/usr.sbin/bluetooth/hccontrol/Makefile b/usr.sbin/bluetooth/hccontrol/Makefile index 5b68cd8..592247e 100644 --- a/usr.sbin/bluetooth/hccontrol/Makefile +++ b/usr.sbin/bluetooth/hccontrol/Makefile @@ -1,14 +1,14 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:39 max Exp $ +# $Id: Makefile,v 1.7 2003/08/14 20:06:17 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= hccontrol -MAN8= hccontrol.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hccontrol.8 SRCS= send_recv.c link_policy.c link_control.c \ host_controller_baseband.c info.c status.c node.c hccontrol.c \ util.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.8 b/usr.sbin/bluetooth/hccontrol/hccontrol.8 index e55635c..559b5f6 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.8 +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hccontrol.8,v 1.3 2003/04/27 19:45:23 max Exp $ +.\" $Id: hccontrol.8,v 1.6 2003/08/06 21:26:38 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 @@ -33,7 +33,7 @@ .Nd HCI configuration utility .Sh SYNOPSIS .Nm -.Op Fl h +.Op Fl hN .Fl n Ar HCI_node_name .Ar command .Op Ar parameters ... @@ -53,6 +53,11 @@ The options are as follows: .Bl -tag -width indent .It Fl h Display usage message and exit. +.It Fl N +Show Bluetooth addresses as numbers. +Normally +.Nm +attempts to resolve Bluetooth addresses, and display them symbolically. .It Fl n Ar HCI_node_name Connect to the specified HCI Netgraph node. .It Ar command @@ -118,6 +123,10 @@ are: .It Cm Write_SCO_Flow_Control_Enable .It Cm Read_Link_Supervision_Timeout .It Cm Write_Link_Supervision_Timeout +.It Cm Read_Page_Scan_Period_Mode +.It Cm Write_Page_Scan_Period_Mode +.It Cm Read_Page_Scan_Mode +.It Cm Write_Page_Scan_Mode .It Cm Read_Local_Version_Information .It Cm Read_Local_Supported_Features .It Cm Read_Buffer_Size diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.c b/usr.sbin/bluetooth/hccontrol/hccontrol.c index fafbf7b..0bf5583 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.c +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.c @@ -25,20 +25,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hccontrol.c,v 1.2 2003/04/27 19:45:24 max Exp $ + * $Id: hccontrol.c,v 1.5 2003/09/05 00:38:24 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> +#include <bluetooth.h> #include <sys/sysctl.h> #include <assert.h> -#include <bitstring.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -54,6 +49,7 @@ static void usage (void); /* Globals */ int verbose = 0; int timeout; +int numeric_bdaddr = 0; /* Main */ int @@ -63,12 +59,16 @@ main(int argc, char *argv[]) int n; /* Process command line arguments */ - while ((n = getopt(argc, argv, "n:vh")) != -1) { + while ((n = getopt(argc, argv, "n:Nvh")) != -1) { switch (n) { case 'n': node = optarg; break; + case 'N': + numeric_bdaddr = 1; + break; + case 'v': verbose = 1; break; @@ -254,7 +254,7 @@ find_hci_command(char const *command, struct hci_command *category) return (NULL); } /* find_hci_command */ -/* Try to find command in specified category */ +/* Print commands in specified category */ static void print_hci_command(struct hci_command *category) { diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.h b/usr.sbin/bluetooth/hccontrol/hccontrol.h index d578fea..001ca71 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.h +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hccontrol.h,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: hccontrol.h,v 1.2 2003/05/19 17:29:29 max Exp $ * $FreeBSD$ */ @@ -70,6 +70,7 @@ char const * const hci_features2str (u_int8_t *, char *, int); char const * const hci_cc2str (int); char const * const hci_con_state2str (int); char const * const hci_status2str (int); +char const * const hci_bdaddr2str (bdaddr_t const *); #endif /* _HCCONTROL_H_ */ diff --git a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c index 5854b00..fd4d60e 100644 --- a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c +++ b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: host_controller_baseband.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: host_controller_baseband.c,v 1.4 2003/08/18 19:19:53 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -189,7 +187,7 @@ hci_read_stored_link_key(int s, int argc, char **argv) } ep; } __attribute__ ((packed)) event; - int n,a0,a1,a2,a3,a4,a5; + int n, n1; /* Send command */ memset(&cmd, 0, sizeof(cmd)); @@ -201,16 +199,14 @@ hci_read_stored_link_key(int s, int argc, char **argv) switch (argc) { case 1: /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", &a5, &a4, &a3, &a2, - &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cmd.cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cmd.cp.bdaddr.b[0] = (a0 & 0xff); - cmd.cp.bdaddr.b[1] = (a1 & 0xff); - cmd.cp.bdaddr.b[2] = (a2 & 0xff); - cmd.cp.bdaddr.b[3] = (a3 & 0xff); - cmd.cp.bdaddr.b[4] = (a4 & 0xff); - cmd.cp.bdaddr.b[5] = (a5 & 0xff); + memcpy(&cmd.cp.bdaddr, he->h_addr, sizeof(cmd.cp.bdaddr)); + } break; default: @@ -269,13 +265,11 @@ again: k = (struct _key *)(event.ep.b + sizeof(event.ep.key)); for (n = 0; n < event.ep.key.num_keys; n++) { - fprintf(stdout, "\t%d: %02x:%02x:%02x:%02x:%02x:%02x ", - n + 1, - k->bdaddr.b[5], k->bdaddr.b[4], k->bdaddr.b[3], - k->bdaddr.b[2], k->bdaddr.b[1], k->bdaddr.b[0]); + fprintf(stdout, "\t%d: %s ", + n + 1, hci_bdaddr2str(&k->bdaddr)); - for (a0 = 0; a0 < sizeof(k->key); a0++) - fprintf(stdout, "%02x", k->key[a0]); + for (n1 = 0; n1 < sizeof(k->key); n1++) + fprintf(stdout, "%02x", k->key[n1]); fprintf(stdout, "\n"); k ++; @@ -302,7 +296,7 @@ hci_write_stored_link_key(int s, int argc, char **argv) u_int8_t key[NG_HCI_KEY_SIZE]; } cp; ng_hci_write_stored_link_key_rp rp; - int32_t n, a0, a1, a2, a3, a4, a5; + int32_t n; memset(&cp, 0, sizeof(cp)); @@ -311,16 +305,14 @@ hci_write_stored_link_key(int s, int argc, char **argv) cp.p.num_keys_write = 1; /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; - cp.bdaddr.b[0] = (a0 & 0xff); - cp.bdaddr.b[1] = (a1 & 0xff); - cp.bdaddr.b[2] = (a2 & 0xff); - cp.bdaddr.b[3] = (a3 & 0xff); - cp.bdaddr.b[4] = (a4 & 0xff); - cp.bdaddr.b[5] = (a5 & 0xff); + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); + + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } /* parse key */ if (hci_hexstring2array(argv[1], cp.key, sizeof(cp.key)) < 0) @@ -357,23 +349,21 @@ hci_delete_stored_link_key(int s, int argc, char **argv) { ng_hci_delete_stored_link_key_cp cp; ng_hci_delete_stored_link_key_rp rp; - int32_t n, a0, a1, a2, a3, a4, a5; + int32_t n; memset(&cp, 0, sizeof(cp)); switch (argc) { case 1: /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (a0 & 0xff); - cp.bdaddr.b[1] = (a1 & 0xff); - cp.bdaddr.b[2] = (a2 & 0xff); - cp.bdaddr.b[3] = (a3 & 0xff); - cp.bdaddr.b[4] = (a4 & 0xff); - cp.bdaddr.b[5] = (a5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -1372,6 +1362,131 @@ hci_write_link_supervision_timeout(int s, int argc, char **argv) return (OK); } /* hci_write_link_supervision_timeout */ +/* Send Read_Page_Scan_Period_Mode command to the unit */ +static int +hci_read_page_scan_period_mode(int s, int argc, char **argv) +{ + ng_hci_read_page_scan_period_rp rp; + int n; + + n = sizeof(rp); + if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_READ_PAGE_SCAN_PERIOD), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + fprintf(stdout, "Page scan period mode: %#02x\n", + rp.page_scan_period_mode); + + return (OK); +} /* hci_read_page_scan_period_mode */ + +/* Send Write_Page_Scan_Period_Mode command to the unit */ +static int +hci_write_page_scan_period_mode(int s, int argc, char **argv) +{ + ng_hci_write_page_scan_period_cp cp; + ng_hci_write_page_scan_period_rp rp; + int n; + + /* parse command arguments */ + switch (argc) { + case 1: + if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 2) + return (USAGE); + + cp.page_scan_period_mode = (n & 0xff); + break; + + default: + return (USAGE); + } + + /* send command */ + n = sizeof(rp); + if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD), + (char const *) &cp, sizeof(cp), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + return (OK); +} /* hci_write_page_scan_period_mode */ + +/* Send Read_Page_Scan_Mode command to the unit */ +static int +hci_read_page_scan_mode(int s, int argc, char **argv) +{ + ng_hci_read_page_scan_rp rp; + int n; + + n = sizeof(rp); + if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_READ_PAGE_SCAN), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + fprintf(stdout, "Page scan mode: %#02x\n", rp.page_scan_mode); + + return (OK); +} /* hci_read_page_scan_mode */ + +/* Send Write_Page_Scan_Mode command to the unit */ +static int +hci_write_page_scan_mode(int s, int argc, char **argv) +{ + ng_hci_write_page_scan_cp cp; + ng_hci_write_page_scan_rp rp; + int n; + + /* parse command arguments */ + switch (argc) { + case 1: + if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 3) + return (USAGE); + + cp.page_scan_mode = (n & 0xff); + break; + + default: + return (USAGE); + } + + /* send command */ + n = sizeof(rp); + if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_WRITE_PAGE_SCAN), + (char const *) &cp, sizeof(cp), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + return (OK); +} /* hci_write_page_scan_mode */ + struct hci_command host_controller_baseband_commands[] = { { "reset", @@ -1708,6 +1823,55 @@ struct hci_command host_controller_baseband_commands[] = { "\t<timeout> - dddd; timeout measured in number of baseband slots\n", &hci_write_link_supervision_timeout }, +{ +"read_page_scan_period_mode", +"\nThis command is used to read the mandatory Page_Scan_Period_Mode of the\n" \ +"local Bluetooth device. Every time an inquiry response message is sent, the\n"\ +"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\ +"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \ +"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \ +"following page scans.", +&hci_read_page_scan_period_mode +}, +{ +"write_page_scan_period_mode <page_scan_period_mode>", +"\nThis command is used to write the mandatory Page_Scan_Period_Mode of the\n" \ +"local Bluetooth device. Every time an inquiry response message is sent, the\n"\ +"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\ +"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \ +"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \ +"following page scans.\n\n" \ +"\t<page_scan_period_mode> - dd; page scan period mode:\n" \ +"\t0x00 - P0 (Default)\n" \ +"\t0x01 - P1\n" \ +"\t0x02 - P2", +&hci_write_page_scan_period_mode +}, +{ +"read_page_scan_mode", +"\nThis command is used to read the default page scan mode of the local\n" \ +"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\ +"that is used for the default page scan. Currently one mandatory page scan\n"\ +"mode and three optional page scan modes are defined. Following an inquiry\n" \ +"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \ +"mandatory page scan mode must be applied.", +&hci_read_page_scan_mode +}, +{ +"write_page_scan_mode <page_scan_mode>", +"\nThis command is used to write the default page scan mode of the local\n" \ +"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\ +"that is used for the default page scan. Currently, one mandatory page scan\n"\ +"mode and three optional page scan modes are defined. Following an inquiry\n"\ +"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \ +"mandatory page scan mode must be applied.\n\n" \ +"\t<page_scan_mode> - dd; page scan mode:\n" \ +"\t0x00 - Mandatory Page Scan Mode (Default)\n" \ +"\t0x01 - Optional Page Scan Mode I\n" \ +"\t0x02 - Optional Page Scan Mode II\n" \ +"\t0x03 - Optional Page Scan Mode III", +&hci_write_page_scan_mode +}, { NULL, } }; diff --git a/usr.sbin/bluetooth/hccontrol/info.c b/usr.sbin/bluetooth/hccontrol/info.c index 1a8649f..12b685b 100644 --- a/usr.sbin/bluetooth/hccontrol/info.c +++ b/usr.sbin/bluetooth/hccontrol/info.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: info.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: info.c,v 1.3 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -173,9 +171,7 @@ hci_read_bd_addr(int s, int argc, char **argv) return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - rp.bdaddr.b[5], rp.bdaddr.b[4], rp.bdaddr.b[3], - rp.bdaddr.b[2], rp.bdaddr.b[1], rp.bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&rp.bdaddr, NULL)); return (OK); } /* hci_read_bd_addr */ diff --git a/usr.sbin/bluetooth/hccontrol/link_control.c b/usr.sbin/bluetooth/hccontrol/link_control.c index 2f3b4b2..0b8ec84 100644 --- a/usr.sbin/bluetooth/hccontrol/link_control.c +++ b/usr.sbin/bluetooth/hccontrol/link_control.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_control.c,v 1.2 2003/03/15 03:07:39 max Exp $ + * $Id: link_control.c,v 1.4 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -158,9 +156,7 @@ hci_inquiry_response(int n, u_int8_t **b) } *ir = (struct inquiry_response *)(*b); fprintf(stdout, "Inquiry result #%d\n", n); - fprintf(stdout, "\tBD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ir->bdaddr.b[5], ir->bdaddr.b[4], ir->bdaddr.b[3], - ir->bdaddr.b[2], ir->bdaddr.b[1], ir->bdaddr.b[0]); + fprintf(stdout, "\tBD_ADDR: %s\n", hci_bdaddr2str(&ir->bdaddr)); fprintf(stdout, "\tPage Scan Rep. Mode: %#02x\n", ir->page_scan_rep_mode); fprintf(stdout, "\tPage Scan Period Mode: %#02x\n", @@ -179,7 +175,7 @@ hci_inquiry_response(int n, u_int8_t **b) static int hci_create_connection(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_create_con_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -241,16 +237,14 @@ hci_create_connection(int s, int argc, char **argv) case 1: /* BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (n0 & 0xff); - cp.bdaddr.b[1] = (n1 & 0xff); - cp.bdaddr.b[2] = (n2 & 0xff); - cp.bdaddr.b[3] = (n3 & 0xff); - cp.bdaddr.b[4] = (n4 & 0xff); - cp.bdaddr.b[5] = (n5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -286,9 +280,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", @@ -443,9 +435,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", @@ -531,7 +521,7 @@ again: static int hci_remote_name_request(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_remote_name_req_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -566,16 +556,14 @@ hci_remote_name_request(int s, int argc, char **argv) case 1: /* BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (n0 & 0xff); - cp.bdaddr.b[1] = (n1 & 0xff); - cp.bdaddr.b[2] = (n2 & 0xff); - cp.bdaddr.b[3] = (n3 & 0xff); - cp.bdaddr.b[4] = (n4 & 0xff); - cp.bdaddr.b[5] = (n5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -612,9 +600,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Name: %s\n", ep->name); } else goto again; diff --git a/usr.sbin/bluetooth/hccontrol/link_policy.c b/usr.sbin/bluetooth/hccontrol/link_policy.c index 0a40f56..387d601 100644 --- a/usr.sbin/bluetooth/hccontrol/link_policy.c +++ b/usr.sbin/bluetooth/hccontrol/link_policy.c @@ -25,15 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_policy.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: link_policy.c,v 1.3 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> +#include <string.h> #include "hccontrol.h" /* Send Role Discovery to the unit */ @@ -84,7 +83,7 @@ hci_role_discovery(int s, int argc, char **argv) static int hci_switch_role(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_switch_role_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -93,16 +92,14 @@ hci_switch_role(int s, int argc, char **argv) switch (argc) { case 2: /* bdaddr */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = n0 & 0xff; - cp.bdaddr.b[1] = n1 & 0xff; - cp.bdaddr.b[2] = n2 & 0xff; - cp.bdaddr.b[3] = n3 & 0xff; - cp.bdaddr.b[4] = n4 & 0xff; - cp.bdaddr.b[5] = n5 & 0xff; + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } /* role */ if (sscanf(argv[1], "%d", &n0) != 1) @@ -144,9 +141,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Role: %s [%#x]\n", (ep->role == NG_HCI_ROLE_MASTER)? "Master" : "Slave", ep->role); diff --git a/usr.sbin/bluetooth/hccontrol/node.c b/usr.sbin/bluetooth/hccontrol/node.c index 4771027..863d516 100644 --- a/usr.sbin/bluetooth/hccontrol/node.c +++ b/usr.sbin/bluetooth/hccontrol/node.c @@ -25,18 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: node.c,v 1.4 2003/03/23 21:28:17 max Exp $ + * $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> #include <sys/ioctl.h> -#include <bitstring.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -142,9 +137,7 @@ hci_read_node_bd_addr(int s, int argc, char **argv) if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0) return (ERROR); - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - r.bdaddr.b[5], r.bdaddr.b[4], r.bdaddr.b[3], - r.bdaddr.b[2], r.bdaddr.b[1], r.bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL)); return (OK); } /* hci_read_node_bd_addr */ @@ -243,14 +236,12 @@ hci_read_neighbor_cache(int s, int argc, char **argv) for (n = 0; n < r.num_entries; n++) { fprintf(stdout, -"%02x:%02x:%02x:%02x:%02x:%02x " \ +"%-17.17s " \ "%02x %02x %02x %02x %02x %02x %02x %02x " \ "%#12x " \ "%#9x " \ "%#9x\n", - r.entries[n].bdaddr.b[5], r.entries[n].bdaddr.b[4], - r.entries[n].bdaddr.b[3], r.entries[n].bdaddr.b[2], - r.entries[n].bdaddr.b[1], r.entries[n].bdaddr.b[0], + hci_bdaddr2str(&r.entries[n].bdaddr), r.entries[n].features[0], r.entries[n].features[1], r.entries[n].features[2], r.entries[n].features[3], r.entries[n].features[4], r.entries[n].features[5], @@ -297,7 +288,7 @@ hci_read_connection_list(int s, int argc, char **argv) for (n = 0; n < r.num_connections; n++) { fprintf(stdout, -"%02x:%02x:%02x:%02x:%02x:%02x " \ +"%-17.17s " \ "%6d " \ "%4.4s " \ "%4d " \ @@ -306,12 +297,7 @@ hci_read_connection_list(int s, int argc, char **argv) "%7d " \ "%5d " \ "%s\n", - r.connections[n].bdaddr.b[5], - r.connections[n].bdaddr.b[4], - r.connections[n].bdaddr.b[3], - r.connections[n].bdaddr.b[2], - r.connections[n].bdaddr.b[1], - r.connections[n].bdaddr.b[0], + hci_bdaddr2str(&r.connections[n].bdaddr), r.connections[n].con_handle, (r.connections[n].link_type == NG_HCI_LINK_ACL)? "ACL" : "SCO", diff --git a/usr.sbin/bluetooth/hccontrol/send_recv.c b/usr.sbin/bluetooth/hccontrol/send_recv.c index 43a2e2a..fc9c549 100644 --- a/usr.sbin/bluetooth/hccontrol/send_recv.c +++ b/usr.sbin/bluetooth/hccontrol/send_recv.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: send_recv.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: send_recv.c,v 1.2 2003/05/21 22:40:30 max Exp $ * $FreeBSD$ */ @@ -35,7 +35,7 @@ #include <sys/endian.h> #include <assert.h> #include <errno.h> -#include <ng_hci.h> +#include <netgraph/bluetooth/include/ng_hci.h> #include <string.h> #include <unistd.h> #include "hccontrol.h" diff --git a/usr.sbin/bluetooth/hccontrol/status.c b/usr.sbin/bluetooth/hccontrol/status.c index fdbf61f..86dd8c9 100644 --- a/usr.sbin/bluetooth/hccontrol/status.c +++ b/usr.sbin/bluetooth/hccontrol/status.c @@ -25,14 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: status.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: status.c,v 1.2 2003/05/21 22:40:30 max Exp $ * $FreeBSD$ */ #include <sys/types.h> #include <sys/endian.h> #include <errno.h> -#include <ng_hci.h> +#include <netgraph/bluetooth/include/ng_hci.h> #include <stdio.h> #include "hccontrol.h" diff --git a/usr.sbin/bluetooth/hccontrol/util.c b/usr.sbin/bluetooth/hccontrol/util.c index 7abe4d4..53b110a 100644 --- a/usr.sbin/bluetooth/hccontrol/util.c +++ b/usr.sbin/bluetooth/hccontrol/util.c @@ -25,11 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: util.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: util.c,v 1.2 2003/05/19 17:29:29 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> +#include <sys/param.h> +#include <bluetooth.h> +#include <stdio.h> #include <string.h> #define SIZE(x) (sizeof((x))/sizeof((x)[0])) @@ -348,3 +350,29 @@ hci_status2str(int status) return (status >= SIZE(t)? "Unknown error" : t[status]); } /* hci_status2str */ +char const * const +hci_bdaddr2str(bdaddr_t const *ba) +{ + extern int numeric_bdaddr; + static char buffer[MAXHOSTNAMELEN]; + struct hostent *he = NULL; + + if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { + buffer[0] = '*'; + buffer[1] = 0; + + return (buffer); + } + + if (!numeric_bdaddr && + (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { + strlcpy(buffer, he->h_name, sizeof(buffer)); + + return (buffer); + } + + bt_ntoa(ba, buffer); + + return (buffer); +} /* hci_bdaddr2str */ + diff --git a/usr.sbin/bluetooth/hcsecd/Makefile b/usr.sbin/bluetooth/hcsecd/Makefile index b39ac22..d9a106f 100644 --- a/usr.sbin/bluetooth/hcsecd/Makefile +++ b/usr.sbin/bluetooth/hcsecd/Makefile @@ -1,12 +1,13 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:42 max Exp $ +# $Id: Makefile,v 1.8 2003/08/14 20:06:20 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= hcsecd -MAN8= hcsecd.8 -WARNS?= 1 -CFLAGS+= -g -I${.CURDIR} -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hcsecd.8 hcsecd.conf.5 SRCS= hcsecd.c lexer.l parser.y +WARNS?= 1 +CFLAGS+= -I${.CURDIR} + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.8 b/usr.sbin/bluetooth/hcsecd/hcsecd.8 index 71ffcb8..1a3bb09 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.8 +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hcsecd.8,v 1.3 2003/04/27 19:45:32 max Exp $ +.\" $Id: hcsecd.8,v 1.8 2003/09/08 18:54:20 max Exp $ .\" $FreeBSD$ .\" .Dd November 16, 2002 @@ -38,22 +38,28 @@ .Sh DESCRIPTION The .Nm -daemon controls link keys and PIN code for Bluetooth devices. +daemon controls link keys and PIN codes for Bluetooth devices. It opens raw HCI socket and listens for the -.Dv Link_Key_Request -and +.Dv Link_Key_Request , .Dv PIN_Code_Request +and +.Dv Link_Key_Notification HCI events. -Once appropriate HCI event has been received, the daemon will +.Pp +Once +.Dv Link_Key_Request +or +.Dv PIN_Code_Request +HCI event is received, the daemon will scan configuration file for matching entry. -The remove device BD_ADDR is used as a key. +The remote device BD_ADDR is used as a key. If no matching entry was found, the default entry will be used. -If no default entry was found then it is assumed that no link key and no PIN code -exist. +If no default entry was found then it is assumed that no link key and no +PIN code exists. For any given entry, link key takes precedence over PIN code. If link key was not specified, it means device must generate link key from PIN code. -If entry was found and has the link key (or PIN code) then the +If entry was found and the link key (or PIN code) exists then the .Dv Link_Key_Request_Reply (or .Dv PIN_Code_Request_Reply ) @@ -66,12 +72,28 @@ command will be sent back to the device. .Pp The .Nm -daemon currently does not handle HCI +daemon also handles HCI .Dv Link_Key_Notification -event and does not cache link keys created from the PIN codes. -It means that the link key only exists while connection is opened. -After the connection has been terminated, the user will have to enter PIN code -again. +event and caches link keys created from the PIN codes in the memory. +To preserve link keys between restarts the +.Nm +daemon dumps link keys for all entries in the +.Pa /var/db/hcsecd.keys +link keys file. +If exists, the link keys file gets processed by +.Nm +daemon after it processes its main configuration file. +The link keys file gets written every time +.Nm +daemon is gracefully shutdown. +It is possible to force +.Nm +daemon to re-read its main configuration file and dump link keys file by sending +.Dv HUP +signal to the +.Nm +process. +User is not expected to modify link keys file by hand. .Pp The command line options are as follows: .Bl -tag -width indent @@ -80,7 +102,7 @@ Do not detach from the controlling terminal. .It Fl f Ar configfile Specify name of the configuration file. The default is -.Pa /usr/local/etc/hcsecd.conf . +.Pa /etc/bluetooth/hcsecd.conf . .It Fl h Display usage message and exit. .El @@ -91,15 +113,15 @@ Everything is based on remote device BD_ADDR. Also might implement interface for external helpers to obtain link keys and PIN codes. .Sh FILES -.Bl -tag -width ".Pa /usr/local/etc/hcsecd.conf" -compact -.It Pa /usr/local/etc/hcsecd.conf -.It Pa /var/run/hcsecd.pid +.Bl -tag -width ".Pa /etc/bluetooth/hcsecd.conf" -compact +.It Pa /etc/bluetooth/hcsecd.conf +.It Pa /var/db/hcsecd.pid +.It Pa /var/run/hcsecd.keys .El .Sh SEE ALSO -.Xr netgraph 3 , -.Xr netgraph 4 , .Xr ng_btsocket 4 , .Xr ng_hci 4 , +.Xr hcsecd.conf 5 , .Xr hccontrol 8 , .Xr hcseriald 8 .Sh AUTHORS diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.c b/usr.sbin/bluetooth/hcsecd/hcsecd.c index 0f72eb7..ac7eacb 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.c +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.c @@ -25,20 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcsecd.c,v 1.3 2003/04/27 19:45:32 max Exp $ + * $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> -#include <sys/socket.h> #include <sys/queue.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -48,10 +42,6 @@ #include <unistd.h> #include "hcsecd.h" -#define HCSECD_BUFFER_SIZE 512 -#define HCSECD_IDENT "hcsecd" -#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" - static int done = 0; static int process_pin_code_request_event @@ -62,6 +52,10 @@ static int send_pin_code_reply (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin); static int send_link_key_reply (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, u_int8_t *key); +static int process_link_key_notification_event + (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep); +static void sighup + (int s); static void sigint (int s); static void usage @@ -115,7 +109,7 @@ main(int argc, char *argv[]) err(1, "Could not sigaction(SIGINT)"); memset(&sa, 0, sizeof(sa)); - sa.sa_handler = read_config_file; + sa.sa_handler = sighup; if (sigaction(SIGHUP, &sa, NULL) < 0) err(1, "Could not sigaction(SIGHUP)"); @@ -127,6 +121,7 @@ main(int argc, char *argv[]) memset(&filter, 0, sizeof(filter)); bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1); bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1); + bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER, (void * const) &filter, sizeof(filter)) < 0) @@ -138,7 +133,8 @@ main(int argc, char *argv[]) openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON); - read_config_file(0); + read_config_file(); + read_keys_file(); if (detach) { FILE *pid = NULL; @@ -184,6 +180,11 @@ main(int argc, char *argv[]) (bdaddr_p)(event + 1)); break; + case NG_HCI_EVENT_LINK_KEY_NOTIFICATION: + process_link_key_notification_event(sock, &addr, + (ng_hci_link_key_notification_ep *)(event + 1)); + break; + default: syslog(LOG_ERR, "Received unexpected HCI event, " \ "event=%#x", event->event); @@ -196,6 +197,7 @@ main(int argc, char *argv[]) syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)", HCSECD_PIDFILE, strerror(errno), errno); + dump_keys_file(); clean_config(); closelog(); close(sock); @@ -211,27 +213,21 @@ process_pin_code_request_event(int sock, struct sockaddr_hci *addr, link_key_p key = NULL; syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "PIN code %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', PIN code %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->pin != NULL)? "exists" : "doesn't exist"); return (send_pin_code_reply(sock, addr, bdaddr, key->pin)); } - syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_pin_code_reply(sock, addr, bdaddr, NULL)); } @@ -244,27 +240,21 @@ process_link_key_request_event(int sock, struct sockaddr_hci *addr, link_key_p key = NULL; syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "link key %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->key != NULL)? "exists" : "doesn't exist"); return (send_link_key_reply(sock, addr, bdaddr, key->key)); } - syslog(LOG_DEBUG, "Could not find link key for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_link_key_reply(sock, addr, bdaddr, NULL)); } @@ -295,10 +285,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr, cp->pin_size = strlen(cp->pin); syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_pin_code_neg_rep_cp *cp = NULL; @@ -310,10 +298,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -323,10 +309,8 @@ again: goto again; syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -359,10 +343,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->key, key, sizeof(cp->key)); syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_link_key_neg_rep_cp *cp = NULL; @@ -374,10 +356,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -387,10 +367,8 @@ again: goto again; syslog(LOG_ERR, "Could not send link key reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -398,7 +376,53 @@ again: return (0); } -/* Signal handler */ +/* Process Link_Key_Notification event */ +static int +process_link_key_notification_event(int sock, struct sockaddr_hci *addr, + ng_hci_link_key_notification_ep *ep) +{ + link_key_p key = NULL; + + syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \ + "remote bdaddr %s", addr->hci_node, + bt_ntoa(&ep->bdaddr, NULL)); + + if ((key = get_key(&ep->bdaddr, 1)) == NULL) { + syslog(LOG_ERR, "Could not find entry for remote bdaddr %s", + bt_ntoa(&ep->bdaddr, NULL)); + return (-1); + } + + syslog(LOG_DEBUG, "Updating link key for the entry, " \ + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name", + (key->key != NULL)? "exists" : "doesn't exist"); + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE); + + return (0); +} + +/* Signal handlers */ +static void +sighup(int s) +{ + syslog(LOG_DEBUG, "Got SIGHUP (%d)", s); + + dump_keys_file(); + read_config_file(); + read_keys_file(); +} + static void sigint(int s) { diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 new file mode 100644 index 0000000..d27025f --- /dev/null +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 @@ -0,0 +1,129 @@ +.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: hcsecd.conf.5,v 1.1 2003/05/26 22:49:23 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 26, 2003 +.Dt HCSECD.CONF 5 +.Os +.Sh NAME +.Nm hcsecd.conf +.Nd +.Xr hcsecd 8 +configuration file +.Sh DESCRIPTION +The +.Nm +file is the configuration file for the +.Xr hcsecd 8 +Bluetooth link keys/PIN codes management daemon. +.Pp +The +.Nm +file is a free-form ASCII text file. +It is parsed by the recursive-descent parser built into +.Xr hcsecd 8 . +The file may contain extra tabs and newlines for formatting purposes. +Keywords in the file are case-sensitive. +Comments may be placed anywhere within the file (except within quotes). +Comments begin with the +.Dq # +character and end at the end of the line. +.Sh FILE FORMAT +The +.Nm +file consists of a list of +.Cm device +entries. +Each +.Cm device +entry defines a link key or PIN code for a remote Bluetooth device. +Each remote Bluetooth device is identified by its unique BD_ADDR. +.Pp +The +.Cm device +entry +.Pp +.Cm device +{ +.Cm option Ar argument ; +.Oo +.Cm option Ar argument ; +.Oc +} +.Pp +The following section describes all supported options and arguments +.Bl -tag -width indent +.It Cm bdaddr Ar BD_ADDR +Specify remote device BD_ADDR for the entry. +.It Cm name Ar device_name +Specify user friendly name for the entry. +Name is a string in a straight double quotes. +.It Cm key Ar link_key +Specify link key for the entry. +Link key is hexadecimal string upto 32 characters in length starting with +.Dq 0x . +.It Cm key nokey +Specify no link key for the entry. +.It Cm pin Ar PIN_code +Specify PIN code for the entry. +PIN code is a string upto 16 characters in length in a straight double quotes. +.It Cm pin nopin +Specify no PIN code for the entry. +.El +.Sh EXAMPLES +A sample +.Nm +file +.Bd -literal +# Default entry is applied if no better match found +# It MUST have 00:00:00:00:00:00 as bdaddr +device { + bdaddr 00:00:00:00:00:00; + name "Default entry"; + key nokey; + pin nopin; +} + +# Ericsson T68 phone +device { + bdaddr 00:80:37:5e:4d:d4; + name "Ericsson T68 phone"; + key nokey; + pin "0000"; # PIN code +} + +# Dummy device +device { + bdaddr 00:11:22:33:44:55; + name "Dummy"; + key 0x00112233445566778899aabbccddeeff; # 16 bytes key + pin nopin; +} +.Ed +.Sh SEE ALSO +.Xr hcsecd 8 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.h b/usr.sbin/bluetooth/hcsecd/hcsecd.h index 65820ed..4f53e99 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.h +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.h @@ -25,13 +25,18 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcsecd.h,v 1.1 2002/11/24 20:22:39 max Exp $ + * $Id: hcsecd.h,v 1.3 2003/09/08 18:54:21 max Exp $ * $FreeBSD$ */ #ifndef _HCSECD_H_ #define _HCSECD_H_ 1 +#define HCSECD_BUFFER_SIZE 512 +#define HCSECD_IDENT "hcsecd" +#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" +#define HCSECD_KEYSFILE "/var/db/" HCSECD_IDENT ".keys" + struct link_key { bdaddr_t bdaddr; /* remote device BDADDR */ @@ -49,9 +54,12 @@ extern char *config_file; void dump_config (void); #endif -void read_config_file(int s); +void read_config_file(void); void clean_config (void); link_key_p get_key (bdaddr_p bdaddr, int exact_match); +int read_keys_file (void); +int dump_keys_file (void); + #endif /* ndef _HCSECD_H_ */ diff --git a/usr.sbin/bluetooth/hcsecd/parser.y b/usr.sbin/bluetooth/hcsecd/parser.y index 750c068..d2e3696 100644 --- a/usr.sbin/bluetooth/hcsecd/parser.y +++ b/usr.sbin/bluetooth/hcsecd/parser.y @@ -26,14 +26,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: parser.y,v 1.1 2002/11/24 20:22:39 max Exp $ + * $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> +#include <sys/fcntl.h> #include <sys/queue.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> +#include <limits.h> #include <stdio.h> #include <stdarg.h> #include <string.h> @@ -49,7 +50,7 @@ static int hexa2int8(char *a); extern int yylineno; static LIST_HEAD(, link_key) link_keys; - char *config_file = "/usr/local/etc/hcsecd.conf"; + char *config_file = "/etc/bluetooth/hcsecd.conf"; static link_key_p key = NULL; %} @@ -82,13 +83,8 @@ line: T_DEVICE { if (get_key(&key->bdaddr, 1) != NULL) { syslog(LOG_ERR, "Ignoring duplicated entry " \ - "for bdaddr %x:%x:%x:%x:%x:%x", - key->bdaddr.b[5], - key->bdaddr.b[4], - key->bdaddr.b[3], - key->bdaddr.b[2], - key->bdaddr.b[1], - key->bdaddr.b[0]); + "for bdaddr %s", + bt_ntoa(&key->bdaddr, NULL)); free_key(key); } else LIST_INSERT_HEAD(&link_keys, key, next); @@ -109,21 +105,11 @@ option: bdaddr bdaddr: T_BDADDR T_BDADDRSTRING { - int a0, a1, a2, a3, a4, a5; - - if (sscanf($2, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) { + if (!bt_aton($2, &key->bdaddr)) { syslog(LOG_ERR, "Cound not parse BDADDR " \ "'%s'", $2); exit(1); } - - key->bdaddr.b[0] = (a0 & 0xff); - key->bdaddr.b[1] = (a1 & 0xff); - key->bdaddr.b[2] = (a2 & 0xff); - key->bdaddr.b[3] = (a3 & 0xff); - key->bdaddr.b[4] = (a4 & 0xff); - key->bdaddr.b[5] = (a5 & 0xff); } ; @@ -205,7 +191,7 @@ yyerror(char const *message) /* Re-read config file */ void -read_config_file(int s) +read_config_file(void) { extern FILE *yyin; @@ -286,18 +272,125 @@ dump_config(void) syslog(LOG_DEBUG, "device %s " \ -"bdaddr %x:%x:%x:%x:%x:%x " \ +"bdaddr %s " \ "pin %s " \ "key %s", (key->name != NULL)? key->name : "noname", - key->bdaddr.b[5], key->bdaddr.b[4], key->bdaddr.b[3], - key->bdaddr.b[2], key->bdaddr.b[1], key->bdaddr.b[0], + bt_ntoa(&key->bdaddr, NULL), (key->pin != NULL)? key->pin : "nopin", (key->key != NULL)? buffer : "nokey"); } } #endif +/* Read keys file */ +int +read_keys_file(void) +{ + FILE *f = NULL; + link_key_t *key = NULL; + char buf[HCSECD_BUFFER_SIZE], *p = NULL, *cp = NULL; + bdaddr_t bdaddr; + int i, len; + + if ((f = fopen(HCSECD_KEYSFILE, "r")) == NULL) { + if (errno == ENOENT) + return (0); + + syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n", + HCSECD_KEYSFILE, strerror(errno), errno); + + return (-1); + } + + while ((p = fgets(buf, sizeof(buf), f)) != NULL) { + if (*p == '#') + continue; + if ((cp = strpbrk(p, " ")) == NULL) + continue; + + *cp++ = '\0'; + + if (!bt_aton(p, &bdaddr)) + continue; + + if ((key = get_key(&bdaddr, 1)) == NULL) + continue; + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memset(key->key, 0, NG_HCI_KEY_SIZE); + + len = strlen(cp) / 2; + if (len > NG_HCI_KEY_SIZE) + len = NG_HCI_KEY_SIZE; + + for (i = 0; i < len; i ++) + key->key[i] = hexa2int8(cp + 2*i); + + syslog(LOG_DEBUG, "Restored link key for the entry, " \ + "remote bdaddr %s, name '%s'", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name"); + } + + fclose(f); + + return (0); +} + +/* Dump keys file */ +int +dump_keys_file(void) +{ + link_key_p key = NULL; + char tmp[PATH_MAX], buf[HCSECD_BUFFER_SIZE]; + int f; + + snprintf(tmp, sizeof(tmp), "%s.tmp", HCSECD_KEYSFILE); + if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { + syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n", + tmp, strerror(errno), errno); + return (-1); + } + + LIST_FOREACH(key, &link_keys, next) { + if (key->key == NULL) + continue; + + snprintf(buf, sizeof(buf), +"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + bt_ntoa(&key->bdaddr, NULL), + key->key[0], key->key[1], key->key[2], key->key[3], + key->key[4], key->key[5], key->key[6], key->key[7], + key->key[8], key->key[9], key->key[10], key->key[11], + key->key[12], key->key[13], key->key[14], key->key[15]); + + if (write(f, buf, strlen(buf)) < 0) { + syslog(LOG_ERR, "Could not write temp keys file. " \ + "%s (%d)\n", strerror(errno), errno); + break; + } + } + + close(f); + + if (rename(tmp, HCSECD_KEYSFILE) < 0) { + syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n", + tmp, HCSECD_KEYSFILE, strerror(errno), errno); + unlink(tmp); + return (-1); + } + + return (0); +} + /* Free key entry */ static void free_key(link_key_p key) diff --git a/usr.sbin/bluetooth/hcseriald/Makefile b/usr.sbin/bluetooth/hcseriald/Makefile index 4d6b629..f21331b 100644 --- a/usr.sbin/bluetooth/hcseriald/Makefile +++ b/usr.sbin/bluetooth/hcseriald/Makefile @@ -1,15 +1,10 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:45 max Exp $ +# $Id: Makefile,v 1.5 2003/08/14 20:06:21 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man - PROG= hcseriald -MAN8= hcseriald.8 - -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hcseriald.8 SRCS= hcseriald.c +WARNS?= 2 DPADD= ${LIBNETGRAPH} LDADD= -lnetgraph diff --git a/usr.sbin/bluetooth/hcseriald/hcseriald.8 b/usr.sbin/bluetooth/hcseriald/hcseriald.8 index 25b89b3..2bf9c54 100644 --- a/usr.sbin/bluetooth/hcseriald/hcseriald.8 +++ b/usr.sbin/bluetooth/hcseriald/hcseriald.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hcseriald.8,v 1.2 2003/04/27 19:45:33 max Exp $ +.\" $Id: hcseriald.8,v 1.3 2003/05/21 00:47:26 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/usr.sbin/bluetooth/hcseriald/hcseriald.c b/usr.sbin/bluetooth/hcseriald/hcseriald.c index a4e7f54..35429ad 100644 --- a/usr.sbin/bluetooth/hcseriald/hcseriald.c +++ b/usr.sbin/bluetooth/hcseriald/hcseriald.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcseriald.c,v 1.2 2003/04/27 19:45:33 max Exp $ + * $Id: hcseriald.c,v 1.3 2003/05/21 22:40:32 max Exp $ * $FreeBSD$ */ @@ -34,7 +34,7 @@ #include <netgraph/ng_message.h> #include <netgraph.h> -#include <ng_h4.h> +#include <netgraph/bluetooth/include/ng_h4.h> #include <errno.h> #include <fcntl.h> diff --git a/usr.sbin/bluetooth/l2control/Makefile b/usr.sbin/bluetooth/l2control/Makefile index f6fb501..847ff4b 100644 --- a/usr.sbin/bluetooth/l2control/Makefile +++ b/usr.sbin/bluetooth/l2control/Makefile @@ -1,12 +1,12 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:47 max Exp $ +# $Id: Makefile,v 1.7 2003/08/14 20:06:22 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= l2control -MAN8= l2control.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= l2control.8 SRCS= l2cap.c l2control.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/l2control/l2cap.c b/usr.sbin/bluetooth/l2control/l2cap.c index ca4111d..c23106c 100644 --- a/usr.sbin/bluetooth/l2control/l2cap.c +++ b/usr.sbin/bluetooth/l2control/l2cap.c @@ -25,17 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2cap.c,v 1.4 2003/04/26 23:11:25 max Exp $ + * $Id: l2cap.c,v 1.5 2003/05/16 19:52:37 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> #include <sys/ioctl.h> -#include <bitstring.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +39,33 @@ #define SIZE(x) (sizeof((x))/sizeof((x)[0])) +/* Print BDADDR */ +static char * +bdaddrpr(bdaddr_t const *ba) +{ + extern int numeric_bdaddr; + static char str[24]; + struct hostent *he = NULL; + + if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { + str[0] = '*'; + str[1] = 0; + + return (str); + } + + if (!numeric_bdaddr && + (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { + strlcpy(str, he->h_name, sizeof(str)); + + return (str); + } + + bt_ntoa(ba, str); + + return (str); +} /* bdaddrpr */ + /* Send read_node_flags command to the node */ static int l2cap_read_node_flags(int s, int argc, char **argv) @@ -134,17 +157,12 @@ l2cap_read_connection_list(int s, int argc, char **argv) "Remote BD_ADDR Handle Flags Pending State\n"); for (n = 0; n < r.num_connections; n++) { fprintf(stdout, - "%02x:%02x:%02x:%02x:%02x:%02x " \ + "%-17.17s " \ "%6d " \ "%c%c%c%c%c " \ "%7d " \ "%s\n", - r.connections[n].remote.b[5], - r.connections[n].remote.b[4], - r.connections[n].remote.b[3], - r.connections[n].remote.b[2], - r.connections[n].remote.b[1], - r.connections[n].remote.b[0], + bdaddrpr(&r.connections[n].remote), r.connections[n].con_handle, ((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'), ((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '), @@ -197,13 +215,11 @@ l2cap_read_channel_list(int s, int argc, char **argv) "Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n"); for (n = 0; n < r.num_channels; n++) { fprintf(stdout, - "%02x:%02x:%02x:%02x:%02x:%02x " \ + "%-17.17s " \ "%5d/%5d %5d " \ "%5d/%5d " \ "%s\n", - r.channels[n].remote.b[5], r.channels[n].remote.b[4], - r.channels[n].remote.b[3], r.channels[n].remote.b[2], - r.channels[n].remote.b[1], r.channels[n].remote.b[0], + bdaddrpr(&r.channels[n].remote), r.channels[n].scid, r.channels[n].dcid, r.channels[n].psm, r.channels[n].imtu, r.channels[n].omtu, diff --git a/usr.sbin/bluetooth/l2control/l2control.8 b/usr.sbin/bluetooth/l2control/l2control.8 index dcd05fe..e98f301 100644 --- a/usr.sbin/bluetooth/l2control/l2control.8 +++ b/usr.sbin/bluetooth/l2control/l2control.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: l2control.8,v 1.3 2003/04/27 19:45:34 max Exp $ +.\" $Id: l2control.8,v 1.5 2003/05/21 00:53:00 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 @@ -33,7 +33,7 @@ .Nd L2CAP configuration utility .Sh SYNOPSIS .Nm -.Op Fl h +.Op Fl hn .Fl a Ar BD_ADDR .Ar command .Op Ar parameters ... @@ -55,6 +55,11 @@ Example: .Fl a Li 00:01:02:03:04:05 . .It Fl h Display usage message and exit. +.It Fl n +Show Bluetooth addresses as numbers. +Normally +.Nm +attempts to resolve Bluetooth addresses, and display them symbolically. .It Ar command One of the supported commands (see below). Special command diff --git a/usr.sbin/bluetooth/l2control/l2control.c b/usr.sbin/bluetooth/l2control/l2control.c index a259657..585021c 100644 --- a/usr.sbin/bluetooth/l2control/l2control.c +++ b/usr.sbin/bluetooth/l2control/l2control.c @@ -25,19 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2control.c,v 1.3 2003/04/27 19:45:34 max Exp $ + * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> -#include <bitstring.h> #include <assert.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -52,6 +47,9 @@ static void print_l2cap_command (struct l2cap_command *); static void usage (void); /* Main */ + +int numeric_bdaddr = 0; + int main(int argc, char *argv[]) { @@ -61,24 +59,22 @@ main(int argc, char *argv[]) memset(&bdaddr, 0, sizeof(bdaddr)); /* Process command line arguments */ - while ((n = getopt(argc, argv, "a:h")) != -1) { + while ((n = getopt(argc, argv, "a:nh")) != -1) { switch (n) { - case 'a': { - int a0, a1, a2, a3, a4, a5; + case 'a': + if (!bt_aton(optarg, &bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) { - usage(); - break; + memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); } + break; - bdaddr.b[0] = (a0 & 0xff); - bdaddr.b[1] = (a1 & 0xff); - bdaddr.b[2] = (a2 & 0xff); - bdaddr.b[3] = (a3 & 0xff); - bdaddr.b[4] = (a4 & 0xff); - bdaddr.b[5] = (a5 & 0xff); - } break; + case 'n': + numeric_bdaddr = 1; + break; case 'h': default: @@ -144,10 +140,7 @@ do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv) if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(2, -"Could not bind socket, bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); e = 0x0ffff; if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0) @@ -200,7 +193,7 @@ find_l2cap_command(char const *command, struct l2cap_command *category) return (NULL); } /* find_l2cap_command */ -/* Try to find command in specified category */ +/* Print commands in specified category */ static void print_l2cap_command(struct l2cap_command *category) { @@ -214,7 +207,7 @@ print_l2cap_command(struct l2cap_command *category) static void usage(void) { - fprintf(stdout, "Usage: l2control -a BD_ADDR [-h] cmd [p1] [..]]\n"); + fprintf(stdout, "Usage: l2control -a BD_ADDR [-n] [-h] cmd [p1] [..]]\n"); exit(255); } /* usage */ diff --git a/usr.sbin/bluetooth/l2ping/Makefile b/usr.sbin/bluetooth/l2ping/Makefile index d99143b..e62d2af 100644 --- a/usr.sbin/bluetooth/l2ping/Makefile +++ b/usr.sbin/bluetooth/l2ping/Makefile @@ -1,12 +1,12 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:49 max Exp $ +# $Id: Makefile,v 1.6 2003/08/14 20:06:24 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= l2ping -MAN8= l2ping.8 +MAN= l2ping.8 SRCS= l2ping.c WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/l2ping/l2ping.8 b/usr.sbin/bluetooth/l2ping/l2ping.8 index 8ecd11e..13e2dfc 100644 --- a/usr.sbin/bluetooth/l2ping/l2ping.8 +++ b/usr.sbin/bluetooth/l2ping/l2ping.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: l2ping.8,v 1.2 2003/04/27 19:45:35 max Exp $ +.\" $Id: l2ping.8,v 1.3 2003/05/21 01:00:19 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/usr.sbin/bluetooth/l2ping/l2ping.c b/usr.sbin/bluetooth/l2ping/l2ping.c index 5f3bc28..b7ef2a5 100644 --- a/usr.sbin/bluetooth/l2ping/l2ping.c +++ b/usr.sbin/bluetooth/l2ping/l2ping.c @@ -25,27 +25,22 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2ping.c,v 1.3 2003/04/27 19:45:36 max Exp $ + * $Id: l2ping.c,v 1.5 2003/05/16 19:54:40 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> #include <sys/ioctl.h> -#include <sys/socket.h> #include <sys/time.h> #include <arpa/inet.h> #include <netinet/in.h> #include <assert.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> static void usage (void); static void tv_sub (struct timeval *, struct timeval const *); @@ -64,11 +59,12 @@ static char const pattern[] = "1234567890-"; int main(int argc, char *argv[]) { - bdaddr_t src, dst; - struct sockaddr_l2cap sa; - struct ng_btsocket_l2cap_raw_ping r; - int n, s, count, wait, flood, fail; - struct timeval a, b; + bdaddr_t src, dst; + struct hostent *he = NULL; + struct sockaddr_l2cap sa; + struct ng_btsocket_l2cap_raw_ping r; + int n, s, count, wait, flood, fail; + struct timeval a, b; /* Set defaults */ memcpy(&src, NG_HCI_BDADDR_ANY, sizeof(src)); @@ -90,31 +86,22 @@ main(int argc, char *argv[]) while ((n = getopt(argc, argv, "a:c:fi:n:s:S:h")) != -1) { switch (n) { case 'a': - case 'S': { - int a0, a1, a2, a3, a4, a5; + if (!bt_aton(optarg, &dst)) { + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - usage(); + memcpy(&dst, he->h_addr, sizeof(dst)); + } + break; - if (n == 'a') { - /* destination bdaddr */ - dst.b[0] = (a0 & 0xff); - dst.b[1] = (a1 & 0xff); - dst.b[2] = (a2 & 0xff); - dst.b[3] = (a3 & 0xff); - dst.b[4] = (a4 & 0xff); - dst.b[5] = (a5 & 0xff); - } else { - /* source bdaddr */ - src.b[0] = (a0 & 0xff); - src.b[1] = (a1 & 0xff); - src.b[2] = (a2 & 0xff); - src.b[3] = (a3 & 0xff); - src.b[4] = (a4 & 0xff); - src.b[5] = (a5 & 0xff); + case 'S': + if (!bt_aton(optarg, &src)) { + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&src, he->h_addr, sizeof(src)); } - } break; + break; case 'c': count = atoi(optarg); @@ -162,10 +149,7 @@ main(int argc, char *argv[]) if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(3, -"Could not bind socket, src bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not bind socket, src bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); memset(&sa, 0, sizeof(sa)); sa.l2cap_len = sizeof(sa); @@ -174,10 +158,7 @@ main(int argc, char *argv[]) if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(4, -"Could not connect socket, dst bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not connect socket, dst bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); /* Fill pattern */ for (n = 0; n < r.echo_size; ) { @@ -198,10 +179,8 @@ main(int argc, char *argv[]) r.result = errno; fail = 1; /* - warn("Could not ping, dst bdaddr=%x:%x:%x:%x:%x:%x", - r.echo_dst.b[5], r.echo_dst.b[4], - r.echo_dst.b[3], r.echo_dst.b[2], - r.echo_dst.b[1], r.echo_dst.b[0]); + warn("Could not ping, dst bdaddr=%s", + bt_ntoa(&r.echo_dst, NULL)); */ } @@ -211,10 +190,9 @@ main(int argc, char *argv[]) tv_sub(&b, &a); fprintf(stdout, -"%d bytes from %x:%x:%x:%x:%x:%x seq_no=%d time=%.3f ms result=%#x %s\n", - r.echo_size, - dst.b[5], dst.b[4], dst.b[3], - dst.b[2], dst.b[1], dst.b[0], +"%d bytes from %s seq_no=%d time=%.3f ms result=%#x %s\n", + r.echo_size, + bt_ntoa(&dst, NULL), ntohl(*((int *)(r.echo_data))), tv2msec(&b), r.result, ((fail == 0)? "" : strerror(errno))); diff --git a/usr.sbin/bluetooth/rfcomm_pppd/Makefile b/usr.sbin/bluetooth/rfcomm_pppd/Makefile index 0269123..adac64e 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/Makefile +++ b/usr.sbin/bluetooth/rfcomm_pppd/Makefile @@ -1,13 +1,14 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:50 max Exp $ +# $Id: Makefile,v 1.7 2003/09/07 18:32:11 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man +.PATH: ${.CURDIR}/../../../usr.bin/bluetooth/rfcomm_sppd + PROG= rfcomm_pppd -MAN8= rfcomm_pppd.8 +MAN= rfcomm_pppd.8 +SRCS= rfcomm_pppd.c rfcomm_sdp.c WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include -SRCS= rfcomm_pppd.c -.include <bsd.prog.mk> +DPADD= ${LIBBLUETOOTH} ${LIBSDP} +LDADD= -lbluetooth -lsdp +.include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 index d6af46d..591a5ce 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 +++ b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: rfcomm_pppd.8,v 1.5 2003/04/27 19:45:37 max Exp $ +.\" $Id: rfcomm_pppd.8,v 1.7 2003/09/07 18:32:11 max Exp $ .\" $FreeBSD$ .\" .Dd February 4, 2003 @@ -54,7 +54,7 @@ It can operate in two modes: client and server. .Pp In the client mode, .Nm -opens an RFCOMM connection to the specified server's +opens a RFCOMM connection to the specified server's .Ar BD_ADRR and .Ar channel . @@ -75,7 +75,7 @@ and connect to the Internet. .Pp In the server mode, .Nm -opens an RFCOMM socket and listens for incomming connections from remote clients. +opens a RFCOMM socket and listens for incomming connections from remote clients. Once the new incomming connection is accepted, .Nm forks and executes @@ -92,7 +92,7 @@ the standard serial port thus providing network connectivity to remote clients. The options are as follows: .Bl -tag -width indent .It Fl a Ar BD_ADDR -In the client mode, this required option specifies the remote BD_ADDR of the +In the client mode this required option specifies the remote BD_ADDR of the RFCOMM server. In the server mode, this option can be used to specify the local BD_ADDR to listen on. @@ -100,21 +100,32 @@ By default, server will listen on .Dv ANY address. .It Fl C Ar channel -In both client and server modes, this required option specifies RFCOMM channel +In both client and server modes this required option specifies RFCOMM channel to connect to or listen on. +In the server mode RFCOMM channel should be number between 1 and 30. +In the client mode RFCOMM channel could be either number between 1 and 30 or +service name. Supported service names are: +.Cm DUN +for DialUp Networking service and +.Cm LAN +for LAN Access Using PPP service. +If service name was specified instead of numeric RFCOMM channel then +.Nm +utility will try to obtain RFCOMM channel for the service via Service +Discovery Protocol. .It Fl c -Act as an RFCOMM client. +Act as a RFCOMM client. This is the default mode. .It Fl d Do not detach from the controlling terminal, i.e., run in foreground. .It Fl h Display usage message and exit. .It Fl l Ar label -In both client and server modes, this required option specifies which +In both client and server modes this required option specifies which .Xr ppp 8 label will be used. .It Fl s -Act as an RFCOMM server. +Act as a RFCOMM server. .El .Sh PPP CONFIGURATION .Ss Important Notes on PPP Configuration @@ -265,7 +276,7 @@ label. The .Nm utility -is not currently integrated with the SDP (Service Discovery Protocol). +does not register services with local SDP (Service Discovery Protocol) daemon. .Sh SEE ALSO .Xr rfcomm_sppd 1 , .Xr ng_btsocket 4 , diff --git a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c index 160988e..ec9f4ca4 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c +++ b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c @@ -25,18 +25,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: rfcomm_pppd.c,v 1.3 2003/04/26 23:59:49 max Exp $ + * $Id: rfcomm_pppd.c,v 1.5 2003/09/07 18:32:11 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> -#include <bitstring.h> +#include <bluetooth.h> +#include <ctype.h> +#include <err.h> #include <errno.h> #include <fcntl.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> +#include <sdp.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -47,6 +45,10 @@ #define RFCOMM_PPPD "rfcomm_pppd" +int rfcomm_channel_lookup (bdaddr_t const *local, + bdaddr_t const *remote, + int service, int *channel, int *error); + static void exec_ppp (int s, char *label); static void sighandler (int s); static void usage (void); @@ -58,41 +60,49 @@ int main(int argc, char *argv[]) { struct sockaddr_rfcomm sock_addr; - char *label = NULL; + char *label = NULL, *ep = NULL; bdaddr_t addr; - int s, channel, detach, server; + int s, channel, detach, server, service; pid_t pid; memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)); channel = 0; detach = 1; server = 0; + service = 0; /* Parse command line arguments */ while ((s = getopt(argc, argv, "a:cC:dhl:s")) != -1) { switch (s) { - case 'a': { /* BDADDR */ - int a0, a1, a2, a3, a4, a5; - - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - usage(); - /* NOT REACHED */ - - addr.b[0] = a0 & 0xff; - addr.b[1] = a1 & 0xff; - addr.b[2] = a2 & 0xff; - addr.b[3] = a3 & 0xff; - addr.b[4] = a4 & 0xff; - addr.b[5] = a5 & 0xff; - } break; + case 'a': /* BDADDR */ + if (!bt_aton(optarg, &addr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&addr, he->h_addr, sizeof(addr)); + } + break; case 'c': /* client */ server = 0; break; case 'C': /* RFCOMM channel */ - channel = atoi(optarg); + channel = strtoul(optarg, &ep, 10); + if (*ep != 0) { + channel = 0; + switch (tolower(optarg[0])) { + case 'd': /* DialUp Networking */ + service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; + break; + + case 'l': /* LAN Access Using PPP */ + service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; + break; + } + } break; case 'd': /* do not detach */ @@ -115,10 +125,22 @@ main(int argc, char *argv[]) } /* Check if we got everything we wanted */ - if ((channel <= 0 || channel > 30) || label == NULL || - (!server && memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)) - usage(); - /* NOT REACHED */ + if (label == NULL) + errx(1, "Must specify PPP label"); + + if (!server) { + if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) + errx(1, "Must specify server BD_ADDR"); + + /* Check channel, if was not set then obtain it via SDP */ + if (channel == 0 && service != 0) + if (rfcomm_channel_lookup(NULL, &addr, service, + &channel, &s) != 0) + errc(1, s, "Could not obtain RFCOMM channel"); + } + + if (channel <= 0 || channel > 30) + errx(1, "Invalid RFCOMM channel number %d", channel); openlog(RFCOMM_PPPD, LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_USER); diff --git a/usr.sbin/bluetooth/sdpcontrol/Makefile b/usr.sbin/bluetooth/sdpcontrol/Makefile new file mode 100644 index 0000000..c0ec8d4 --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/Makefile @@ -0,0 +1,12 @@ +# $Id: Makefile,v 1.1 2003/09/08 02:27:27 max Exp $ +# $FreeBSD$ + +PROG= sdpcontrol +MAN= sdpcontrol.8 +SRCS= sdpcontrol.c search.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} ${LIBSDP} +LDADD= -lbluetooth -lsdp + +.include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 new file mode 100644 index 0000000..a7f1f6b --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 @@ -0,0 +1,100 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: sdpcontrol.8,v 1.1 2003/09/08 02:27:27 max Exp $ +.\" $FreeBSD$ +.\" +.Dd September 7, 2003 +.Dt SDPCONTROL 8 +.Os +.Sh NAME +.Nm spdcontrol +.Nd SDP configuration utility +.Sh SYNOPSIS +.Nm +.Op Fl h +.Fl a Ar BD_ADDR +.Ar command +.Op Ar parameters ... +.Sh DESCRIPTION +The +.Nm +utility connects to the remote device with the specified BD_ADDR and attempts +to send query via Service Discovery Protocol (SDP). +The +.Nm +utility will use Service Search Attribute Request and will print results to +the standard output and error messages to the standard error. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a Ar BD_ADDR +Connect to the remote device with the specified BD_ADDR. +Example: +.Fl a Li 00:01:02:03:04:05 . +.It Fl h +Display usage message and exit. +.It Ar command +One of the supported commands (see below). +Special command +.Cm help +can be used to obtain the list of all supported commands. +To get more information about specific command use +.Cm help Ar command . +.It Ar parameters +One or more optional space separated command parameters. +.El +.Sh COMMANDS +The currently supported node commands in +.Nm +are: +.Pp +.Bl -tag -offset indent -compact +.It Cm Browse +.It Cm Search +.El +.Sh CAVEAT +Currently, the +.Nm +utility only implements client side functionality. +.Pp +The +.Nm +utility only request the following attributes from the remote SDP server: +.Bl -enum -offset indent -compact +.It +Service Record Handle +.It +Service Class ID List +.It +Protocol Descriptor List +.It +Bluetooth Profile Descriptor List +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr sdp 3 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c new file mode 100644 index 0000000..b5a1a4d --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c @@ -0,0 +1,197 @@ +/* + * sdpcontrol.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdpcontrol.c,v 1.1 2003/09/08 02:27:27 max Exp $ + * $FreeBSD$ + */ + +#include <assert.h> +#include <bluetooth.h> +#include <err.h> +#include <errno.h> +#include <sdp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "sdpcontrol.h" + +/* Prototypes */ +static int do_sdp_command (bdaddr_p, int, char **); +static struct sdp_command * find_sdp_command (char const *, + struct sdp_command *); +static void print_sdp_command (struct sdp_command *); +static void usage (void); + +/* Main */ +int +main(int argc, char *argv[]) +{ + int n; + bdaddr_t bdaddr; + + memset(&bdaddr, 0, sizeof(bdaddr)); + + /* Process command line arguments */ + while ((n = getopt(argc, argv, "a:h")) != -1) { + switch (n) { + case 'a': + if (!bt_aton(optarg, &bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); + } + break; + + case 'h': + default: + usage(); + /* NOT REACHED */ + } + } + + argc -= optind; + argv += optind; + + if (*argv == NULL) + usage(); + + return (do_sdp_command(&bdaddr, argc, argv)); +} + +/* Execute commands */ +static int +do_sdp_command(bdaddr_p bdaddr, int argc, char **argv) +{ + char *cmd = argv[0]; + struct sdp_command *c = NULL; + void *xs = NULL; + int e, help; + + help = 0; + if (strcasecmp(cmd, "help") == 0) { + argc --; + argv ++; + + if (argc <= 0) { + fprintf(stdout, "Supported commands:\n"); + print_sdp_command(sdp_commands); + fprintf(stdout, "\nFor more information use " \ + "'help command'\n"); + + return (OK); + } + + help = 1; + cmd = argv[0]; + } + + c = find_sdp_command(cmd, sdp_commands); + if (c == NULL) { + fprintf(stdout, "Unknown command: \"%s\"\n", cmd); + return (ERROR); + } + + if (!help) { + if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) + usage(); + + if ((xs = sdp_open(NG_HCI_BDADDR_ANY, bdaddr)) == NULL) + errx(1, "Could not create SDP session object"); + + if (sdp_error(xs) == 0) + e = (c->handler)(xs, -- argc, ++ argv); + else + e = ERROR; + } else + e = USAGE; + + switch (e) { + case OK: + case FAILED: + break; + + case ERROR: + fprintf(stdout, "Could not execute command \"%s\". %s\n", + cmd, strerror(sdp_error(xs))); + break; + + case USAGE: + fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); + break; + + default: assert(0); break; + } + + sdp_close(xs); + + return (e); +} /* do_sdp_command */ + +/* Try to find command in specified category */ +static struct sdp_command * +find_sdp_command(char const *command, struct sdp_command *category) +{ + struct sdp_command *c = NULL; + + for (c = category; c->command != NULL; c++) { + char *c_end = strchr(c->command, ' '); + + if (c_end != NULL) { + int len = c_end - c->command; + + if (strncasecmp(command, c->command, len) == 0) + return (c); + } else if (strcasecmp(command, c->command) == 0) + return (c); + } + + return (NULL); +} /* find_sdp_command */ + +/* Print commands in specified category */ +static void +print_sdp_command(struct sdp_command *category) +{ + struct sdp_command *c = NULL; + + for (c = category; c->command != NULL; c++) + fprintf(stdout, "\t%s\n", c->command); +} /* print_sdp_command */ + +/* Usage */ +static void +usage(void) +{ + fprintf(stdout, "Usage: sdpcontrol -a BD_ADDR [-h] " \ + "cmd [p1] [..]]\n"); + exit(255); +} /* usage */ + diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h new file mode 100644 index 0000000..4a1ee76f --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h @@ -0,0 +1,49 @@ +/* + * sdpcontrol.h + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdpcontrol.h,v 1.1 2003/09/08 02:27:27 max Exp $ + * $FreeBSD$ + */ + +#ifndef __SDPCONTROL_H__ +#define __SDPCONTROL_H__ + +#define OK 0 /* everything was OK */ +#define ERROR 1 /* could not execute command */ +#define FAILED 2 /* error was reported */ +#define USAGE 3 /* invalid parameters */ + +struct sdp_command { + char const *command; + char const *description; + int (*handler)(void *, int, char **); +}; + +extern struct sdp_command sdp_commands[]; + +#endif /* __SDPCONTROL_H__ */ + diff --git a/usr.sbin/bluetooth/sdpcontrol/search.c b/usr.sbin/bluetooth/sdpcontrol/search.c new file mode 100644 index 0000000..7180952 --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/search.c @@ -0,0 +1,707 @@ +/* + * search.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <ctype.h> +#include <sdp.h> +#include <stdio.h> +#include <stdlib.h> +#include "sdpcontrol.h" + +/* List of the attributes we are looking for */ +static u_int32_t attrs[] = +{ + SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, + SDP_ATTR_SERVICE_RECORD_HANDLE), + SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, + SDP_ATTR_SERVICE_CLASS_ID_LIST), + SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), + SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, + SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) +}; +#define attrs_len (sizeof(attrs)/sizeof(attrs[0])) + +/* Buffer for the attributes */ +#define NRECS 25 /* request this much records from the SDP server */ +#define BSIZE 256 /* one attribute buffer size */ +static u_int8_t buffer[NRECS * attrs_len][BSIZE]; + +/* SDP attributes */ +static sdp_attr_t values[NRECS * attrs_len]; +#define values_len (sizeof(values)/sizeof(values[0])) + +/* + * Print Service Class ID List + * + * The ServiceClassIDList attribute consists of a data element sequence in + * which each data element is a UUID representing the service classes that + * a given service record conforms to. The UUIDs are listed in order from + * the most specific class to the most general class. The ServiceClassIDList + * must contain at least one service class UUID. + */ + +static void +print_service_class_id_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len, value; + + if (end - start < 2) { + fprintf(stderr, "Invalid Service Class ID List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Service Class ID List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value, start); + fprintf(stdout, "\t%s (%#4.4x)\n", + sdp_uuid2desc(value), value); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value, start); + fprintf(stdout, "\t%#8.8x\n", value); + break; + + case SDP_DATA_UUID128: { + int128_t uuid; + + SDP_GET128(&uuid, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&uuid.b[0], + *(u_int16_t *)&uuid.b[4], + *(u_int16_t *)&uuid.b[6], + *(u_int16_t *)&uuid.b[8], + *(u_int16_t *)&uuid.b[10], + *(u_int32_t *)&uuid.b[12]); + } break; + + default: + fprintf(stderr, "Invalid Service Class ID List. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + } +} /* print_service_class_id_list */ + +/* + * Print Protocol Descriptor List + * + * If the ProtocolDescriptorList describes a single stack, it takes the form + * of a data element sequence in which each element of the sequence is a + * protocol descriptor. Each protocol descriptor is, in turn, a data element + * sequence whose first element is a UUID identifying the protocol and whose + * successive elements are protocol-specific parameters. The protocol + * descriptors are listed in order from the lowest layer protocol to the + * highest layer protocol used to gain access to the service. If it is possible + * for more than one kind of protocol stack to be used to gain access to the + * service, the ProtocolDescriptorList takes the form of a data element + * alternative where each member is a data element sequence as described above. + */ + +static void +print_protocol_descriptor(u_int8_t const *start, u_int8_t const *end) +{ + union { + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + int128_t int128; + } value; + u_int32_t type, len, param; + + /* Get Protocol UUID */ + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value.uint16, start); + fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), + value.uint16); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value.uint32, start); + fprintf(stdout, "\t%#8.8x\n", value.uint32); + break; + + case SDP_DATA_UUID128: + SDP_GET128(&value.int128, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&value.int128.b[0], + *(u_int16_t *)&value.int128.b[4], + *(u_int16_t *)&value.int128.b[6], + *(u_int16_t *)&value.int128.b[8], + *(u_int16_t *)&value.int128.b[10], + *(u_int32_t *)&value.int128.b[12]); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Protocol specific parameters */ + for (param = 1; start < end; param ++) { + fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_NIL: + fprintf(stdout, "nil\n"); + break; + + case SDP_DATA_UINT8: + case SDP_DATA_INT8: + case SDP_DATA_BOOL: + SDP_GET8(value.uint8, start); + fprintf(stdout, "u/int8/bool %u\n", value.uint8); + break; + + case SDP_DATA_UINT16: + case SDP_DATA_INT16: + case SDP_DATA_UUID16: + SDP_GET16(value.uint16, start); + fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); + break; + + case SDP_DATA_UINT32: + case SDP_DATA_INT32: + case SDP_DATA_UUID32: + SDP_GET32(value.uint32, start); + fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); + break; + + case SDP_DATA_UINT64: + case SDP_DATA_INT64: + SDP_GET64(value.uint64, start); + fprintf(stdout, "u/int64 %llu\n", value.uint64); + break; + + case SDP_DATA_UINT128: + case SDP_DATA_INT128: + case SDP_DATA_UUID128: + SDP_GET128(&value.int128, start); + fprintf(stdout, "u/int/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&value.int128.b[0], + *(u_int16_t *)&value.int128.b[4], + *(u_int16_t *)&value.int128.b[6], + *(u_int16_t *)&value.int128.b[8], + *(u_int16_t *)&value.int128.b[10], + *(u_int32_t *)&value.int128.b[12]); + break; + + case SDP_DATA_STR8: + case SDP_DATA_URL8: + SDP_GET8(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_STR16: + case SDP_DATA_URL16: + SDP_GET16(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_STR32: + case SDP_DATA_URL32: + SDP_GET32(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_SEQ8: + case SDP_DATA_ALT8: + SDP_GET8(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + case SDP_DATA_SEQ16: + case SDP_DATA_ALT16: + SDP_GET16(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + case SDP_DATA_SEQ32: + case SDP_DATA_ALT32: + SDP_GET32(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor. " \ + "Unknown data type: %#02x\n", type); + return; + /* NOT REACHED */ + } + } +} /* print_protocol_descriptor */ + +static void +print_protocol_descriptor_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len; + + if (end - start < 2) { + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + print_protocol_descriptor(start, start + len); + start += len; + } +} /* print_protocol_descriptor_list */ + +/* + * Print Bluetooth Profile Descriptor List + * + * The BluetoothProfileDescriptorList attribute consists of a data element + * sequence in which each element is a profile descriptor that contains + * information about a Bluetooth profile to which the service represented by + * this service record conforms. Each profile descriptor is a data element + * sequence whose first element is the UUID assigned to the profile and whose + * second element is a 16-bit profile version number. Each version of a profile + * is assigned a 16-bit unsigned integer profile version number, which consists + * of two 8-bit fields. The higher-order 8 bits contain the major version + * number field and the lower-order 8 bits contain the minor version number + * field. + */ + +static void +print_bluetooth_profile_descriptor_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len, value; + + if (end - start < 2) { + fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Get UUID */ + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value, start); + fprintf(stdout, "\t%s (%#4.4x) ", + sdp_uuid2desc(value), value); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value, start); + fprintf(stdout, "\t%#8.8x ", value); + break; + + case SDP_DATA_UUID128: { + int128_t uuid; + + SDP_GET128(&uuid, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ", + *(u_int32_t *)&uuid.b[0], + *(u_int16_t *)&uuid.b[4], + *(u_int16_t *)&uuid.b[6], + *(u_int16_t *)&uuid.b[8], + *(u_int16_t *)&uuid.b[10], + *(u_int32_t *)&uuid.b[12]); + } break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Get version */ + SDP_GET8(type, start); + if (type != SDP_DATA_UINT16) { + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Invalid version type=%#x\n", type); + return; + } + + SDP_GET16(value, start); + fprintf(stdout, "ver. %d.%d\n", + (value >> 8) & 0xff, value & 0xff); + } +} /* print_bluetooth_profile_descriptor_list */ + +/* Perform SDP search command */ +static int +do_sdp_search(void *xs, int argc, char **argv) +{ + char *ep = NULL; + int32_t n, type, value; + u_int16_t service; + + /* Parse command line arguments */ + switch (argc) { + case 1: + n = strtoul(argv[0], &ep, 16); + if (*ep != 0) { + switch (tolower(argv[0][0])) { + case 'c': /* CIP/CTP */ + switch (tolower(argv[0][1])) { + case 'i': + service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS; + break; + + case 't': + service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'd': /* DialUp Networking */ + service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; + break; + + case 'f': /* Fax/OBEX File Transfer */ + switch (tolower(argv[0][1])) { + case 'a': + service = SDP_SERVICE_CLASS_FAX; + break; + + case 't': + service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'g': /* GN */ + service = SDP_SERVICE_CLASS_GN; + break; + + case 'h': /* Headset/HID */ + switch (tolower(argv[0][1])) { + case 'i': + service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; + break; + + case 's': + service = SDP_SERVICE_CLASS_HEADSET; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'l': /* LAN Access Using PPP */ + service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; + break; + + case 'n': /* NAP */ + service = SDP_SERVICE_CLASS_NAP; + break; + + case 'o': /* OBEX Object Push */ + service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH; + break; + + case 's': /* Serial Port */ + service = SDP_SERVICE_CLASS_SERIAL_PORT; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + } else + service = (u_int16_t) n; + break; + + default: + return (USAGE); + } + + if (service < SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER) + return (USAGE); + + /* Initialize attribute values array */ + for (n = 0; n < values_len; n ++) { + values[n].flags = SDP_ATTR_INVALID; + values[n].attr = 0; + values[n].vlen = BSIZE; + values[n].value = buffer[n]; + } + + /* Do SDP Service Search Attribute Request */ + n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values); + if (n != 0) + return (ERROR); + + /* Print attributes values */ + for (n = 0; n < values_len; n ++) { + if (values[n].flags != SDP_ATTR_OK) + break; + + switch (values[n].attr) { + case SDP_ATTR_SERVICE_RECORD_HANDLE: + fprintf(stdout, "\n"); + if (values[n].vlen == 5) { + SDP_GET8(type, values[n].value); + if (type == SDP_DATA_UINT32) { + SDP_GET32(value, values[n].value); + fprintf(stdout, "Record Handle: " \ + "%#8.8x\n", value); + } else + fprintf(stderr, "Invalid type=%#x " \ + "Record Handle " \ + "attribute!\n", type); + } else + fprintf(stderr, "Invalid size=%d for Record " \ + "Handle attribute\n", + values[n].vlen); + break; + + case SDP_ATTR_SERVICE_CLASS_ID_LIST: + fprintf(stdout, "Service Class ID List:\n"); + print_service_class_id_list(values[n].value, + values[n].value + values[n].vlen); + break; + + case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: + fprintf(stdout, "Protocol Descriptor List:\n"); + print_protocol_descriptor_list(values[n].value, + values[n].value + values[n].vlen); + break; + + case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST: + fprintf(stdout, "Bluetooth Profile Descriptor List:\n"); + print_bluetooth_profile_descriptor_list(values[n].value, + values[n].value + values[n].vlen); + break; + + default: + fprintf(stderr, "Unexpected attribute ID=%#4.4x\n", + values[n].attr); + break; + } + } + + return (OK); +} /* do_sdp_search */ + +/* Perform SDP browse command */ +static int +do_sdp_browse(void *xs, int argc, char **argv) +{ +#undef _STR +#undef STR +#define _STR(x) #x +#define STR(x) _STR(x) + + static char const * const av[] = { + STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP), + NULL + }; + + switch (argc) { + case 0: + argc = 1; + argv = (char **) av; + /* FALL THROUGH */ + case 1: + return (do_sdp_search(xs, argc, argv)); + } + + return (USAGE); +} /* do_sdp_browse */ + +/* List of SDP commands */ +struct sdp_command sdp_commands[] = { +{ +"Browse [<Group>]", +"Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \ +"to browse. If omitted <Group> is set to Public Browse Group.\n\n" \ +"\t<Group> - xxxx; 16-bit UUID of the group to browse\n", +do_sdp_browse +}, +{ +"Search <Service>", +"Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \ +"service to search for. For some services it is possible to use service name\n"\ +"instead of service UUID\n\n" \ +"\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \ +"\tKnown service names\n" \ +"\t===================\n" \ +"\tCIP - Common ISDN Access\n" \ +"\tCTP - Cordless Telephony\n" \ +"\tDUN - DialUp Networking\n" \ +"\tFAX - Fax\n" \ +"\tFTRN - OBEX File Transfer\n" \ +"\tGN - GN\n" \ +"\tHID - Human Interface Device\n" \ +"\tHSET - Headset\n" \ +"\tLAN - LAN Access Using PPP\n" \ +"\tNAP - Network Access Point\n" \ +"\tOPUSH - OBEX Object Push\n" \ +"\tSP - Serial Port\n", +do_sdp_search +}, +{ NULL, NULL, NULL } +}; + |