Unverified Commit d3d2204e authored by Matthias Schiffer's avatar Matthias Schiffer Committed by GitHub

Merge pull request #1879 from freifunk-gluon/respondd-cleanup

gluon-mesh-* respondd cleanup (part 1?)
parents 7220c596 ecc29e0b
......@@ -25,7 +25,7 @@ LDFLAGS_JSONC = $(shell pkg-config --libs json-c)
respondd.so: respondd.c handle_neighbour.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared $(LDFLAGS_JSONC) -o $@ $^ -lgluonutil -lblobmsg_json -lubox -lubus -liwinfo -luci
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared $(LDFLAGS_JSONC) -o $@ $^ -lgluonutil -lblobmsg_json -lubox -lubus -luci
neighbours-babel: neighbours-babel.c handle_neighbour.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_JSONC) $(LDFLAGS) $(LDLIBS) $(LDFLAGS_JSONC) -o $@ $^
......@@ -26,17 +26,15 @@
#include <respondd.h>
#include <iwinfo.h>
#include <json-c/json.h>
#include <libgluonutil.h>
#include <uci.h>
#include <alloca.h>
#include <glob.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
......@@ -49,33 +47,18 @@
#include <sys/un.h>
#include <ifaddrs.h>
#include <linux/ethtool.h>
#include <linux/if_addr.h>
#include <linux/sockios.h>
#include <netdb.h>
#include "errno.h"
#include <errno.h>
#include <libbabelhelper/babelhelper.h>
#include <libubox/blobmsg_json.h>
#include "libubus.h"
#define _STRINGIFY(s) #s
#define STRINGIFY(s) _STRINGIFY(s)
#include <stdlib.h>
#define MAX_INACTIVITY 60000
#include <libubus.h>
#define SOCKET_INPUT_BUFFER_SIZE 255
#define BABEL_PORT 33123
#define VPN_INTERFACE "mesh-vpn"
#define l3rdctl "/var/run/l3roamd.sock"
#define IFNAMELEN 32
#define PROTOLEN 32
#define UBUS_TIMEOUT 30
#define UBUS_SOCKET "/var/run/ubus.sock"
#define UBUS_TIMEOUT 30000
static struct babelhelper_ctx bhelper_ctx = {};
......@@ -258,9 +241,9 @@ static void blobmsg_handle_element(struct blob_attr *attr, bool head, char **ifn
switch (blob_id(attr)) {
case BLOBMSG_TYPE_STRING:
if (!strncmp(blobmsg_name(attr),"device", 6)) {
if (!strncmp(blobmsg_name(attr), "device", 6)) {
free(*ifname);
*ifname = strndup(data, IFNAMELEN);
*ifname = strndup(data, IF_NAMESIZE);
} else if (!strncmp(blobmsg_name(attr), "proto", 5)) {
free(*proto);
*proto = strndup(data, PROTOLEN);
......@@ -330,7 +313,7 @@ static struct json_object * get_mesh_ifs() {
unsigned int id=8;
ubus_ctx = ubus_connect(UBUS_SOCKET);
ubus_ctx = ubus_connect(NULL);
if (!ubus_ctx) {
fprintf(stderr,"could not connect to ubus, not providing mesh-data\n");
goto end;
......@@ -338,7 +321,7 @@ static struct json_object * get_mesh_ifs() {
blob_buf_init(&b, 0);
ubus_lookup_id(ubus_ctx, "network.interface", &id);
int uret = ubus_invoke(ubus_ctx, id, "dump", b.head, receive_call_result_data, &ret, UBUS_TIMEOUT * 1000);
int uret = ubus_invoke(ubus_ctx, id, "dump", b.head, receive_call_result_data, &ret, UBUS_TIMEOUT);
if (uret > 0)
fprintf(stderr, "ubus command failed: %s\n", ubus_strerror(uret));
......@@ -386,34 +369,40 @@ static struct json_object * respondd_provider_nodeinfo(void) {
return ret;
}
static uint64_t getnumber(const char *ifname, const char *stat) {
static struct json_object * read_number(const char *ifname, const char *stat) {
const char *format = "/sys/class/net/%s/statistics/%s";
struct json_object *ret = NULL;
int64_t i;
char path[strlen(format) + strlen(ifname) + strlen(stat) + 1];
snprintf(path, sizeof(path), format, ifname, stat);
if (! access(path, F_OK)) {
char *line=gluonutil_read_line(path);
long long i = atoll(line);
free(line);
return(i);
}
return 0;
FILE *f = fopen(path, "r");
if (!f)
return NULL;
if (fscanf(f, "%"SCNd64, &i) == 1)
ret = json_object_new_int64(i);
fclose(f);
return ret;
}
static struct json_object * get_traffic(void) {
char ifname[16];
strncpy(ifname, "br-client", 16);
const char *ifname = "br-client";
struct json_object *ret = NULL;
struct json_object *rx = json_object_new_object();
struct json_object *tx = json_object_new_object();
json_object_object_add(rx, "packets", json_object_new_int64(getnumber(ifname, "rx_packets")));
json_object_object_add(rx, "bytes", json_object_new_int64(getnumber(ifname, "rx_bytes")));
json_object_object_add(rx, "dropped", json_object_new_int64(getnumber(ifname, "rx_dropped")));
json_object_object_add(tx, "packets", json_object_new_int64(getnumber(ifname, "tx_packets")));
json_object_object_add(tx, "dropped", json_object_new_int64(getnumber(ifname, "tx_dropped")));
json_object_object_add(tx, "bytes", json_object_new_int64(getnumber(ifname, "tx_bytes")));
json_object_object_add(rx, "packets", read_number(ifname, "rx_packets"));
json_object_object_add(rx, "bytes", read_number(ifname, "rx_bytes"));
json_object_object_add(rx, "dropped", read_number(ifname, "rx_dropped"));
json_object_object_add(tx, "packets", read_number(ifname, "tx_packets"));
json_object_object_add(tx, "dropped", read_number(ifname, "tx_dropped"));
json_object_object_add(tx, "bytes", read_number(ifname, "tx_bytes"));
ret = json_object_new_object();
json_object_object_add(ret, "rx", rx);
......@@ -422,72 +411,6 @@ static struct json_object * get_traffic(void) {
return ret;
}
static void count_iface_stations(size_t *wifi24, size_t *wifi5, const char *ifname) {
const struct iwinfo_ops *iw = iwinfo_backend(ifname);
if (!iw)
return;
int freq;
if (iw->frequency(ifname, &freq) < 0)
return;
size_t *wifi;
if (freq >= 2400 && freq < 2500)
wifi = wifi24;
else if (freq >= 5000 && freq < 6000)
wifi = wifi5;
else
return;
int len;
char buf[IWINFO_BUFSIZE];
if (iw->assoclist(ifname, buf, &len) < 0)
return;
struct iwinfo_assoclist_entry *entry;
for (entry = (struct iwinfo_assoclist_entry *)buf; (char*)(entry+1) <= buf + len; entry++) {
if (entry->inactive > MAX_INACTIVITY)
continue;
(*wifi)++;
}
}
static void count_stations(size_t *wifi24, size_t *wifi5) {
struct uci_context *ctx = uci_alloc_context();
ctx->flags &= ~UCI_FLAG_STRICT;
struct uci_package *p;
if (uci_load(ctx, "wireless", &p))
goto end;
struct uci_element *e;
uci_foreach_element(&p->sections, e) {
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "wifi-iface"))
continue;
const char *network = uci_lookup_option_string(ctx, s, "network");
if (!network || strcmp(network, "client"))
continue;
const char *mode = uci_lookup_option_string(ctx, s, "mode");
if (!mode || strcmp(mode, "ap"))
continue;
const char *ifname = uci_lookup_option_string(ctx, s, "ifname");
if (!ifname)
continue;
count_iface_stations(wifi24, wifi5, ifname);
}
end:
uci_free_context(ctx);
}
static bool handle_route_addgw_nexthop(char **data, void *arg) {
struct json_object *obj = (struct json_object*) arg;
if (data[PREFIX] && data[FROM] && data[VIA] && data[IF]) {
......@@ -569,21 +492,12 @@ end:
}
static struct json_object * get_clients(void) {
size_t wifi24 = 0, wifi5 = 0;
count_stations(&wifi24, &wifi5);
int total = ask_l3roamd_for_client_count();
size_t wifi = wifi24 + wifi5;
struct json_object *ret = json_object_new_object();
int total = ask_l3roamd_for_client_count();
if (total >= 0)
json_object_object_add(ret, "total", json_object_new_int(total));
json_object_object_add(ret, "wifi", json_object_new_int(wifi));
json_object_object_add(ret, "wifi24", json_object_new_int(wifi24));
json_object_object_add(ret, "wifi5", json_object_new_int(wifi5));
return ret;
}
......@@ -598,89 +512,6 @@ static struct json_object * respondd_provider_statistics(void) {
return ret;
}
static struct json_object * get_wifi_neighbours(const char *ifname) {
const struct iwinfo_ops *iw = iwinfo_backend(ifname);
if (!iw)
return NULL;
int len;
char buf[IWINFO_BUFSIZE];
if (iw->assoclist(ifname, buf, &len) < 0)
return NULL;
struct json_object *neighbours = json_object_new_object();
struct iwinfo_assoclist_entry *entry;
for (entry = (struct iwinfo_assoclist_entry *)buf; (char*)(entry+1) <= buf + len; entry++) {
if (entry->inactive > MAX_INACTIVITY)
continue;
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "signal", json_object_new_int(entry->signal));
json_object_object_add(obj, "noise", json_object_new_int(entry->noise));
json_object_object_add(obj, "inactive", json_object_new_int(entry->inactive));
char mac[18];
snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
entry->mac[0], entry->mac[1], entry->mac[2],
entry->mac[3], entry->mac[4], entry->mac[5]);
json_object_object_add(neighbours, mac, obj);
}
struct json_object *ret = json_object_new_object();
if (json_object_object_length(neighbours))
json_object_object_add(ret, "neighbours", neighbours);
else
json_object_put(neighbours);
return ret;
}
static struct json_object * get_wifi(void) {
struct uci_context *ctx = uci_alloc_context();
ctx->flags &= ~UCI_FLAG_STRICT;
struct json_object *ret = json_object_new_object();
struct uci_package *p;
if (uci_load(ctx, "network", &p))
goto end;
struct uci_element *e;
uci_foreach_element(&p->sections, e) {
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "interface"))
continue;
const char *proto = uci_lookup_option_string(ctx, s, "proto");
if (!proto || strcmp(proto, "gluon_mesh"))
continue;
const char *ifname = uci_lookup_option_string(ctx, s, "ifname");
if (!ifname)
continue;
char *ifaddr = gluonutil_get_interface_address(ifname);
if (!ifaddr)
continue;
struct json_object *neighbours = get_wifi_neighbours(ifname);
if (neighbours)
json_object_object_add(ret, ifaddr, neighbours);
free(ifaddr);
}
end:
uci_free_context(ctx);
return ret;
}
static struct json_object * respondd_provider_neighbours(void) {
struct json_object *ret = json_object_new_object();
......@@ -689,10 +520,6 @@ static struct json_object * respondd_provider_neighbours(void) {
json_object_object_add(ret, "babel", babel);
struct json_object *wifi = get_wifi();
if (wifi)
json_object_object_add(ret, "wifi", wifi);
return ret;
}
......
......@@ -31,5 +31,8 @@ endif
CFLAGS += $(LIBBATADV_CFLAGS)
LDLIBS += $(LIBBATADV_LDLIBS)
respondd.so: respondd.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -liwinfo -luci
SOURCES = respondd.c respondd-nodeinfo.c respondd-statistics.c respondd-neighbours.c
respondd.so: $(SOURCES) respondd-common.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -fvisibility=hidden -D_GNU_SOURCE -o $@ $(SOURCES) $(LDLIBS) -lgluonutil
/*
Copyright (c) 2016-2019, 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.
*/
#pragma once
struct json_object * respondd_provider_nodeinfo(void);
struct json_object * respondd_provider_statistics(void);
struct json_object * respondd_provider_neighbours(void);
/*
Copyright (c) 2016-2019, 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.
*/
#include "respondd-common.h"
#include <batadv-genl.h>
#include <libgluonutil.h>
#include <json-c/json.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
struct neigh_netlink_opts {
struct json_object *interfaces;
struct batadv_nlquery_opts query_opts;
};
static struct json_object * ifnames2addrs(struct json_object *interfaces) {
struct json_object *ret = json_object_new_object();
json_object_object_foreach(interfaces, ifname, interface) {
char *ifaddr = gluonutil_get_interface_address(ifname);
if (!ifaddr)
continue;
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "neighbours", json_object_get(interface));
json_object_object_add(ret, ifaddr, obj);
free(ifaddr);
}
json_object_put(interfaces);
return ret;
}
static const enum batadv_nl_attrs parse_orig_list_mandatory[] = {
BATADV_ATTR_ORIG_ADDRESS,
BATADV_ATTR_NEIGH_ADDRESS,
BATADV_ATTR_TQ,
BATADV_ATTR_HARD_IFINDEX,
BATADV_ATTR_LAST_SEEN_MSECS,
};
static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg)
{
struct nlattr *attrs[BATADV_ATTR_MAX+1];
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct batadv_nlquery_opts *query_opts = arg;
struct genlmsghdr *ghdr;
uint8_t *orig;
uint8_t *dest;
uint8_t tq;
uint32_t hardif;
uint32_t lastseen;
char ifname_buf[IF_NAMESIZE], *ifname;
struct neigh_netlink_opts *opts;
char mac1[18];
opts = batadv_container_of(query_opts, struct neigh_netlink_opts,
query_opts);
if (!genlmsg_valid_hdr(nlh, 0))
return NL_OK;
ghdr = nlmsg_data(nlh);
if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS)
return NL_OK;
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
genlmsg_len(ghdr), batadv_genl_policy))
return NL_OK;
if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory,
BATADV_ARRAY_SIZE(parse_orig_list_mandatory)))
return NL_OK;
orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]);
dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]);
tq = nla_get_u8(attrs[BATADV_ATTR_TQ]);
hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]);
lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]);
if (memcmp(orig, dest, 6) != 0)
return NL_OK;
ifname = if_indextoname(hardif, ifname_buf);
if (!ifname)
return NL_OK;
sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x",
orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]);
struct json_object *obj = json_object_new_object();
if (!obj)
return NL_OK;
struct json_object *interface;
if (!json_object_object_get_ex(opts->interfaces, ifname, &interface)) {
interface = json_object_new_object();
json_object_object_add(opts->interfaces, ifname, interface);
}
json_object_object_add(obj, "tq", json_object_new_int(tq));
json_object_object_add(obj, "lastseen", json_object_new_double(lastseen / 1000.));
json_object_object_add(obj, "best", json_object_new_boolean(!!attrs[BATADV_ATTR_FLAG_BEST]));
json_object_object_add(interface, mac1, obj);
return NL_OK;
}
static struct json_object * get_batadv(void) {
struct neigh_netlink_opts opts = {
.query_opts = {
.err = 0,
},
};
int ret;
opts.interfaces = json_object_new_object();
if (!opts.interfaces)
return NULL;
ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS,
parse_orig_list_netlink_cb, NLM_F_DUMP,
&opts.query_opts);
if (ret < 0) {
json_object_put(opts.interfaces);
return NULL;
}
return ifnames2addrs(opts.interfaces);
}
struct json_object * respondd_provider_neighbours(void) {
struct json_object *ret = json_object_new_object();
struct json_object *batadv = get_batadv();
if (batadv)
json_object_object_add(ret, "batadv", batadv);
return ret;
}
/*
Copyright (c) 2016-2019, 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.
*/
#include "respondd-common.h"
#include <libgluonutil.h>
#include <json-c/json.h>
#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <glob.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_addr.h>
#include <linux/rtnetlink.h>
struct ip_address_information {
unsigned int ifindex;
struct json_object *addresses;
};
static int get_addresses_cb(struct nl_msg *msg, void *arg) {
struct ip_address_information *info = (struct ip_address_information*) arg;
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct ifaddrmsg *msg_content = NLMSG_DATA(nlh);
int remaining = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));