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 /lib | |
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)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 7 | ||||
-rw-r--r-- | lib/libbluetooth/Makefile | 30 | ||||
-rw-r--r-- | lib/libbluetooth/bluetooth.3 | 293 | ||||
-rw-r--r-- | lib/libbluetooth/bluetooth.c | 369 | ||||
-rw-r--r-- | lib/libbluetooth/bluetooth.h | 78 | ||||
-rw-r--r-- | lib/libsdp/Makefile | 33 | ||||
-rw-r--r-- | lib/libsdp/sdp-int.h | 65 | ||||
-rw-r--r-- | lib/libsdp/sdp.3 | 309 | ||||
-rw-r--r-- | lib/libsdp/sdp.h | 477 | ||||
-rw-r--r-- | lib/libsdp/search.c | 383 | ||||
-rw-r--r-- | lib/libsdp/session.c | 174 | ||||
-rw-r--r-- | lib/libsdp/util.c | 439 |
12 files changed, 2655 insertions, 2 deletions
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; + } + } +} + |