The batman-adv device which was only usable for a single batX net device was replaced with a file in debugfs which can be used the same way as /dev/batman-adv before.
It seems that the debugfs has no 100% common mount path in current distributions and maybe isn't mounted at all. So before we try to access a batman file in debugfs, we have to search for the mountpoint in /proc/mounts and maybe mount it manually in /sys/kernel/debug.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- batctl/Makefile | 4 +- batctl/debugfs.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++ batctl/debugfs.h | 46 +++++++++ batctl/main.h | 2 +- batctl/ping.c | 21 +++- batctl/traceroute.c | 21 +++- 6 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 batctl/debugfs.c create mode 100644 batctl/debugfs.h
diff --git a/batctl/Makefile b/batctl/Makefile index db375f7..bc591da 100644 --- a/batctl/Makefile +++ b/batctl/Makefile @@ -39,8 +39,8 @@ SRC_FILES = "(.c)|(.h)|(Makefile)|(INSTALL)|(LIESMICH)|(README EXTRA_MODULES_C := bisect.c EXTRA_MODULES_H := bisect.h
-SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c $(EXTRA_MODULES_C) -SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h $(EXTRA_MODULES_H) +SRC_C = main.c bat-hosts.c functions.c sys.c ping.c traceroute.c tcpdump.c list-batman.c hash.c vis.c debugfs.c $(EXTRA_MODULES_C) +SRC_H = main.h bat-hosts.h functions.h sys.h ping.h traceroute.h tcpdump.h list-batman.h hash.h allocate.h vis.h debugfs.h $(EXTRA_MODULES_H) SRC_O = $(SRC_C:.c=.o)
PACKAGE_NAME = batctl diff --git a/batctl/debugfs.c b/batctl/debugfs.c new file mode 100644 index 0000000..cfe1254 --- /dev/null +++ b/batctl/debugfs.c @@ -0,0 +1,269 @@ +/* + * 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 <linux/magic.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/", + 0, +}; + +/* use this to force a umount */ +void debugfs_force_cleanup(void) +{ + debugfs_find_mountpoint(); + debugfs_premounted = 0; + debugfs_umount(); +} + +/* construct a full path to a debugfs element */ +int debugfs_make_path(const char *element, char *buffer, int size) +{ + int len; + + if (strlen(debugfs_mountpoint) == 0) { + buffer[0] = '\0'; + return -1; + } + + len = strlen(debugfs_mountpoint) + strlen(element) + 1; + if (len >= size) + return len+1; + + snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element); + 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) { + printf("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; +} + +/* umount the debugfs */ + +int debugfs_umount(void) +{ + char umountcmd[128]; + int ret; + + /* if it was already mounted, leave it */ + if (debugfs_premounted) + return 0; + + /* make sure it's a valid mount point */ + ret = debugfs_valid_mountpoint(debugfs_mountpoint); + if (ret) + return ret; + + snprintf(umountcmd, sizeof(umountcmd), + "/bin/umount %s", debugfs_mountpoint); + return system(umountcmd); +} + +int debugfs_write(const char *entry, const char *value) +{ + char path[MAX_PATH+1]; + int ret, count; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* get how many chars we're going to write */ + count = strlen(value); + + /* open the debugfs entry */ + fd = open(path, O_RDWR); + if (fd < 0) + return -errno; + + while (count > 0) { + /* write it */ + ret = write(fd, value, count); + if (ret <= 0) { + if (ret == EAGAIN) + continue; + close(fd); + return -errno; + } + count -= ret; + } + + /* close it */ + close(fd); + + /* return success */ + return 0; +} + +/* + * read a debugfs entry + * returns the number of chars read or a negative errno + */ +int debugfs_read(const char *entry, char *buffer, size_t size) +{ + char path[MAX_PATH+1]; + int ret; + int fd; + + /* construct the path */ + snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry); + + /* verify that it exists */ + ret = debugfs_valid_entry(path); + if (ret) + return ret; + + /* open the debugfs entry */ + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + do { + /* read it */ + ret = read(fd, buffer, size); + if (ret == 0) { + close(fd); + return EOF; + } + } while (ret < 0 && errno == EAGAIN); + + /* close it */ + close(fd); + + /* make *sure* there's a null character at the end */ + buffer[ret] = '\0'; + + /* return the number of chars read */ + return ret; +} diff --git a/batctl/debugfs.h b/batctl/debugfs.h new file mode 100644 index 0000000..45f6339 --- /dev/null +++ b/batctl/debugfs.h @@ -0,0 +1,46 @@ +/* + * 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 + * + */ + +#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 + +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_umount(void); +extern int debugfs_write(const char *entry, const char *value); +extern int debugfs_read(const char *entry, char *buffer, size_t size); +extern void debugfs_force_cleanup(void); +extern int debugfs_make_path(const char *element, char *buffer, int size); + +#endif /* __DEBUGFS_H__ */ diff --git a/batctl/main.h b/batctl/main.h index 9c83a7e..2fe603e 100644 --- a/batctl/main.h +++ b/batctl/main.h @@ -23,4 +23,4 @@
#define SOURCE_VERSION "0.3.0-alpha" /*put exactly one distinct word inside the string like "0.3-pre-alpha" or "0.3-rc1" or "0.3" */
-#define BAT_DEVICE "/dev/batman-adv" +#define SOCKET_PATH "batman_adv/bat0/socket" diff --git a/batctl/ping.c b/batctl/ping.c index 0352870..9df5c07 100644 --- a/batctl/ping.c +++ b/batctl/ping.c @@ -35,6 +35,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
char is_aborted = 0; @@ -79,6 +80,8 @@ int ping(int argc, char **argv) float min = 0.0, max = 0.0, avg = 0.0; uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN]; size_t packet_len; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) { switch (optchar) { @@ -139,11 +142,19 @@ int ping(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler);
- ping_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + ping_fd = open(icmp_socket, O_RDWR);
if (ping_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -177,7 +188,7 @@ int ping(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
@@ -207,7 +218,7 @@ int ping(int argc, char **argv) read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); goto sleep; }
diff --git a/batctl/traceroute.c b/batctl/traceroute.c index b9b838e..00fcd89 100644 --- a/batctl/traceroute.c +++ b/batctl/traceroute.c @@ -34,6 +34,7 @@ #include "functions.h" #include "packet.h" #include "bat-hosts.h" +#include "debugfs.h"
#define TTL_MAX 50 @@ -59,6 +60,8 @@ int traceroute(int argc, char **argv) int ret = EXIT_FAILURE, res, trace_fd = 0, i; int found_args = 1, optchar, seq_counter = 0, read_opt = USE_BAT_HOSTS; double time_delta; + char *debugfs_mnt; + char icmp_socket[MAX_PATH+1];
while ((optchar = getopt(argc, argv, "hn")) != -1) { switch (optchar) { @@ -99,11 +102,19 @@ int traceroute(int argc, char **argv)
mac_string = ether_ntoa_long(dst_mac);
- trace_fd = open(BAT_DEVICE, O_RDWR); + debugfs_mnt = debugfs_mount(NULL); + if (!debugfs_mnt) { + printf("Error - can't mount or find debugfs\n"); + goto out; + } + + debugfs_make_path(SOCKET_PATH, icmp_socket, sizeof(icmp_socket)); + + trace_fd = open(icmp_socket, O_RDWR);
if (trace_fd < 0) { - printf("Error - can't open a connection to the batman adv kernel module via the device '%s': %s\n", - BAT_DEVICE, strerror(errno)); + printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n", + icmp_socket, strerror(errno)); printf("Check whether the module is loaded and active.\n"); goto out; } @@ -123,7 +134,7 @@ int traceroute(int argc, char **argv) icmp_packet_out.seqno = htons(++seq_counter);
if (write(trace_fd, (char *)&icmp_packet_out, sizeof(icmp_packet_out)) < 0) { - printf("Error - can't write to batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }
@@ -149,7 +160,7 @@ int traceroute(int argc, char **argv) read_len = read(trace_fd, (char *)&icmp_packet_in, sizeof(icmp_packet_in));
if (read_len < 0) { - printf("Error - can't read from batman adv kernel file '%s': %s\n", BAT_DEVICE, strerror(errno)); + printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno)); continue; }