2012-08-28 02:46:34 +02:00
|
|
|
/*
|
|
|
|
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>
|
2012-08-23 17:43:26 +02:00
|
|
|
#include <stdio.h>
|
2012-08-28 02:46:34 +02:00
|
|
|
#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);
|
|
|
|
}
|
|
|
|
|
2012-08-23 17:43:26 +02:00
|
|
|
|
|
|
|
int main() {
|
2012-08-28 02:46:34 +02:00
|
|
|
ffvisd_iface_foreach(pr_iface_info, NULL);
|
|
|
|
|
2012-08-23 17:43:26 +02:00
|
|
|
return 0;
|
|
|
|
}
|