Repository : ssh://git@open-mesh.org/alfred
On branch : master
>---------------------------------------------------------------
commit 918c077f8b37072d39e34ad5f334ded35bb91fc8
Author: Sven Eckelmann <sven(a)open-mesh.com>
Date: Thu Jan 3 16:25:18 2013 +0100
alfred: Query the tq value for servers from batman-adv
Signed-off-by: Sven Eckelmann <sven(a)open-mesh.com>
>---------------------------------------------------------------
918c077f8b37072d39e34ad5f334ded35bb91fc8
Makefile | 2 +-
batadv_query.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++
util.c => batadv_query.h | 22 ++---
debugfs.c | 158 ++++++++++++++++++++++++++++++++++++
util.c => debugfs.h | 38 +++++----
recv.c | 10 ++-
6 files changed, 399 insertions(+), 32 deletions(-)
diff --git a/Makefile b/Makefile
index 9796528..67ff185 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@
# alfred build
BINARY_NAME = alfred
-OBJ = main.o server.o client.o netsock.o send.o recv.o hash.o unix_sock.o util.o
+OBJ = main.o server.o client.o netsock.o send.o recv.o hash.o unix_sock.o util.o debugfs.o batadv_query.o
# alfred flags and options
CFLAGS += -pedantic -Wall -W -std=gnu99 -fno-strict-aliasing -MD
diff --git a/batadv_query.c b/batadv_query.c
new file mode 100644
index 0000000..e56ad60
--- /dev/null
+++ b/batadv_query.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2012 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "batadv_query.h"
+#include "debugfs.h"
+#include <stdio.h>
+#include <netinet/ether.h>
+#include <stdlib.h>
+
+#define DEBUG_BATIF_PATH_FMT "%s/batman_adv/%s"
+#define DEBUG_TRANSTABLE_GLOBAL "transtable_global"
+#define DEBUG_ORIGINATORS "originators"
+
+struct ether_addr *translate_mac(char *mesh_iface, struct ether_addr *mac)
+{
+ enum {
+ tg_start,
+ tg_mac,
+ tg_via,
+ tg_originator,
+ } pos;
+ char full_path[MAX_PATH+1];
+ char *debugfs_mnt;
+ static struct ether_addr in_mac;
+ struct ether_addr *mac_result, *mac_tmp;
+ FILE *f = NULL;
+ size_t len = 0;
+ char *line = NULL;
+ char *input, *saveptr, *token;
+ int line_invalid;
+
+ memcpy(&in_mac, mac, sizeof(in_mac));
+ mac_result = &in_mac;
+
+ debugfs_mnt = debugfs_mount(NULL);
+ if (!debugfs_mnt)
+ goto out;
+
+ debugfs_make_path(DEBUG_BATIF_PATH_FMT "/" DEBUG_TRANSTABLE_GLOBAL,
+ mesh_iface, full_path, sizeof(full_path));
+
+ f = fopen(full_path, "r");
+ if (!f)
+ goto out;
+
+ while (getline(&line, &len, f) != -1) {
+ line_invalid = 0;
+ pos = tg_start;
+ input = line;
+
+ while ((token = strtok_r(input, " \t", &saveptr))) {
+ input = NULL;
+
+ switch (pos) {
+ case tg_start:
+ if (strcmp(token, "*") != 0)
+ line_invalid = 1;
+ else
+ pos = tg_mac;
+ break;
+ case tg_mac:
+ mac_tmp = ether_aton(token);
+ if (!mac_tmp || memcmp(mac_tmp, &in_mac,
+ sizeof(in_mac)) != 0)
+ line_invalid = 1;
+ else
+ pos = tg_via;
+ break;
+ case tg_via:
+ if (strcmp(token, "via") == 0)
+ pos = tg_originator;
+ break;
+ case tg_originator:
+ mac_tmp = ether_aton(token);
+ if (!mac_tmp) {
+ line_invalid = 1;
+ } else {
+ mac_result = mac_tmp;
+ goto out;
+ }
+ break;
+ }
+
+ if (line_invalid)
+ break;
+ }
+ }
+
+out:
+ if (f)
+ fclose(f);
+ free(line);
+ return mac_result;
+}
+
+uint8_t get_tq(char *mesh_iface, struct ether_addr *mac)
+{
+ enum {
+ orig_mac,
+ orig_lastseen,
+ orig_tqstart,
+ orig_tqvalue,
+ } pos;
+ char full_path[MAX_PATH+1];
+ char *debugfs_mnt;
+ static struct ether_addr in_mac;
+ struct ether_addr *mac_tmp;
+ FILE *f = NULL;
+ size_t len = 0;
+ char *line = NULL;
+ char *input, *saveptr, *token;
+ int line_invalid;
+ uint8_t tq = 0;
+
+ memcpy(&in_mac, mac, sizeof(in_mac));
+
+ debugfs_mnt = debugfs_mount(NULL);
+ if (!debugfs_mnt)
+ goto out;
+
+ debugfs_make_path(DEBUG_BATIF_PATH_FMT "/" DEBUG_ORIGINATORS,
+ mesh_iface, full_path, sizeof(full_path));
+
+ f = fopen(full_path, "r");
+ if (!f)
+ goto out;
+
+ while (getline(&line, &len, f) != -1) {
+ line_invalid = 0;
+ pos = orig_mac;
+ input = line;
+
+ while ((token = strtok_r(input, " \t", &saveptr))) {
+ input = NULL;
+
+ switch (pos) {
+ case orig_mac:
+ mac_tmp = ether_aton(token);
+ if (!mac_tmp || memcmp(mac_tmp, &in_mac,
+ sizeof(in_mac)) != 0)
+ line_invalid = 1;
+ else
+ pos = orig_lastseen;
+ break;
+ case orig_lastseen:
+ pos = orig_tqstart;
+ break;
+ case orig_tqstart:
+ if (strlen(token) == 0) {
+ line_invalid = 1;
+ break;
+ } else if (token[0] != '(') {
+ line_invalid = 1;
+ break;
+ } else if (strlen(token) == 1) {
+ pos = orig_tqvalue;
+ break;
+ } else {
+ /* fall through */
+ token++;
+ }
+ case orig_tqvalue:
+ if (token[strlen(token) - 1] != ')') {
+ line_invalid = 1;
+ } else {
+ token[strlen(token) - 1] = '\0';
+ tq = strtol(token, NULL, 10);
+ goto out;
+ }
+ break;
+ }
+
+ if (line_invalid)
+ break;
+ }
+ }
+
+out:
+ if (f)
+ fclose(f);
+ free(line);
+ return tq;
+}
diff --git a/util.c b/batadv_query.h
similarity index 60%
copy from util.c
copy to batadv_query.h
index 0d026b1..d4a3b79 100644
--- a/util.c
+++ b/batadv_query.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2012 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2006-2012 B.A.T.M.A.N. contributors:
*
- * Simon Wunderlich
+ * Simon Wunderlich, Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -18,18 +18,12 @@
* 02110-1301, USA
*
*/
+#ifndef _BATADV_QUERY_H
+#define _BATADV_QUERY_H
-#include <sys/time.h>
+#include <stdint.h>
-int time_diff(struct timeval *tv1, struct timeval *tv2,
- struct timeval *tvdiff) {
- tvdiff->tv_sec = tv1->tv_sec - tv2->tv_sec;
- if (tv1->tv_usec < tv2->tv_usec) {
- tvdiff->tv_usec = 1000000 + tv1->tv_usec - tv2->tv_usec;
- tvdiff->tv_sec -= 1;
- } else {
- tvdiff->tv_usec = tv1->tv_usec - tv2->tv_usec;
- }
+struct ether_addr *translate_mac(char *mesh_iface, struct ether_addr *mac);
+uint8_t get_tq(char *mesh_iface, struct ether_addr *mac);
- return (tvdiff->tv_sec >= 0);
-}
+#endif
diff --git a/debugfs.c b/debugfs.c
new file mode 100644
index 0000000..dc2218e
--- /dev/null
+++ b/debugfs.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2009 Clark Williams <williams(a)redhat.com>
+ * Copyright (C) 2009 Xiao Guangrong <xiaoguangrong(a)cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "debugfs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/vfs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef DEBUGFS_MAGIC
+#define DEBUGFS_MAGIC 0x64626720
+#endif
+
+static int debugfs_premounted;
+static char debugfs_mountpoint[MAX_PATH+1];
+
+static const char *debugfs_known_mountpoints[] = {
+ "/sys/kernel/debug/",
+ "/debug/",
+ NULL,
+};
+
+/* construct a full path to a debugfs element */
+int debugfs_make_path(const char *fmt, char *mesh_iface, char *buffer, int size)
+{
+ int len;
+
+ if (strlen(debugfs_mountpoint) == 0) {
+ buffer[0] = '\0';
+ return -1;
+ }
+
+ len = strlen(debugfs_mountpoint) + strlen(fmt) + 1;
+ if (len >= size)
+ return len+1;
+
+ snprintf(buffer, size-1, fmt, debugfs_mountpoint, mesh_iface);
+ buffer[size - 1] = '\0';
+ return 0;
+}
+
+static int debugfs_found;
+
+/* find the path to the mounted debugfs */
+const char *debugfs_find_mountpoint(void)
+{
+ const char **ptr;
+ char type[100];
+ FILE *fp;
+
+ if (debugfs_found)
+ return (const char *)debugfs_mountpoint;
+
+ ptr = debugfs_known_mountpoints;
+ while (*ptr) {
+ if (debugfs_valid_mountpoint(*ptr) == 0) {
+ debugfs_found = 1;
+ strcpy(debugfs_mountpoint, *ptr);
+ return debugfs_mountpoint;
+ }
+ ptr++;
+ }
+
+ /* give up and parse /proc/mounts */
+ fp = fopen("/proc/mounts", "r");
+ if (fp == NULL) {
+ fprintf(stderr,
+ "Error - can't open /proc/mounts for read: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ while (fscanf(fp, "%*s %"
+ STR(MAX_PATH)
+ "s %99s %*s %*d %*d\n",
+ debugfs_mountpoint, type) == 2) {
+ if (strcmp(type, "debugfs") == 0)
+ break;
+ }
+ fclose(fp);
+
+ if (strcmp(type, "debugfs") != 0)
+ return NULL;
+
+ debugfs_found = 1;
+
+ return debugfs_mountpoint;
+}
+
+/* verify that a mountpoint is actually a debugfs instance */
+
+int debugfs_valid_mountpoint(const char *debugfs)
+{
+ struct statfs st_fs;
+
+ if (statfs(debugfs, &st_fs) < 0)
+ return -ENOENT;
+ else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+ return -ENOENT;
+
+ return 0;
+}
+
+
+int debugfs_valid_entry(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st))
+ return -errno;
+
+ return 0;
+}
+
+/* mount the debugfs somewhere if it's not mounted */
+
+char *debugfs_mount(const char *mountpoint)
+{
+ /* see if it's already mounted */
+ if (debugfs_find_mountpoint()) {
+ debugfs_premounted = 1;
+ return debugfs_mountpoint;
+ }
+
+ /* if not mounted and no argument */
+ if (mountpoint == NULL)
+ mountpoint = "/sys/kernel/debug";
+
+ if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
+ return NULL;
+
+ /* save the mountpoint */
+ strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
+ debugfs_found = 1;
+
+ return debugfs_mountpoint;
+}
diff --git a/util.c b/debugfs.h
similarity index 50%
copy from util.c
copy to debugfs.h
index 0d026b1..3981b8b 100644
--- a/util.c
+++ b/debugfs.h
@@ -1,7 +1,6 @@
/*
- * Copyright (C) 2012 B.A.T.M.A.N. contributors:
- *
- * Simon Wunderlich
+ * Copyright (C) 2009 Clark Williams <williams(a)redhat.com>
+ * Copyright (C) 2009 Xiao Guangrong <xiaoguangrong(a)cn.fujitsu.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -19,17 +18,26 @@
*
*/
-#include <sys/time.h>
+#ifndef __DEBUGFS_H__
+#define __DEBUGFS_H__
+
+#include <sys/mount.h>
+#include <string.h>
+
+#ifndef MAX_PATH
+# define MAX_PATH 256
+#endif
+
+#ifndef STR
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#endif
-int time_diff(struct timeval *tv1, struct timeval *tv2,
- struct timeval *tvdiff) {
- tvdiff->tv_sec = tv1->tv_sec - tv2->tv_sec;
- if (tv1->tv_usec < tv2->tv_usec) {
- tvdiff->tv_usec = 1000000 + tv1->tv_usec - tv2->tv_usec;
- tvdiff->tv_sec -= 1;
- } else {
- tvdiff->tv_usec = tv1->tv_usec - tv2->tv_usec;
- }
+extern const char *debugfs_find_mountpoint(void);
+extern int debugfs_valid_mountpoint(const char *debugfs);
+extern int debugfs_valid_entry(const char *path);
+extern char *debugfs_mount(const char *mountpoint);
+extern int debugfs_make_path(const char *fmt, char *mesh_iface,
+ char *buffer, int size);
- return (tvdiff->tv_sec >= 0);
-}
+#endif /* __DEBUGFS_H__ */
diff --git a/recv.c b/recv.c
index 8ddf7ab..bbb6313 100644
--- a/recv.c
+++ b/recv.c
@@ -32,6 +32,7 @@
#include <linux/if_ether.h>
#include <linux/filter.h>
#include "alfred.h"
+#include "batadv_query.h"
int process_alfred_push_data(struct globals *globals, struct ethhdr *ethhdr,
struct alfred_packet *packet)
@@ -105,6 +106,7 @@ int process_alfred_announce_master(struct globals *globals,
struct alfred_packet *packet)
{
struct server *server;
+ struct ether_addr *macaddr;
if (packet->version != ALFRED_VERSION)
return -1;
@@ -124,8 +126,12 @@ int process_alfred_announce_master(struct globals *globals,
}
server->last_seen = time(NULL);
- server->tq = 255;
- /* TODO: update TQ */
+ macaddr = translate_mac(globals->interface,
+ (struct ether_addr *)server->address);
+ if (macaddr)
+ server->tq = get_tq(globals->interface, macaddr);
+ else
+ server->tq = 0;
if (globals->opmode == OPMODE_SLAVE)
set_best_server(globals);