summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
committeremax <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
commit41bb0e8fd2568243020852e22a6d176bccfa60cd (patch)
tree0ae0c2be63f9f9161693789721b96beb9cabcc77 /lib
parent66feac7937e372f502539e7d443aee80a25abe16 (diff)
downloadFreeBSD-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/Makefile7
-rw-r--r--lib/libbluetooth/Makefile30
-rw-r--r--lib/libbluetooth/bluetooth.3293
-rw-r--r--lib/libbluetooth/bluetooth.c369
-rw-r--r--lib/libbluetooth/bluetooth.h78
-rw-r--r--lib/libsdp/Makefile33
-rw-r--r--lib/libsdp/sdp-int.h65
-rw-r--r--lib/libsdp/sdp.3309
-rw-r--r--lib/libsdp/sdp.h477
-rw-r--r--lib/libsdp/search.c383
-rw-r--r--lib/libsdp/session.c174
-rw-r--r--lib/libsdp/util.c439
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;
+ }
+ }
+}
+
OpenPOWER on IntegriCloud