Repository : ssh://git@open-mesh.org/alfred
On branch : master
commit 918c077f8b37072d39e34ad5f334ded35bb91fc8 Author: Sven Eckelmann sven@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@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@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@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@redhat.com + * Copyright (C) 2009 Xiao Guangrong xiaoguangrong@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);