diff options
Diffstat (limited to 'ffvisd/ffvisd.c')
-rw-r--r-- | ffvisd/ffvisd.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/ffvisd/ffvisd.c b/ffvisd/ffvisd.c index dc79d60..309fad2 100644 --- a/ffvisd/ffvisd.c +++ b/ffvisd/ffvisd.c @@ -1,5 +1,171 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _GNU_SOURCE + +#include <stdarg.h> +#include <stdbool.h> #include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <net/if.h> + + +#define ANNOUNCE_INTERVAL 20 +#define ANNOUNCE_TIMEOUT 60 + +#define SYSFS_PATH_MAX 256 +#define SYSFS_CLASS_NET "/sys/class/net" + + +//static char *mesh = "bat0"; + + +typedef struct _ffvisd_eth_address_t { + uint8_t address[6]; +} ffvisd_eth_address_t; + +typedef struct _ffvisd_ipv6_host_address_t { + uint8_t address[8]; +} ffvisd_ipv6_host_address_t; + +typedef struct _ffvisd_server_announce_t { + ffvisd_eth_address_t eth_address; + uint16_t reserved; + ffvisd_ipv6_host_address_t address; + uint32_t age; +} ffvisd_server_announce_t; + +typedef struct _ffvisd_announce_t { + uint32_t magic; + uint32_t version; + uint32_t n_servers; + uint32_t reserved; + ffvisd_server_announce_t servers[]; +} ffvisd_announce_t; + +typedef struct _ffvisd_iface_t { + unsigned ifindex; + unsigned iftype; + char *ifname; + char *mesh_iface; +} ffvisd_iface_t; + + +typedef void (*iface_cb)(const ffvisd_iface_t *iface, void *arg); + + +void ffvisd_iface_free(ffvisd_iface_t *iface); + + +bool file_readv(const char *file, const char *format, va_list ap) { + FILE *f = fopen(file, "r"); + if (!f) + return false; + + int ret = vfscanf(f, format, ap); + + fclose(f); + + return (ret > 0); +} + +bool iface_file_read(const char *ifname, const char *file, const char *format, ...) { + char filename[SYSFS_PATH_MAX]; + + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/%s", ifname, file); + + va_list ap; + va_start(ap, format); + bool ret = file_readv(filename, format, ap); + va_end(ap); + + return ret; +} + +ffvisd_iface_t* ffvisd_iface_new(const char *ifname) { + ffvisd_iface_t *iface = calloc(1, sizeof(ffvisd_iface_t)); + + iface->ifname = strdup(ifname); + + if (!iface_file_read(ifname, "ifindex", "%u", &iface->ifindex)) { + ffvisd_iface_free(iface); + return NULL; + } + + if (!iface_file_read(ifname, "batman_adv/mesh_iface", "%as", &iface->mesh_iface) || !strcmp(iface->mesh_iface, "none")) { + free(iface->mesh_iface); + iface->mesh_iface = NULL; + } + + return iface; +} + +void ffvisd_iface_free(ffvisd_iface_t *iface) { + if (iface) { + free(iface->ifname); + free(iface->mesh_iface); + free(iface); + } +} + +void ffvisd_iface_foreach(iface_cb cb, void *arg) { + struct dirent **namelist; + + int i, count = scandir(SYSFS_CLASS_NET, &namelist, NULL, NULL); + + if (count < 0) { + fprintf(stderr, "error: scandir: %m"); + return; + } + + for (i = 0; i < count; i++) { + ffvisd_iface_t *iface = ffvisd_iface_new(namelist[i]->d_name); + + if (iface) + cb(iface, arg); + + ffvisd_iface_free(iface); + free(namelist[i]); + } + + free(namelist); +} + + +void pr_iface_info(const ffvisd_iface_t *iface, void *arg) { + printf("Interface %s: ifindex=%i mesh_iface=%s iftype=%i\n", iface->ifname, iface->ifindex, iface->mesh_iface, iface->iftype); +} + int main() { + ffvisd_iface_foreach(pr_iface_info, NULL); + return 0; } |