summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorplunky <plunky@NetBSD.org>2007-04-21 06:15:22 +0000
committerplunky <plunky@NetBSD.org>2007-04-21 06:15:22 +0000
commitf5db72e7b75e66bff8fd02536e16c714f586d6a3 (patch)
treeda2c5f808b067b36ddaac23b9d44090f993f0673 /sys/dev
parentc4ec0fc4f86bef89641b9da211a0db43ed55abbf (diff)
Add 'service level' security for L2CAP and RFCOMM connections, following
the Linux (BlueZ) API. - L2CAP or RFCOMM connections can require the baseband radio link mode be any of: authenticated (devices are paired) encrypted (implies authentication) secured (encryption, plus generate new link key) - for sockets, the mode is set using setsockopt(2) and the socket connection will be aborted if the mode change fails. - mode settings will be applied during connection establishment, and for safety, we enter a wait state and will only proceed when the mode settings are successfuly set. - It is possible to change the mode on already open connections, but not possible to guarantee that data already queued (from either end) will not be delivered. (this is a feature, not a bug) - bthidev(4) and rfcomm_sppd(1) support "auth", "encrypt" and "secure" options - btdevctl(8) by default enables "auth" for HIDs, and "encrypt" for keyboards (which are required to support it)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/bluetooth/btdev.h6
-rw-r--r--sys/dev/bluetooth/bthidev.c62
-rw-r--r--sys/dev/bluetooth/btsco.c14
3 files changed, 77 insertions, 5 deletions
diff --git a/sys/dev/bluetooth/btdev.h b/sys/dev/bluetooth/btdev.h
index c0b6bdac4f4..bd9e0551db2 100644
--- a/sys/dev/bluetooth/btdev.h
+++ b/sys/dev/bluetooth/btdev.h
@@ -1,4 +1,4 @@
-/* $NetBSD: btdev.h,v 1.5 2006/10/04 19:23:59 plunky Exp $ */
+/* $NetBSD: btdev.h,v 1.6 2007/04/21 06:15:22 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -43,6 +43,10 @@
#define BTDEVladdr "local-bdaddr"
#define BTDEVraddr "remote-bdaddr"
#define BTDEVservice "service-name"
+#define BTDEVmode "link-mode"
+#define BTDEVauth "auth"
+#define BTDEVencrypt "encrypt"
+#define BTDEVsecure "secure"
#ifdef _KERNEL
struct btdev {
diff --git a/sys/dev/bluetooth/bthidev.c b/sys/dev/bluetooth/bthidev.c
index 2d1f6358026..85fdef68e68 100644
--- a/sys/dev/bluetooth/bthidev.c
+++ b/sys/dev/bluetooth/bthidev.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bthidev.c,v 1.7 2006/11/16 01:32:48 christos Exp $ */
+/* $NetBSD: bthidev.c,v 1.8 2007/04/21 06:15:22 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.7 2006/11/16 01:32:48 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bthidev.c,v 1.8 2007/04/21 06:15:22 plunky Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -72,6 +72,7 @@ struct bthidev_softc {
bdaddr_t sc_laddr; /* local address */
bdaddr_t sc_raddr; /* remote address */
+ int sc_mode; /* link mode */
uint16_t sc_ctlpsm; /* control PSM */
struct l2cap_channel *sc_ctl; /* control channel */
@@ -125,6 +126,7 @@ static void bthidev_int_disconnected(void *, int);
static void *bthidev_ctl_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
static void *bthidev_int_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
static void bthidev_complete(void *, int);
+static void bthidev_linkmode(void *, int);
static void bthidev_input(void *, struct mbuf *);
static const struct btproto bthidev_ctl_proto = {
@@ -133,6 +135,7 @@ static const struct btproto bthidev_ctl_proto = {
bthidev_ctl_disconnected,
bthidev_ctl_newconn,
bthidev_complete,
+ bthidev_linkmode,
bthidev_input,
};
@@ -142,6 +145,7 @@ static const struct btproto bthidev_int_proto = {
bthidev_int_disconnected,
bthidev_int_newconn,
bthidev_complete,
+ bthidev_linkmode,
bthidev_input,
};
@@ -198,6 +202,23 @@ bthidev_attach(struct device *parent, struct device *self, void *aux)
obj = prop_dictionary_get(dict, BTDEVraddr);
bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));
+ obj = prop_dictionary_get(dict, BTDEVmode);
+ if (prop_object_type(obj) == PROP_TYPE_STRING) {
+ if (prop_string_equals_cstring(obj, BTDEVauth))
+ sc->sc_mode = L2CAP_LM_AUTH;
+ else if (prop_string_equals_cstring(obj, BTDEVencrypt))
+ sc->sc_mode = L2CAP_LM_ENCRYPT;
+ else if (prop_string_equals_cstring(obj, BTDEVsecure))
+ sc->sc_mode = L2CAP_LM_SECURE;
+ else {
+ aprint_error(" unknown %s\n", BTDEVmode);
+ return;
+ }
+
+ aprint_verbose(" %s %s", BTDEVmode,
+ prop_string_cstring_nocopy(obj));
+ }
+
obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm);
if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
sc->sc_ctlpsm = prop_number_integer_value(obj);
@@ -435,6 +456,10 @@ bthidev_listen(struct bthidev_softc *sc)
if (err)
return err;
+ err = l2cap_setopt(sc->sc_ctl_l, SO_L2CAP_LM, &sc->sc_mode);
+ if (err)
+ return err;
+
sa.bt_psm = sc->sc_ctlpsm;
err = l2cap_bind(sc->sc_ctl_l, &sa);
if (err)
@@ -451,6 +476,10 @@ bthidev_listen(struct bthidev_softc *sc)
if (err)
return err;
+ err = l2cap_setopt(sc->sc_int_l, SO_L2CAP_LM, &sc->sc_mode);
+ if (err)
+ return err;
+
sa.bt_psm = sc->sc_intpsm;
err = l2cap_bind(sc->sc_int_l, &sa);
if (err)
@@ -488,6 +517,10 @@ bthidev_connect(struct bthidev_softc *sc)
return err;
}
+ err = l2cap_setopt(sc->sc_ctl, SO_L2CAP_LM, &sc->sc_mode);
+ if (err)
+ return err;
+
bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
err = l2cap_bind(sc->sc_ctl, &sa);
if (err) {
@@ -543,6 +576,10 @@ bthidev_ctl_connected(void *arg)
if (err)
goto fail;
+ err = l2cap_setopt(sc->sc_int, SO_L2CAP_LM, &sc->sc_mode);
+ if (err)
+ goto fail;
+
memset(&sa, 0, sizeof(sa));
sa.bt_len = sizeof(sa);
sa.bt_family = AF_BLUETOOTH;
@@ -707,6 +744,27 @@ bthidev_complete(void *arg, int count)
/* dont care */
}
+static void
+bthidev_linkmode(void *arg, int new)
+{
+ struct bthidev_softc *sc = arg;
+
+ if ((sc->sc_mode & L2CAP_LM_AUTH) && !(new & L2CAP_LM_AUTH))
+ printf("%s: auth failed\n", device_xname((struct device *)sc));
+ else if ((sc->sc_mode & L2CAP_LM_ENCRYPT) && !(new & L2CAP_LM_ENCRYPT))
+ printf("%s: encrypt off\n", device_xname((struct device *)sc));
+ else if ((sc->sc_mode & L2CAP_LM_SECURE) && !(new & L2CAP_LM_SECURE))
+ printf("%s: insecure\n", device_xname((struct device *)sc));
+ else
+ return;
+
+ if (sc->sc_int != NULL)
+ l2cap_disconnect(sc->sc_int, 0);
+
+ if (sc->sc_ctl != NULL)
+ l2cap_disconnect(sc->sc_ctl, 0);
+}
+
/*
* Receive reports from the protocol stack.
*/
diff --git a/sys/dev/bluetooth/btsco.c b/sys/dev/bluetooth/btsco.c
index d82173197c2..95d63cfee0f 100644
--- a/sys/dev/bluetooth/btsco.c
+++ b/sys/dev/bluetooth/btsco.c
@@ -1,4 +1,4 @@
-/* $NetBSD: btsco.c,v 1.13 2007/03/13 19:26:06 plunky Exp $ */
+/* $NetBSD: btsco.c,v 1.14 2007/04/21 06:15:22 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.13 2007/03/13 19:26:06 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.14 2007/04/21 06:15:22 plunky Exp $");
#include <sys/param.h>
#include <sys/audioio.h>
@@ -215,6 +215,7 @@ static void btsco_sco_connected(void *);
static void btsco_sco_disconnected(void *, int);
static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
static void btsco_sco_complete(void *, int);
+static void btsco_sco_linkmode(void *, int);
static void btsco_sco_input(void *, struct mbuf *);
static const struct btproto btsco_sco_proto = {
@@ -223,6 +224,7 @@ static const struct btproto btsco_sco_proto = {
btsco_sco_disconnected,
btsco_sco_newconn,
btsco_sco_complete,
+ btsco_sco_linkmode,
btsco_sco_input,
};
@@ -502,6 +504,14 @@ btsco_sco_complete(void *arg, int count)
}
static void
+btsco_sco_linkmode(void *arg, int new)
+{
+/* struct btsco_softc *sc = arg; */
+
+ /* dont care */
+}
+
+static void
btsco_sco_input(void *arg, struct mbuf *m)
{
struct btsco_softc *sc = arg;