svn commit: r187938 - head/usr.sbin/bluetooth/btpand
Maksim Yevmenkin
emax at FreeBSD.org
Fri Jan 30 14:23:22 PST 2009
Author: emax
Date: Fri Jan 30 22:23:21 2009
New Revision: 187938
URL: http://svn.freebsd.org/changeset/base/187938
Log:
Add btpand(8) daemon from NetBSD. This daemon provides support for
Bluetooth Network Access Point (NAP), Group Ad-hoc Network (GN) and
Personal Area Network User (PANU) profiles.
Obtained from: NetBSD
MFC after: 1 month
Added:
head/usr.sbin/bluetooth/btpand/
head/usr.sbin/bluetooth/btpand/Makefile (contents, props changed)
head/usr.sbin/bluetooth/btpand/bnep.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/bnep.h (contents, props changed)
head/usr.sbin/bluetooth/btpand/btpand.8 (contents, props changed)
head/usr.sbin/bluetooth/btpand/btpand.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/btpand.h (contents, props changed)
head/usr.sbin/bluetooth/btpand/channel.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/client.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/event.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/event.h (contents, props changed)
head/usr.sbin/bluetooth/btpand/packet.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/sdp.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/sdp.h (contents, props changed)
head/usr.sbin/bluetooth/btpand/server.c (contents, props changed)
head/usr.sbin/bluetooth/btpand/tap.c (contents, props changed)
Added: head/usr.sbin/bluetooth/btpand/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/bluetooth/btpand/Makefile Fri Jan 30 22:23:21 2009 (r187938)
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.2 2008/08/18 08:25:32 plunky Exp $
+# $FreeBSD$
+
+PROG= btpand
+MAN= btpand.8
+SRCS= btpand.c bnep.c channel.c client.c event.c packet.c server.c sdp.c tap.c
+
+WARNS?= 3
+
+DPADD+= ${LIBBLUETOOTH} ${LIBSDP} ${LIBUTIL}
+LDADD+= -lbluetooth -lsdp -lutil
+
+.include <bsd.prog.mk>
Added: head/usr.sbin/bluetooth/btpand/bnep.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/bluetooth/btpand/bnep.c Fri Jan 30 22:23:21 2009 (r187938)
@@ -0,0 +1,755 @@
+/* $NetBSD: bnep.c,v 1.1 2008/08/17 13:20:57 plunky Exp $ */
+
+/*-
+ * Copyright (c) 2008 Iain Hibbert
+ * 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 ``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 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.
+ */
+
+/* $FreeBSD$ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: bnep.c,v 1.1 2008/08/17 13:20:57 plunky Exp $");
+
+#include <sys/uio.h>
+#include <bluetooth.h>
+#include <sdp.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "btpand.h"
+#include "bnep.h"
+
+static bool bnep_recv_extension(packet_t *);
+static size_t bnep_recv_control(channel_t *, uint8_t *, size_t, bool);
+static size_t bnep_recv_control_command_not_understood(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_setup_connection_req(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_setup_connection_rsp(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_filter_net_type_set(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_filter_net_type_rsp(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_filter_multi_addr_set(channel_t *, uint8_t *, size_t);
+static size_t bnep_recv_filter_multi_addr_rsp(channel_t *, uint8_t *, size_t);
+
+static bool bnep_pfilter(channel_t *, packet_t *);
+static bool bnep_mfilter(channel_t *, packet_t *);
+
+static uint8_t NAP_UUID[] = {
+ 0x00, 0x00, 0x11, 0x16,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
+static uint8_t GN_UUID[] = {
+ 0x00, 0x00, 0x11, 0x17,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb,
+};
+
+static uint8_t PANU_UUID[] = {
+ 0x00, 0x00, 0x11, 0x15,
+ 0x00, 0x00,
+ 0x10, 0x00,
+ 0x80, 0x00,
+ 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
+/*
+ * receive BNEP packet
+ * return true if packet is to be forwarded
+ */
+bool
+bnep_recv(packet_t *pkt)
+{
+ size_t len;
+ uint8_t type;
+
+ if (pkt->len < 1)
+ return false;
+
+ type = pkt->ptr[0];
+ packet_adj(pkt, 1);
+
+ switch (BNEP_TYPE(type)) {
+ case BNEP_GENERAL_ETHERNET:
+ if (pkt->len < (ETHER_ADDR_LEN * 2) + ETHER_TYPE_LEN) {
+ log_debug("dropped short packet (type 0x%2.2x)", type);
+ return false;
+ }
+
+ pkt->dst = pkt->ptr;
+ packet_adj(pkt, ETHER_ADDR_LEN);
+ pkt->src = pkt->ptr;
+ packet_adj(pkt, ETHER_ADDR_LEN);
+ pkt->type = pkt->ptr;
+ packet_adj(pkt, ETHER_TYPE_LEN);
+ break;
+
+ case BNEP_CONTROL:
+ len = bnep_recv_control(pkt->chan, pkt->ptr, pkt->len, false);
+ if (len == 0)
+ return false;
+
+ packet_adj(pkt, len);
+ break;
+
+ case BNEP_COMPRESSED_ETHERNET:
+ if (pkt->len < ETHER_TYPE_LEN) {
+ log_debug("dropped short packet (type 0x%2.2x)", type);
+ return false;
+ }
+
+ pkt->dst = pkt->chan->laddr;
+ pkt->src = pkt->chan->raddr;
+ pkt->type = pkt->ptr;
+ packet_adj(pkt, ETHER_TYPE_LEN);
+ break;
+
+ case BNEP_COMPRESSED_ETHERNET_SRC_ONLY:
+ if (pkt->len < ETHER_ADDR_LEN + ETHER_TYPE_LEN) {
+ log_debug("dropped short packet (type 0x%2.2x)", type);
+ return false;
+ }
+
+ pkt->dst = pkt->chan->laddr;
+ pkt->src = pkt->ptr;
+ packet_adj(pkt, ETHER_ADDR_LEN);
+ pkt->type = pkt->ptr;
+ packet_adj(pkt, ETHER_TYPE_LEN);
+ break;
+
+ case BNEP_COMPRESSED_ETHERNET_DST_ONLY:
+ if (pkt->len < ETHER_ADDR_LEN + ETHER_TYPE_LEN) {
+ log_debug("dropped short packet (type 0x%2.2x)", type);
+ return false;
+ }
+
+ pkt->dst = pkt->ptr;
+ packet_adj(pkt, ETHER_ADDR_LEN);
+ pkt->src = pkt->chan->raddr;
+ pkt->type = pkt->ptr;
+ packet_adj(pkt, ETHER_TYPE_LEN);
+ break;
+
+ default:
+ /*
+ * Any packet containing a reserved BNEP
+ * header packet type SHALL be dropped.
+ */
+
+ log_debug("dropped packet with reserved type 0x%2.2x", type);
+ return false;
+ }
+
+ if (BNEP_TYPE_EXT(type)
+ && !bnep_recv_extension(pkt))
+ return false; /* invalid extensions */
+
+ if (BNEP_TYPE(type) == BNEP_CONTROL
+ || pkt->chan->state != CHANNEL_OPEN)
+ return false; /* no forwarding */
+
+ return true;
+}
+
+static bool
+bnep_recv_extension(packet_t *pkt)
+{
+ exthdr_t *eh;
+ size_t len, size;
+ uint8_t type;
+
+ do {
+ if (pkt->len < 2)
+ return false;
+
+ type = pkt->ptr[0];
+ size = pkt->ptr[1];
+
+ if (pkt->len < size + 2)
+ return false;
+
+ switch (type) {
+ case BNEP_EXTENSION_CONTROL:
+ len = bnep_recv_control(pkt->chan, pkt->ptr + 2, size, true);
+ if (len != size)
+ log_err("ignored spurious data in exthdr");
+
+ break;
+
+ default:
+ /* Unknown extension headers in data packets */
+ /* SHALL be forwarded irrespective of any */
+ /* network protocol or multicast filter settings */
+ /* and any local filtering policy. */
+
+ eh = malloc(sizeof(exthdr_t));
+ if (eh == NULL) {
+ log_err("exthdr malloc() failed: %m");
+ break;
+ }
+
+ eh->ptr = pkt->ptr;
+ eh->len = size;
+ STAILQ_INSERT_TAIL(&pkt->extlist, eh, next);
+ break;
+ }
+
+ packet_adj(pkt, size + 2);
+ } while (BNEP_TYPE_EXT(type));
+
+ return true;
+}
+
+static size_t
+bnep_recv_control(channel_t *chan, uint8_t *ptr, size_t size, bool isext)
+{
+ uint8_t type;
+ size_t len;
+
+ if (size-- < 1)
+ return 0;
+
+ type = *ptr++;
+
+ switch (type) {
+ case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD:
+ len = bnep_recv_control_command_not_understood(chan, ptr, size);
+ break;
+
+ case BNEP_SETUP_CONNECTION_REQUEST:
+ if (isext)
+ return 0; /* not allowed in extension headers */
+
+ len = bnep_recv_setup_connection_req(chan, ptr, size);
+ break;
+
+ case BNEP_SETUP_CONNECTION_RESPONSE:
+ if (isext)
+ return 0; /* not allowed in extension headers */
+
+ len = bnep_recv_setup_connection_rsp(chan, ptr, size);
+ break;
+
+ case BNEP_FILTER_NET_TYPE_SET:
+ len = bnep_recv_filter_net_type_set(chan, ptr, size);
+ break;
+
+ case BNEP_FILTER_NET_TYPE_RESPONSE:
+ len = bnep_recv_filter_net_type_rsp(chan, ptr, size);
+ break;
+
+ case BNEP_FILTER_MULTI_ADDR_SET:
+ len = bnep_recv_filter_multi_addr_set(chan, ptr, size);
+ break;
+
+ case BNEP_FILTER_MULTI_ADDR_RESPONSE:
+ len = bnep_recv_filter_multi_addr_rsp(chan, ptr, size);
+ break;
+
+ default:
+ len = 0;
+ break;
+ }
+
+ if (len == 0)
+ bnep_send_control(chan, BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD, type);
+
+ return len;
+}
+
+static size_t
+bnep_recv_control_command_not_understood(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ uint8_t type;
+
+ if (size < 1)
+ return 0;
+
+ type = *ptr++;
+ log_err("received Control Command Not Understood (0x%2.2x)", type);
+
+ /* we didn't send any reserved commands, just cut them off */
+ channel_close(chan);
+
+ return 1;
+}
+
+static size_t
+bnep_recv_setup_connection_req(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ uint8_t off;
+ int src, dst, rsp;
+ size_t len;
+
+ if (size < 1)
+ return 0;
+
+ len = *ptr++;
+ if (size < (len * 2 + 1))
+ return 0;
+
+ if (chan->state != CHANNEL_WAIT_CONNECT_REQ
+ && chan->state != CHANNEL_OPEN) {
+ log_debug("ignored");
+ return (len * 2 + 1);
+ }
+
+ if (len == 2)
+ off = 2;
+ else if (len == 4)
+ off = 0;
+ else if (len == 16)
+ off = 0;
+ else {
+ rsp = BNEP_SETUP_INVALID_UUID_SIZE;
+ goto done;
+ }
+
+ if (memcmp(ptr, NAP_UUID + off, len) == 0)
+ dst = SDP_SERVICE_CLASS_NAP;
+ else if (memcmp(ptr, GN_UUID + off, len) == 0)
+ dst = SDP_SERVICE_CLASS_GN;
+ else if (memcmp(ptr, PANU_UUID + off, len) == 0)
+ dst = SDP_SERVICE_CLASS_PANU;
+ else
+ dst = 0;
+
+ if (dst != service_class) {
+ rsp = BNEP_SETUP_INVALID_DST_UUID;
+ goto done;
+ }
+
+ ptr += len;
+
+ if (memcmp(ptr, NAP_UUID + off, len) == 0)
+ src = SDP_SERVICE_CLASS_NAP;
+ else if (memcmp(ptr, GN_UUID + off, len) == 0)
+ src = SDP_SERVICE_CLASS_GN;
+ else if (memcmp(ptr, PANU_UUID + off, len) == 0)
+ src = SDP_SERVICE_CLASS_PANU;
+ else
+ src = 0;
+
+ if ((dst != SDP_SERVICE_CLASS_PANU && src != SDP_SERVICE_CLASS_PANU)
+ || src == 0) {
+ rsp = BNEP_SETUP_INVALID_SRC_UUID;
+ goto done;
+ }
+
+ rsp = BNEP_SETUP_SUCCESS;
+ chan->state = CHANNEL_OPEN;
+ channel_timeout(chan, 0);
+
+done:
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ bnep_send_control(chan, BNEP_SETUP_CONNECTION_RESPONSE, rsp);
+ return (len * 2 + 1);
+}
+
+static size_t
+bnep_recv_setup_connection_rsp(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ int rsp;
+
+ if (size < 2)
+ return 0;
+
+ rsp = be16dec(ptr);
+
+ if (chan->state != CHANNEL_WAIT_CONNECT_RSP) {
+ log_debug("ignored");
+ return 2;
+ }
+
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ if (rsp == BNEP_SETUP_SUCCESS) {
+ chan->state = CHANNEL_OPEN;
+ channel_timeout(chan, 0);
+ } else {
+ channel_close(chan);
+ }
+
+ return 2;
+}
+
+static size_t
+bnep_recv_filter_net_type_set(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ pfilter_t *pf;
+ int i, nf, rsp;
+ size_t len;
+
+ if (size < 2)
+ return 0;
+
+ len = be16dec(ptr);
+ ptr += 2;
+
+ if (size < (len + 2))
+ return 0;
+
+ if (chan->state != CHANNEL_OPEN) {
+ log_debug("ignored");
+ return (len + 2);
+ }
+
+ nf = len / 4;
+ pf = malloc(nf * sizeof(pfilter_t));
+ if (pf == NULL) {
+ rsp = BNEP_FILTER_TOO_MANY_FILTERS;
+ goto done;
+ }
+
+ log_debug("nf = %d", nf);
+
+ for (i = 0; i < nf; i++) {
+ pf[i].start = be16dec(ptr);
+ ptr += 2;
+ pf[i].end = be16dec(ptr);
+ ptr += 2;
+
+ if (pf[i].start > pf[i].end) {
+ free(pf);
+ rsp = BNEP_FILTER_INVALID_RANGE;
+ goto done;
+ }
+
+ log_debug("pf[%d] = %#4.4x, %#4.4x", i, pf[i].start, pf[i].end);
+ }
+
+ if (chan->pfilter)
+ free(chan->pfilter);
+
+ chan->pfilter = pf;
+ chan->npfilter = nf;
+
+ rsp = BNEP_FILTER_SUCCESS;
+
+done:
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ bnep_send_control(chan, BNEP_FILTER_NET_TYPE_RESPONSE, rsp);
+ return (len + 2);
+}
+
+static size_t
+bnep_recv_filter_net_type_rsp(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ int rsp;
+
+ if (size < 2)
+ return 0;
+
+ if (chan->state != CHANNEL_OPEN) {
+ log_debug("ignored");
+ return 2;
+ }
+
+ rsp = be16dec(ptr);
+
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ /* we did not send any filter_net_type_set message */
+ return 2;
+}
+
+static size_t
+bnep_recv_filter_multi_addr_set(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ mfilter_t *mf;
+ int i, nf, rsp;
+ size_t len;
+
+ if (size < 2)
+ return 0;
+
+ len = be16dec(ptr);
+ ptr += 2;
+
+ if (size < (len + 2))
+ return 0;
+
+ if (chan->state != CHANNEL_OPEN) {
+ log_debug("ignored");
+ return (len + 2);
+ }
+
+ nf = len / (ETHER_ADDR_LEN * 2);
+ mf = malloc(nf * sizeof(mfilter_t));
+ if (mf == NULL) {
+ rsp = BNEP_FILTER_TOO_MANY_FILTERS;
+ goto done;
+ }
+
+ log_debug("nf = %d", nf);
+
+ for (i = 0; i < nf; i++) {
+ memcpy(mf[i].start, ptr, ETHER_ADDR_LEN);
+ ptr += ETHER_ADDR_LEN;
+
+ memcpy(mf[i].end, ptr, ETHER_ADDR_LEN);
+ ptr += ETHER_ADDR_LEN;
+
+ if (memcmp(mf[i].start, mf[i].end, ETHER_ADDR_LEN) > 0) {
+ free(mf);
+ rsp = BNEP_FILTER_INVALID_RANGE;
+ goto done;
+ }
+
+ log_debug("pf[%d] = "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", i,
+ mf[i].start[0], mf[i].start[1], mf[i].start[2],
+ mf[i].start[3], mf[i].start[4], mf[i].start[5],
+ mf[i].end[0], mf[i].end[1], mf[i].end[2],
+ mf[i].end[3], mf[i].end[4], mf[i].end[5]);
+ }
+
+ if (chan->mfilter)
+ free(chan->mfilter);
+
+ chan->mfilter = mf;
+ chan->nmfilter = nf;
+
+ rsp = BNEP_FILTER_SUCCESS;
+
+done:
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ bnep_send_control(chan, BNEP_FILTER_MULTI_ADDR_RESPONSE, rsp);
+ return (len + 2);
+}
+
+static size_t
+bnep_recv_filter_multi_addr_rsp(channel_t *chan, uint8_t *ptr, size_t size)
+{
+ int rsp;
+
+ if (size < 2)
+ return false;
+
+ if (chan->state != CHANNEL_OPEN) {
+ log_debug("ignored");
+ return 2;
+ }
+
+ rsp = be16dec(ptr);
+ log_debug("addr %s response 0x%2.2x",
+ ether_ntoa((struct ether_addr *)chan->raddr), rsp);
+
+ /* we did not send any filter_multi_addr_set message */
+ return 2;
+}
+
+void
+bnep_send_control(channel_t *chan, uint8_t type, ...)
+{
+ packet_t *pkt;
+ uint8_t *p;
+ va_list ap;
+
+ assert(chan->state != CHANNEL_CLOSED);
+
+ pkt = packet_alloc(chan);
+ if (pkt == NULL)
+ return;
+
+ p = pkt->ptr;
+ va_start(ap, type);
+
+ *p++ = BNEP_CONTROL;
+ *p++ = type;
+
+ switch(type) {
+ case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD:
+ *p++ = va_arg(ap, int);
+ break;
+
+ case BNEP_SETUP_CONNECTION_REQUEST:
+ *p++ = va_arg(ap, int);
+ be16enc(p, va_arg(ap, int));
+ p += 2;
+ be16enc(p, va_arg(ap, int));
+ p += 2;
+ break;
+
+ case BNEP_SETUP_CONNECTION_RESPONSE:
+ case BNEP_FILTER_NET_TYPE_RESPONSE:
+ case BNEP_FILTER_MULTI_ADDR_RESPONSE:
+ be16enc(p, va_arg(ap, int));
+ p += 2;
+ break;
+
+ case BNEP_FILTER_NET_TYPE_SET: /* TODO */
+ case BNEP_FILTER_MULTI_ADDR_SET: /* TODO */
+ default:
+ log_err("Can't send control type 0x%2.2x", type);
+ break;
+ }
+
+ va_end(ap);
+ pkt->len = p - pkt->ptr;
+
+ channel_put(chan, pkt);
+ packet_free(pkt);
+}
+
+/*
+ * BNEP send packet routine
+ * return true if packet can be removed from queue
+ */
+bool
+bnep_send(channel_t *chan, packet_t *pkt)
+{
+ struct iovec iov[2];
+ uint8_t *p, *type, *proto;
+ exthdr_t *eh;
+ bool src, dst;
+ size_t nw;
+
+ if (pkt->type == NULL) {
+ iov[0].iov_base = pkt->ptr;
+ iov[0].iov_len = pkt->len;
+ iov[1].iov_base = NULL;
+ iov[1].iov_len = 0;
+ } else {
+ p = chan->sendbuf;
+
+ dst = (memcmp(pkt->dst, chan->raddr, ETHER_ADDR_LEN) != 0);
+ src = (memcmp(pkt->src, chan->laddr, ETHER_ADDR_LEN) != 0);
+
+ type = p;
+ p += 1;
+
+ if (dst && src)
+ *type = BNEP_GENERAL_ETHERNET;
+ else if (dst && !src)
+ *type = BNEP_COMPRESSED_ETHERNET_DST_ONLY;
+ else if (!dst && src)
+ *type = BNEP_COMPRESSED_ETHERNET_SRC_ONLY;
+ else /* (!dst && !src) */
+ *type = BNEP_COMPRESSED_ETHERNET;
+
+ if (dst) {
+ memcpy(p, pkt->dst, ETHER_ADDR_LEN);
+ p += ETHER_ADDR_LEN;
+ }
+
+ if (src) {
+ memcpy(p, pkt->src, ETHER_ADDR_LEN);
+ p += ETHER_ADDR_LEN;
+ }
+
+ proto = p;
+ memcpy(p, pkt->type, ETHER_TYPE_LEN);
+ p += ETHER_TYPE_LEN;
+
+ STAILQ_FOREACH(eh, &pkt->extlist, next) {
+ if (p + eh->len > chan->sendbuf + chan->mtu)
+ break;
+
+ *type |= BNEP_EXT;
+ type = p;
+
+ memcpy(p, eh->ptr, eh->len);
+ p += eh->len;
+ }
+
+ *type &= ~BNEP_EXT;
+
+ iov[0].iov_base = chan->sendbuf;
+ iov[0].iov_len = (p - chan->sendbuf);
+
+ if ((chan->npfilter == 0 || bnep_pfilter(chan, pkt))
+ && (chan->nmfilter == 0 || bnep_mfilter(chan, pkt))) {
+ iov[1].iov_base = pkt->ptr;
+ iov[1].iov_len = pkt->len;
+ } else if (be16dec(proto) == ETHERTYPE_VLAN
+ && pkt->len >= ETHER_VLAN_ENCAP_LEN) {
+ iov[1].iov_base = pkt->ptr;
+ iov[1].iov_len = ETHER_VLAN_ENCAP_LEN;
+ } else {
+ iov[1].iov_base = NULL;
+ iov[1].iov_len = 0;
+ memset(proto, 0, ETHER_TYPE_LEN);
+ }
+ }
+
+ if (iov[0].iov_len + iov[1].iov_len > chan->mtu) {
+ log_err("packet exceeded MTU (dropped)");
+ return false;
+ }
+
+ nw = writev(chan->fd, iov, __arraycount(iov));
+ return (nw > 0);
+}
+
+static bool
+bnep_pfilter(channel_t *chan, packet_t *pkt)
+{
+ int proto, i;
+
+ proto = be16dec(pkt->type);
+ if (proto == ETHERTYPE_VLAN) { /* IEEE 802.1Q tag header */
+ if (pkt->len < 4)
+ return false;
+
+ proto = be16dec(pkt->ptr + 2);
+ }
+
+ for (i = 0; i < chan->npfilter; i++) {
+ if (chan->pfilter[i].start <= proto
+ && chan->pfilter[i].end >=proto)
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+bnep_mfilter(channel_t *chan, packet_t *pkt)
+{
+ int i;
+
+ if (!ETHER_IS_MULTICAST(pkt->dst))
+ return true;
+
+ for (i = 0; i < chan->nmfilter; i++) {
+ if (memcmp(pkt->dst, chan->mfilter[i].start, ETHER_ADDR_LEN) >= 0
+ && memcmp(pkt->dst, chan->mfilter[i].end, ETHER_ADDR_LEN) <= 0)
+ return true;
+ }
+
+ return false;
+}
Added: head/usr.sbin/bluetooth/btpand/bnep.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/bluetooth/btpand/bnep.h Fri Jan 30 22:23:21 2009 (r187938)
@@ -0,0 +1,72 @@
+/* $NetBSD: bnep.h,v 1.1 2008/08/17 13:20:57 plunky Exp $ */
+
+/*-
+ * Copyright (c) 2008 Iain Hibbert
+ * 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 ``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 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.
+ */
+
+/* $FreeBSD$ */
+
+/*
+ * Constants defined in the Bluetooth Network Encapsulation
+ * Protocol (BNEP) specification v1.0
+ */
+
+#define BNEP_MTU_MIN 1691
+
+#define BNEP_EXT 0x80
+#define BNEP_TYPE(x) ((x) & 0x7f)
+#define BNEP_TYPE_EXT(x) (((x) & BNEP_EXT) == BNEP_EXT)
+
+/* BNEP packet types */
+#define BNEP_GENERAL_ETHERNET 0x00
+#define BNEP_CONTROL 0x01
+#define BNEP_COMPRESSED_ETHERNET 0x02
+#define BNEP_COMPRESSED_ETHERNET_SRC_ONLY 0x03
+#define BNEP_COMPRESSED_ETHERNET_DST_ONLY 0x04
+
+/* BNEP extension header types */
+#define BNEP_EXTENSION_CONTROL 0x00
+
+/* BNEP control types */
+#define BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD 0x00
+#define BNEP_SETUP_CONNECTION_REQUEST 0x01
+#define BNEP_SETUP_CONNECTION_RESPONSE 0x02
+#define BNEP_FILTER_NET_TYPE_SET 0x03
+#define BNEP_FILTER_NET_TYPE_RESPONSE 0x04
+#define BNEP_FILTER_MULTI_ADDR_SET 0x05
+#define BNEP_FILTER_MULTI_ADDR_RESPONSE 0x06
+
+/* BNEP setup response codes */
+#define BNEP_SETUP_SUCCESS 0x0000
+#define BNEP_SETUP_INVALID_SRC_UUID 0x0001
+#define BNEP_SETUP_INVALID_DST_UUID 0x0002
+#define BNEP_SETUP_INVALID_UUID_SIZE 0x0003
+#define BNEP_SETUP_NOT_ALLOWED 0x0004
+
+/* BNEP filter return codes */
+#define BNEP_FILTER_SUCCESS 0x0000
+#define BNEP_FILTER_UNSUPPORTED_REQUEST 0x0001
+#define BNEP_FILTER_INVALID_RANGE 0x0002
+#define BNEP_FILTER_TOO_MANY_FILTERS 0x0003
+#define BNEP_FILTER_SECURITY_FAILURE 0x0004
Added: head/usr.sbin/bluetooth/btpand/btpand.8
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/bluetooth/btpand/btpand.8 Fri Jan 30 22:23:21 2009 (r187938)
@@ -0,0 +1,241 @@
+.\" $NetBSD: btpand.8,v 1.3 2008/08/17 14:43:07 plunky Exp $
+.\" $FreeBSD$
+.\"
+.\" Copyright (c) 2008 Iain Hibbert
+.\" 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 ``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 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.
+.\"
+.Dd August 17, 2008
+.Dt BTPAND 8
+.Os
+.Sh NAME
+.Nm btpand
+.Nd Bluetooth PAN daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl i Ar ifname
+.Op Fl m Ar mode
+.Fl a Ar addr
+.Fl d Ar device
+.Brq Fl s Ar service | Fl S Ar service Op Fl p Ar psm
+.Nm
+.Op Fl c Ar path
+.Op Fl i Ar ifname
+.Op Fl l Ar limit
+.Op Fl m Ar mode
+.Op Fl p Ar psm
+.Fl d Ar device
+.Brq Fl s Ar service | Fl S Ar service
+.Sh DESCRIPTION
+The
+.Nm
+daemon handles Bluetooth Personal Area Networking services
+in the system.
+It can operate in client mode as a Personal Area Networking User
+.Pq PANU
+or in server mode as Network Access Point
+.Pq NAP ,
+Group ad-hoc Network
+.Pq GN
+or PANU host.
+.Nm
+connects to the system via a
+.Xr tap 4
+virtual Ethernet device and forwards Ethernet packets to
+remote Bluetooth devices using the Bluetooth Network Encapsulation
+Protocol
+.Pq BNEP .
+.Pp
+The PANU client is the device that uses either the NAP or GN
+service, or can talk directly to a PANU host in a crossover
+cable fashion.
+.Pp
+A GN host forwards Ethernet packets to each of the connected PAN
+users as needed but does not provide access to any additional networks.
+.Pp
+The NAP service provides some of the features of an Ethernet bridge,
+with the NAP host forwarding Ethernet packets between each of the
+connected PAN users, and a different network
+media.
+.Pp
+Note, the only differences between NAP and GN services as implemented by
+.Nm
+are in the SDP service record.
+The bridging of packets by the NAP must be configured separately.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl a Ar address"
+.It Fl a Ar address
+In client mode, address of remote server.
+May be given as BDADDR or name, in which case
+.Nm
+will attempt to resolve the address via the
+.Xr bt_gethostbyname 3
+call.
+.It Fl c Ar path
+In server mode, specify
+.Ar path
+to the
+.Xr sdpd 8
+control socket.
+The default path is
+.Pa /var/run/sdp .
+.It Fl d Ar device
+Restrict connections to the local
+.Ar device .
+May be given as BDADDR or name, in which case
+.Nm
+will attempt to resolve the address via the
+.Xr bt_devaddr 3
+call.
+.Nm
+will set the
+.Xr tap 4
+interface physical address to the BDADDR
+of the Bluetooth radio.
+.It Fl i Ar ifname
+.Nm
+uses the
+.Xr tap 4
+driver to create a new network interface for use.
+Use this option to select a specific
+.Xr tap 4
+device interface which must already be created.
+.It Fl l Ar limit
+In server mode, limit the number of simultaneous connections.
+The default limit is 7 for NAP and GN servers,
+and 1 for a PANU server.
+.It Fl m Ar mode
+Set L2CAP connection link mode.
+Supported modes are:
+.Pp
+.Bl -tag -compact
+.It auth
+require devices to be paired.
+.It encrypt
+auth, plus enable encryption.
+.It secure
+encryption, plus change of link key.
+.El
+.Pp
+NOT YET SUPPORTED.
+Use global device settings to set authentication and encryption.
+.It Fl p Ar psm
+Use an alternative L2CAP Protocol/Service Multiplexer
+.Pq PSM
+for server mode or client mode
+.Pq when not using Service Discovery .
+The default PSM for BNEP is 15
+.Pq 0x000f .
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list