summaryrefslogtreecommitdiffstats
path: root/network/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'network/common.c')
-rw-r--r--network/common.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/network/common.c b/network/common.c
index 8e5043cc..1649eb70 100644
--- a/network/common.c
+++ b/network/common.c
@@ -25,4 +25,150 @@
#include <config.h>
#endif
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/bnep.h>
+
+#include "logging.h"
#include "common.h"
+
+static int ctl;
+
+/* Compatibility with old ioctls */
+#define OLD_BNEPCONADD 1
+#define OLD_BNEPCONDEL 2
+#define OLD_BNEPGETCONLIST 3
+#define OLD_BNEPGETCONINFO 4
+
+static unsigned long bnepconnadd;
+static unsigned long bnepconndel;
+static unsigned long bnepgetconnlist;
+static unsigned long bnepgetconninfo;
+
+static struct {
+ char *str;
+ uint16_t uuid;
+} __svc[] = {
+ { "PANU", BNEP_SVC_PANU },
+ { "NAP", BNEP_SVC_NAP },
+ { "GN", BNEP_SVC_GN },
+ { NULL }
+};
+
+int bnep_str2svc(char *svc, uint16_t *uuid)
+{
+ int i;
+ for (i = 0; __svc[i].str; i++)
+ if (!strcasecmp(svc, __svc[i].str)) {
+ *uuid = __svc[i].uuid;
+ return 0;
+ }
+ return -1;
+}
+
+char *bnep_svc2str(uint16_t uuid)
+{
+ int i;
+ for (i = 0; __svc[i].str; i++)
+ if (__svc[i].uuid == uuid)
+ return __svc[i].str;
+ return NULL;
+}
+
+int bnep_init(void)
+{
+ ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
+ if (ctl < 0) {
+ error("Failed to open control socket");
+ return 1;
+ }
+
+ /* Temporary ioctl compatibility hack */
+ {
+ struct bnep_connlist_req req;
+ struct bnep_conninfo ci[1];
+
+ req.cnum = 1;
+ req.ci = ci;
+
+ if (!ioctl(ctl, BNEPGETCONNLIST, &req)) {
+ /* New ioctls */
+ bnepconnadd = BNEPCONNADD;
+ bnepconndel = BNEPCONNDEL;
+ bnepgetconnlist = BNEPGETCONNLIST;
+ bnepgetconninfo = BNEPGETCONNINFO;
+ } else {
+ /* Old ioctls */
+ bnepconnadd = OLD_BNEPCONADD;
+ bnepconndel = OLD_BNEPCONDEL;
+ bnepgetconnlist = OLD_BNEPGETCONLIST;
+ bnepgetconninfo = OLD_BNEPGETCONINFO;
+ }
+ }
+
+ return 0;
+}
+
+int bnep_cleanup(void)
+{
+ close(ctl);
+ return 0;
+}
+
+int bnep_kill_connection(const char *addr)
+{
+ struct bnep_conndel_req req;
+ uint8_t *dst = (void *) strtoba(addr);
+
+ memcpy(req.dst, dst, ETH_ALEN);
+ req.flags = 0;
+ if (ioctl(ctl, bnepconndel, &req)) {
+ error("Failed to kill connection");
+ return -1;
+ }
+ return 0;
+}
+
+int bnep_kill_all_connections(void)
+{
+ struct bnep_connlist_req req;
+ struct bnep_conninfo ci[48];
+ int i;
+
+ req.cnum = 48;
+ req.ci = ci;
+ if (ioctl(ctl, bnepgetconnlist, &req)) {
+ error("Failed to get connection list");
+ return -1;
+ }
+
+ for (i=0; i < req.cnum; i++) {
+ struct bnep_conndel_req req;
+ memcpy(req.dst, ci[i].dst, ETH_ALEN);
+ req.flags = 0;
+ ioctl(ctl, bnepconndel, &req);
+ }
+ return 0;
+}
+
+int bnep_connadd(int sk, uint16_t role, char *dev)
+{
+ struct bnep_connadd_req req;
+
+ strncpy(req.device, dev, 16);
+ req.device[15] = '\0';
+ req.sock = sk;
+ req.role = role;
+ if (ioctl(ctl, bnepconnadd, &req)) {
+ error("Failed to add device %s", dev);
+ return -1;
+ }
+ strncpy(dev, req.device, 16);
+ return 0;
+}