diff options
Diffstat (limited to 'ffvisd')
-rw-r--r-- | ffvisd/ffvisd.c | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/ffvisd/ffvisd.c b/ffvisd/ffvisd.c index 309fad2..a169e89 100644 --- a/ffvisd/ffvisd.c +++ b/ffvisd/ffvisd.c @@ -26,15 +26,21 @@ #define _GNU_SOURCE +#include <libgen.h> #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 <unistd.h> + +#include <net/ethernet.h> #include <net/if.h> +#include <net/if_arp.h> + +#include <sys/types.h> +#include <sys/stat.h> #define ANNOUNCE_INTERVAL 20 @@ -43,12 +49,15 @@ #define SYSFS_PATH_MAX 256 #define SYSFS_CLASS_NET "/sys/class/net" +#define FFD_MAGIC 0xffd +#define FFVISD_VERSION 0 + //static char *mesh = "bat0"; typedef struct _ffvisd_eth_address_t { - uint8_t address[6]; + uint8_t address[ETH_ALEN]; } ffvisd_eth_address_t; typedef struct _ffvisd_ipv6_host_address_t { @@ -63,20 +72,39 @@ typedef struct _ffvisd_server_announce_t { } ffvisd_server_announce_t; typedef struct _ffvisd_announce_t { - uint32_t magic; - uint32_t version; + uint16_t magic; + uint16_t version; uint32_t n_servers; uint32_t reserved; ffvisd_server_announce_t servers[]; } ffvisd_announce_t; +typedef enum _ffvisd_iftype_t { + IF_UNKNOWN = 0, + IF_WIRED, + IF_WIRELESS, + IF_VIRTUAL, + IF_BRIDGE, + IF_MESH, + IF_MAX +} ffvisd_iftype_t; + typedef struct _ffvisd_iface_t { unsigned ifindex; - unsigned iftype; + ffvisd_iftype_t iftype; char *ifname; + char *bridge_iface; char *mesh_iface; } ffvisd_iface_t; +static const char *ffvisd_iftype_names[IF_MAX] = { + [IF_UNKNOWN] = "unknown", + [IF_WIRED] = "wired", + [IF_WIRELESS] = "wireless", + [IF_VIRTUAL] = "virtual", + [IF_BRIDGE] = "bridge", + [IF_MESH] = "mesh", +}; typedef void (*iface_cb)(const ffvisd_iface_t *iface, void *arg); @@ -109,58 +137,88 @@ bool iface_file_read(const char *ifname, const char *file, const char *format, . return ret; } -ffvisd_iface_t* ffvisd_iface_new(const char *ifname) { - ffvisd_iface_t *iface = calloc(1, sizeof(ffvisd_iface_t)); +bool iface_file_exists(const char *ifname, const char *file) { + char filename[SYSFS_PATH_MAX]; - iface->ifname = strdup(ifname); + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/%s", ifname, file); - if (!iface_file_read(ifname, "ifindex", "%u", &iface->ifindex)) { - ffvisd_iface_free(iface); + struct stat st; + return (stat(filename, &st) == 0); +} + +char* get_bridge(const char *ifname) { + char filename[SYSFS_PATH_MAX], filename2[SYSFS_PATH_MAX] = {0}; + + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/brport/bridge", ifname); + if (readlink(filename, filename2, sizeof(filename2)) < 0) return NULL; - } + + return strdup(basename(filename2)); +} + +ffvisd_iface_t* ffvisd_iface_new(const char *ifname, unsigned ifindex) { + ffvisd_iface_t *iface = calloc(1, sizeof(ffvisd_iface_t)); + + iface->ifname = strdup(ifname); + iface->ifindex = ifindex; 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; } + iface->bridge_iface = get_bridge(ifname); + + int type; + if (iface_file_read(ifname, "type", "%i", &type) && type == ARPHRD_ETHER) { + if(iface_file_exists(ifname, "mesh")) + iface->iftype = IF_MESH; + else if(iface_file_exists(ifname, "bridge")) + iface->iftype = IF_BRIDGE; + else if(iface_file_exists(ifname, "tun_flags")) + iface->iftype = IF_VIRTUAL; + else if(iface_file_exists(ifname, "wireless")) + iface->iftype = IF_WIRELESS; + else + iface->iftype = IF_WIRED; + } + return iface; } void ffvisd_iface_free(ffvisd_iface_t *iface) { if (iface) { free(iface->ifname); + free(iface->bridge_iface); 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); + struct if_nameindex *ifaces = if_nameindex(); - if (count < 0) { - fprintf(stderr, "error: scandir: %m"); + if (!ifaces) { + fprintf(stderr, "error: if_nameindex: %m"); return; } - for (i = 0; i < count; i++) { - ffvisd_iface_t *iface = ffvisd_iface_new(namelist[i]->d_name); + int i; + for (i = 0; ifaces[i].if_name; i++) { + ffvisd_iface_t *iface = ffvisd_iface_new(ifaces[i].if_name, ifaces[i].if_index); if (iface) cb(iface, arg); ffvisd_iface_free(iface); - free(namelist[i]); } - free(namelist); + if_freenameindex(ifaces); } 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); + printf("Interface %s: ifindex=%i bridge_iface=%s mesh_iface=%s iftype=%s\n", iface->ifname, iface->ifindex, iface->bridge_iface, iface->mesh_iface, ffvisd_iftype_names[iface->iftype]); } |